-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gestures don't work on Label Spans #4734
Comments
Reproduced on Windows(OS: 19044.1526) and Android(OS: Android 12.0-API31). |
Confirmed - #6257 is a duplicate of this issue. Added to the 6.0.300 milestone and self-assigned by PureWeen - thanks. |
This issue persists. ETA on the fix? |
Still not working on Windows. This is a real pain. I need to be able to allow users to click on a link in formatted text. Clicking 'anywhere' on the text, as in the workarounds above, is not much use. Any news on when this is going to be fixed? Not holding my breath.... |
Still not working on iOS... using a label link instead WORKS sure but it can be pretty janky alignment-wise so span links are preferred, only they don't work in iOS. I hope someone is looking at this still! |
@RedZone908 @riccardominato @WhoeverReadsThisIsStupid @mobilewares @donatellijl12 to anyone who needs a fix right now on iOS, you can fix the label handler by adding this class and overwrite default Handler it as part of ConfigureMauiHandlers
This adds code from #15544 and you can use TapGestureRecognizer on spans. As soon as PR will be fixed you can delete code above and remove the registration you added |
@artemvalieiev this worked! Thank you so much! However, for other potential users - @riccardominato @WhoeverReadsThisIsStupid @mobilewares @donatellijl12 - be aware that you must enclose the entire |
I have found a workaround and it is working .net 7 Xaml: For android and iOS <Label>
<Label.GestureRecognizers>
<TapGestureRecognizer/>
</Label.GestureRecognizers>
<Label.FormattedText>
<FormattedString>
<Span Text="First"/>
<Span Text="Click here">
<Span.GestureRecognizers>
<TapGestureRecognizer/>
</Span.GestureRecognizers>
</Span>
<Span Text="last"/>
</FormattedString>
</Label.FormattedText>
</Label> ios handler public class LabelhandlerEx : LabelHandler
{
protected override void ConnectHandler(MauiLabel platformView)
{
base.ConnectHandler(platformView);
if(VirtualView is Label label)
{
label.SizeChanged += Label_SizeChanged;
}
}
private void Label_SizeChanged(object sender, EventArgs e)
{
PlatformView.RecalculateSpanPositions((Label)VirtualView);
}
}
internal static class LabelExtensions
{
public static void RecalculateSpanPositions(this NativeLabel control, Label element)
{
if (element == null)
return;
if (element.TextType == TextType.Html)
return;
if (element?.FormattedText?.Spans == null
|| element.FormattedText.Spans.Count == 0)
return;
var finalSize = control.Frame;
if (finalSize.Width <= 0 || finalSize.Height <= 0)
return;
var inline = control.AttributedText;
var range = new NSRange(0, inline.Length);
NSTextStorage textStorage = new NSTextStorage();
textStorage.SetString(inline);
var layoutManager = new NSLayoutManager();
textStorage.AddLayoutManager(layoutManager);
var textContainer = new NSTextContainer(size: finalSize.Size)
{
LineFragmentPadding = 0
};
layoutManager.AddTextContainer(textContainer);
var labelWidth = finalSize.Width;
var currentLocation = 0;
for (int i = 0; i < element.FormattedText.Spans.Count; i++)
{
var span = element.FormattedText.Spans[i];
var location = currentLocation;
var length = span.Text?.Length ?? 0;
if (length == 0)
continue;
var startRect = GetCharacterBounds(new NSRange(location, 1), layoutManager, textContainer);
var endRect = GetCharacterBounds(new NSRange(location + length, 1), layoutManager, textContainer);
var startLineHeight = startRect.Bottom - startRect.Top;
var endLineHeight = endRect.Bottom - endRect.Top;
var defaultLineHeight = control.FindDefaultLineHeight(location, length);
var yaxis = startRect.Top;
var lineHeights = new List<double>();
while ((endRect.Bottom - yaxis) > 0.001)
{
double lineHeight;
if (yaxis == startRect.Top) // First Line
{
lineHeight = startRect.Bottom - startRect.Top;
}
else if (yaxis != endRect.Top) // Middle Line(s)
{
lineHeight = defaultLineHeight;
}
else // Bottom Line
{
lineHeight = endRect.Bottom - endRect.Top;
}
lineHeights.Add(lineHeight);
yaxis += (float)lineHeight;
}
((ISpatialElement)span).Region = Region.FromLines(lineHeights.ToArray(), finalSize.Width, startRect.X, endRect.X, startRect.Top).Inflate(10);
// update current location
currentLocation += length;
}
}
static CGRect GetCharacterBounds(NSRange characterRange, NSLayoutManager layoutManager, NSTextContainer textContainer)
{
var glyphRange = new NSRange();
layoutManager.GetCharacterRange(characterRange, out glyphRange);
return layoutManager.GetBoundingRect(glyphRange, textContainer);
}
static double FindDefaultLineHeight(this NativeLabel control, int start, int length)
{
if (length == 0)
return 0.0;
var textStorage = new NSTextStorage();
textStorage.SetString(control.AttributedText.Substring(start, length));
var layoutManager = new NSLayoutManager();
textStorage.AddLayoutManager(layoutManager);
var textContainer = new NSTextContainer(size: new SizeF(float.MaxValue, float.MaxValue))
{
LineFragmentPadding = 0
};
layoutManager.AddTextContainer(textContainer);
var rect = GetCharacterBounds(new NSRange(0, 1), layoutManager, textContainer);
return rect.Bottom - rect.Top;
}
}
} |
@psatheesh18 yep, that's basically the same code @artemvalieiev shared above, the advance version of the fix that will eventually be applied officially in apparently .NET 8 SR3 |
Does someone has a fix for the Windows app when working with Label Spans hyperlink? This #17731 never got merged |
Are you really closing this issue without fixing the Windows part? At least give a response to the users and explain the reasons behind the decision... |
@nicop85 sorry about that, the bot is very persistent. But, it better watch out because we will replace it with AI. |
I have found a workaround for Windows (#17731 ). Based on the changes made in that issue and the response of @artemvalieiev, I've played around to finally get to something that works. It is not perfect and there are some scenarios where the triggering area is bigger than expected (specially if the clickable span has a line break), but at least for me its better than something that doesn't do anything :) In the MauiProgram.cs you will have to add
And then add this class to your project
Hope it helps anyone and let me know if you notice something wrong with the code |
Duplicate of #24432 |
Description
I added a gesture to a label span and tapped it. Nothing is happening on Windows. Cannot test Android bc it doesn't render the span.
Platforms:
Steps to Reproduce
Run this:
Version with bug
Preview 13 (current)
Last version that worked well
Unknown/Other
Affected platforms
Android, Windows
Affected platform versions
All
Did you find any workaround?
No workaround
Relevant log output
No response
The text was updated successfully, but these errors were encountered: