VladislavAntonyuk / MauiSamples

.NET MAUI Samples
https://vladislavantonyuk.azurewebsites.net/articles?categoryName=.NET%20MAUI/Xamarin
MIT License
723 stars 186 forks source link

`<Span>`s and support for setting custom cursors #421

Closed MartyIX closed 4 months ago

MartyIX commented 6 months ago

I have noticed that Span is not a VisualElement. So this if is not true:

https://github.com/VladislavAntonyuk/MauiSamples/blob/c774f4d3230f546e5dd74abb34c9e697522ea45a/MauiCursor/CursorBehavior.cs#L9

@VladislavAntonyuk Would you please know how to modify the code to allow custom cursors for <Span>s?

VladislavAntonyuk commented 6 months ago

You can see how TextColor or other properties implemented. Change SetCustomCursor method to receive Element or View. Span should be an Element or View.

MartyIX commented 6 months ago

Span should be an Element or View.

Span is Element. However, an exception Microsoft.Maui.Platform.HandlerNotFoundException: 'Handler not found for view Microsoft.Maui.Controls.Span.' is thrown here:

    public static void SetHoverCursor(this Element visualElement, CursorIcon cursor, IMauiContext? mauiContext)
    {
        ArgumentNullException.ThrowIfNull(mauiContext);

        UIElement view = visualElement.ToPlatform(mauiContext);  /// <<<<----------- Throws exception

        view.PointerEntered += (object sender, PointerRoutedEventArgs e)
            => view.SetCursor(InputCursor.CreateFromCoreCursor(new CoreCursor(GetCursor(cursor), 1)));

        view.PointerExited += (object sender, PointerRoutedEventArgs e)
            => view.SetCursor(InputCursor.CreateFromCoreCursor(new CoreCursor(GetCursor(CursorIcon.Arrow), 1)));
    }

Tested on Windows.

MartyIX commented 6 months ago

My XAML looks like this:

<Label>
    <Label.FormattedText>
        <FormattedString>
            <Span Text="Don't have an account? "/>
            <Span Text="Register" utils:CursorBehavior.Cursor="PointingHand">
                <Span.GestureRecognizers>
                    <TapGestureRecognizer Command="{Binding RegisterCommand}" />
                </Span.GestureRecognizers>
            </Span>
        </FormattedString>
    </Label.FormattedText>
</Label>

So maybe that utils:CursorBehavior.Cursor="PointingHand" is executed "too soon" because that label is not materialized yet.. I don't really know.

MartyIX commented 6 months ago

Ok, it seems like the most reasonable explanation is that the following line crashes for spans

UIElement view = visualElement.ToPlatform(mauiContext);

because spans do not have platform views but only parent labels.

VladislavAntonyuk commented 4 months ago

Even Native TextBlock doesn't allow custom cursor. Run, Span are not UIElement, they are TextElement.

TextBlock textBlock = new TextBlock();
textBlock.IsTextSelectionEnabled = true;
textBlock.FontFamily = new FontFamily("Arial");

// For Run and Span, add 'using Windows.UI.Xaml.Documents;'
var run = new Run();
run.Text = "This text demonstrates ";

var span = new Microsoft.UI.Xaml.Documents.Span();

Run run1 = new Run();
run1.FontStyle = Windows.UI.Text.FontStyle.Italic;
run1.Text = "the use of inlines ";

Run run2 = new Run();
run2.Text = "with formatting.";

span.Inlines.Add(run1);
span.Inlines.Add(run2);
textBlock.Inlines.Add(run);
textBlock.Inlines.Add(span);

// Add TextBlock to the visual tree.
return textBlock;
MartyIX commented 4 months ago

Thank you for the clarification.