Xamarin 在使用下划线时形成 BoxView 宽度太长

Xaamrin Forms BoxView Width Too Long when using to Underline

我正在使用 BoxView 在我的应用程序中添加下划线。我有几个非常短的标签 - 诸如“是”或“否”之类的文本。这是带有下划线的 BoxView 的其中一个标签的 XAML:

<StackLayout Orientation="Vertical" Grid.Row="5" Grid.Column="1" Margin="0,4,0,4" HorizontalOptions="Start" BackgroundColor="Purple" MinimumWidthRequest="1">
    <Label x:Name="txtUseMetric" TextColor="Blue" FontSize="Small" Text="{Binding UseMetricText}" BackgroundColor="Yellow">
    <Label.GestureRecognizers>
        <TapGestureRecognizer Tapped="Value_Tapped" CommandParameter="usemetric" />
    </Label.GestureRecognizers>
    </Label>
    <BoxView BackgroundColor="Green" HeightRequest="1" MinimumWidthRequest="1" />
</StackLayout>

我的问题是 BoxView 的宽度总是超出我的文本我已经尝试覆盖 App.Xaml 文件中的 MinWidthRequest,如下所示:

<Style TargetType="BoxView">
    <Setter Property="MinimumWidthRequest" Value="3" />
</Style>

但这并没有效果。我已经包含了屏幕截图供您查看。

仅供参考 - 黄色是标签的宽度。您看不到任何紫色(StackLayout 的背景色),因为 StackLayout 和 Label 的宽度相同。第二个屏幕截图显示了如果我删除 BoxView 时屏幕的样子 - 即 Label 和 StackLayout 的大小正确。

关于如何解决这个问题有什么建议吗?

BoxView 太长导致标签和 StackLayout 太长的屏幕截图

已删除 BoxView 且标签和堆栈布局大小正确的屏幕截图

一个选项是用自定义呈现器替换 label/box 下划线,为标签添加下划线功能。

操作方法如下:

用户控制

public class CustomLabel : Label
{
    public static readonly BindableProperty IsUnderlinedProperty =
        BindableProperty.Create(nameof(IsUnderlined), typeof(bool), typeof(CustomLabel), false);

    public bool IsUnderlined
    {
        get { return (bool)GetValue(IsUnderlinedProperty); }
        set
        {
            SetValue(IsUnderlinedProperty, value);
        }
    }
}

Android 渲染器

[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace Incident.Droid.CustomRenderers
{
    public class CustomLabelRenderer : LabelRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {
            base.OnElementChanged(e);

            var view = (CustomLabel)Element;
            var control = Control;

            UpdateUi(view, control);
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            var view = (CustomLabel)Element;

            if (e.PropertyName == CustomLabel.IsUnderlinedProperty.PropertyName)
            {
                Control.PaintFlags = view.IsUnderlined ? Control.PaintFlags | PaintFlags.UnderlineText : Control.PaintFlags &= ~PaintFlags.UnderlineText;
            }

        }

        static void UpdateUi(CustomLabel view, TextView control)
        {
            if (view.FontSize > 0)
            {
                control.TextSize = (float)view.FontSize;
            }

            if (view.IsUnderlined)
            {
                control.PaintFlags = control.PaintFlags | PaintFlags.UnderlineText;
            }
        }
    }
}

iOS 渲染器

[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace Incident.iOS.CustomRenderers
{
    public class CustomLabelRenderer : LabelRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {
            base.OnElementChanged(e);

            var view = (CustomLabel)Element;

            UpdateUi(view, Control);
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            var view = (CustomLabel)Element;

            if (e.PropertyName == CustomLabel.IsUnderlinedProperty.PropertyName)
            {
                UpdateUi(view, Control);
            }
        }

        private static void UpdateUi(CustomLabel view, UILabel control)
        {
            var attrString = new NSMutableAttributedString(control.Text);

            if (view != null && view.IsUnderlined)
            {
                attrString.AddAttribute(UIStringAttributeKey.UnderlineStyle,
                    NSNumber.FromInt32((int)NSUnderlineStyle.Single),
                    new NSRange(0, attrString.Length));
            }

            control.AttributedText = attrString;
        }
    }
}

请注意默认值 HorizontalOptions and that Label 派生自视图:

默认值为 LayoutOptions。Fill 除非另有说明。

在 "Use Metric" 标签上添加 HorizontalOptions="Start"

<Label x:Name="txtUseMetric" TextColor="Blue" FontSize="Small" 
       Text="{Binding UseMetricText}" BackgroundColor="Yellow"
       HorizontalOptions="Start">
<BoxView BackgroundColor="Green" HeightRequest="1" 
         WidthRequest="{Binding Path=Width, Source={x:Reference txtUseMetric}" 
         HorizontalOptions="Start"/>