Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xamarin.forms Xaamrin使用下划线时形成的BoxView宽度过长_Xamarin.forms_Label_Width_Underline_Stacklayout - Fatal编程技术网

Xamarin.forms Xaamrin使用下划线时形成的BoxView宽度过长

Xamarin.forms Xaamrin使用下划线时形成的BoxView宽度过长,xamarin.forms,label,width,underline,stacklayout,Xamarin.forms,Label,Width,Underline,Stacklayout,我正在使用BoxView在我的应用程序中完成下划线。我有两个非常短的标签,例如Yes或No等。下面是其中一个标签的XAML,其中一个标签的BoxView用于下划线: <StackLayout Orientation="Vertical" Grid.Row="5" Grid.Column="1" Margin="0,4,0,4" HorizontalOptions="Start" BackgroundColor="Purple" MinimumWidthRequest="1">

我正在使用BoxView在我的应用程序中完成下划线。我有两个非常短的标签,例如Yes或No等。下面是其中一个标签的XAML,其中一个标签的BoxView用于下划线:

<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和标签的宽度相同。第二个屏幕截图显示了移除BoxView时屏幕的外观,即标签和堆栈布局的大小正确

有没有关于如何解决这个问题的建议

BoxView屏幕截图过长,标签和堆栈布局过长

移除BoxView并正确调整标签和堆栈布局大小的屏幕截图

一个选项是使用自定义渲染器替换标签/框下划线,该渲染器向标签添加下划线功能

以下是如何做到这一点:

用户控制

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;
            }
        }
    }
}
[程序集:ExportRenderer(typeof(CustomLabel)、typeof(CustomLabelRenderer))]
命名空间事件.Droid.CustomRenders
{
公共类CustomLabelRenderer:LabelRenderer
{
受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e)
{
基础。一个要素发生变化(e);
var视图=(CustomLabel)元素;
var控制=控制;
更新(视图、控件);
}
受保护的覆盖无效OnElementPropertyChanged(对象发送方,PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(发送方,e);
var视图=(CustomLabel)元素;
如果(e.PropertyName==CustomLabel.IsUnderlinedProperty.PropertyName)
{
Control.PaintFlags=view.is下划线?Control.PaintFlags | PaintFlags.UnderlineText:Control.PaintFlags&=~PaintFlags.UnderlineText;
}
}
静态void UpdateUi(CustomLabel视图、TextView控件)
{
如果(view.FontSize>0)
{
control.TextSize=(float)view.FontSize;
}
如果(视图.带下划线)
{
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;
        }
    }
}
[程序集:ExportRenderer(typeof(CustomLabel)、typeof(CustomLabelRenderer))]
命名空间事件.iOS.CustomRenders
{
公共类CustomLabelRenderer:LabelRenderer
{
受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e)
{
基础。一个要素发生变化(e);
var视图=(CustomLabel)元素;
更新(视图、控件);
}
受保护的覆盖无效OnElementPropertyChanged(对象发送方,PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(发送方,e);
var视图=(CustomLabel)元素;
如果(e.PropertyName==CustomLabel.IsUnderlinedProperty.PropertyName)
{
更新(视图、控件);
}
}
私有静态void UpdateUi(自定义标签视图,UILabel控件)
{
var attrString=新的NSMutableAttributeString(control.Text);
if(view!=null&&view.is下划线)
{
attrString.AddAttribute(UIStringAttributeKey.UnderlineStyle,
NSNumber.FromInt32((int)NSUnderlineStyle.Single),
新的NSRange(0,attrString.Length));
}
control.attributeText=attrString;
}
}
}
请注意默认值和来自视图的值:

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

在“使用度量”标签上添加
horizontalpoptions=“Start”



您使用框视图加下划线而不是向标签添加下划线功能的原因是什么?您是说编写我自己的自定义渲染器?是的。这很简单。我会用代码写一个答案。我不喜欢写自定义平台代码。它更容易被破坏,每个平台都会发生变化。此外,我还需要支持UWP以及android和ios。如果您使用Xamarin.Forms,尽管您可能希望远离特定于平台的代码(我最初也这么做了),但最终您将被迫接受它。这是克服Xamarin.Forms强加的一些限制的唯一方法。如果你试图避免它,你会付出更多的努力和代码,最终得到一个更糟糕的解决方案。请参见上面的注释。因此,这似乎是修复它的实际代码。WidthRequest=“{Binding Path=Width,Source={x:Reference txtosemetric}”(我以前所有的东西都是horizontalpoptions=“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"/>