Xamarin形式:空标签不呈现

[更新] :我修改了自定义渲染器以处理这种情况。见下文!

在开发Xamrin Forms(Android + iOS)应用程序时,我遇到了带有标签的奇怪行为:如果我将带有空文本的标签放置在Android上可以正常显示,而在iOS上则完全不显示

这是一个简单的例子:

XAML

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
     xmlns:d="http://xamarin.com/schemas/2014/forms/design"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     mc:Ignorable="d"
     x:Class="MyApp.Views.Page1"
     xmlns:ctrl="clr-namespace:MyApp.Controls">
<ContentPage.Content>
    <StackLayout Spacing="0">
        <Label x:Name="LabelOs" Margin="0,20" />

        <Label x:Name="Label1" Text="Label1" BackgroundColor="Red" TextColor="White" Margin="0" Padding="0" />
        <Label x:Name="Label2" Text="" BackgroundColor="Green" TextColor="White" Margin="0" Padding="0" />
        <Label x:Name="Label3" Text="Label3" BackgroundColor="Blue" TextColor="White" Margin="0" Padding="0" />

        <ctrl:RRLabel x:Name="Label1Custom" Text="Label1Custom" BackgroundColor="Yellow" Borders="Left,Right,Bottom" Margin="10,50,10,10" />
        <ctrl:RRLabel x:Name="Label2Custom" Text="" Borders="Left,Bottom" BackgroundColor="Yellow" Margin="10" />
        <ctrl:RRLabel x:Name="Label3Custom" Text="Label3Custom" Borders="Left,Bottom" BackgroundColor="Yellow" Margin="10" />

        <Button x:Name="Button1" Text="Set Label2" Clicked="Button1_Clicked" Margin="20,20,0" />

    </StackLayout>
</ContentPage.Content>

背后的代码

private void Button1_Clicked(object sender,EventArgs e)
{
    Label2.Text = "Label2";
    Label2Custom.Text = "Label2Custom";
}

标签自定义渲染器(仅相关部分):

public override void Draw(CGRect rect)
{

    using (CGContext g = UIGraphics.getcurrentContext())
    {
        base.Draw(rect);

        g.SetLineWidth(2);
        g.SetStrokeColor(lineColor);

        var path = new CGPath();

        if ((label.Borders & RRLabel.LabelBorders.Left) == RRLabel.LabelBorders.Left)
            path.AddLines(new CGPoint[] { new CGPoint(rect.Left,rect.Top),new CGPoint(rect.Left,rect.Bottom) });

        if ((label.Borders & RRLabel.LabelBorders.Bottom) == RRLabel.LabelBorders.Bottom)
            path.AddLines(new CGPoint[] { new CGPoint(rect.Left,rect.Bottom),new CGPoint(rect.Right,rect.Bottom) });

        if ((label.Borders & RRLabel.LabelBorders.Right) == RRLabel.LabelBorders.Right)
            path.AddLines(new CGPoint[] { new CGPoint(rect.Right,rect.Top) });

        if ((label.Borders & RRLabel.LabelBorders.Top) == RRLabel.LabelBorders.Top)
            path.AddLines(new CGPoint[] { new CGPoint(rect.Right,rect.Top) });

        g.AddPath(path);
        g.DrawPath(CGPathDrawingMode.Stroke);
    }
}

这是该应用在Android上的外观:

Xamarin形式:空标签不呈现

在iOS上:

Xamarin形式:空标签不呈现

如您所见,标准标签和自定义标签都存在问题:它们的高度均为0,因此不会显示背景。 设置文本后,将正确呈现标准标签,而在自定义标签中,则没有背景和边框。

如果我将标签文本设置为空格,那当然一切都很好,但是我想避免这种情况。

[解决方案] :我设法通过修改自定义渲染器来解决此问题:

共享控件

public class RRLabel : Label
{
    /* ... */

    public bool IosForceHeight { get; set; } = true;
}

渲染器

protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
    base.OnElementChanged(e);

    if (Control != null && e.NewElement != null)
    {
        /* ... */
        if (label.IosForceHeight && label.Text == "") Control.Text = " ";
    }
}

protected override void OnElementPropertyChanged(object sender,PropertyChangedEventArgs e)
{
    base.OnElementPropertyChanged(sender,e);

    /* ... */
    if (label.IosForceHeight && e.PropertyName == nameof(RRLabel.Text) && label.Text == "") Control.Text = " ";
}

这样,我可以始终呈现标签,同时在共享控件中保留Text属性的实际值。

zz19860418 回答:Xamarin形式:空标签不呈现

是的。这是两个平台之间的渲染差异之一。

它与本机实现一致。 在iOS上,带有文本的Label的高度为0。在Android上,它采用任何Label所需的高度。

我不使用空白文本呈现Label的解决方案是在IsVisible属性上使用转换器。

相反,如果您仍要测量高度,请设置标签的HeightRequest。

希望有帮助!

,

这是iOS平台的默认行为。

我将提供一个解决方案,该解决方案将标签的文本设置为iOS,以使标签显示在<Label x:Name="Label2" Text=" " BackgroundColor="Green" TextColor="White" Margin="0" /> 侧。

例如:

class Product(db.Model):
    __tablename__ = 'products'

    skuid = db.Column(db.String(16),primary_key=True)
    name = db.Column(db.String(128))
    variant_sets = db.relationship("ProductToOption")

class ProductToOption(db.Model):
    __tablename__ = 'products_to_options'

    id = db.Column(db.INTEGER,primary_key=True)
    skuid = db.Column(db.String(36),db.ForeignKey('products.skuid'),nullable=False)
    options_code = db.Column(db.String(36),nullable=False)

    variants = db.relationship('Option')

class Option(db.Model):
    __tablename__ = 'options'

    variant_set = db.Column(db.String(16),db.ForeignKey('products_to_options.options_code'),nullable=False)
    code = db.Column(db.String(8),nullable=False)
    variant_type = db.Column(db.String(16),nullable=False)
    description = db.Column(db.String(16),nullable=False)
本文链接:https://www.f2er.com/3122467.html

大家都在问