Xamarin Forms标签 - 对齐?

11

我想问一下,在使用Xamarin Forms Xaml的情况下,有没有办法对

更新: 目前还不支持文本对齐。大多数答案都是关于居中文本的,但这不是我要问的。一种方法可以使用Timothy提供的Renderer。

11个回答

13

虽然你不能使用Xamarin.Forms功能将标签的文本拉伸到全宽,但可以通过平台渲染器轻松实现。

Android text justification in Xamarin.Froms label

大多数Xamarin平台都有相应本地元素中可用的文本对齐功能,只需设置本地元素的一个属性即可。我认为之所以没有将此功能添加到标准的Xamarin.Forms标签中,是因为平台在该功能方面的落后,例如,Android仅在8.1版本中添加了Android.Text.JustificationMode.InterWord标志。
以下是Android渲染器实现:
using Android.Content;
using Saplin.CPDT.UICore.Controls;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(Saplin.CPDT.UICore.Controls.ExtendedLabel), typeof(Saplin.CPDT.Droid.ExtnededLabelRenderer))]
namespace Saplin.CPDT.Droid
{
    public class ExtnededLabelRenderer : Xamarin.Forms.Platform.Android.LabelRenderer
    {
        public ExtnededLabelRenderer(Context context) : base(context)
        {
        }

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

            var el = (Element as ExtendedLabel);

            if (el != null && el.JustifyText)
            {
                if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
                {
                    Control.JustificationMode = Android.Text.JustificationMode.InterWord;
                }

            }
        }
    }
}
  1. 在原生项目中创建渲染器类
  2. 添加assembly: ExportRenderer属性
  3. 设置TextView的JustificationMode

在我的示例中,我使用了Xamarin.Forms.Label的子类ExtenedLabel,并添加了额外的属性JustifyText以设置文本的对齐方式。以下是如何声明子类控件:

using System;
using Xamarin.Forms;

namespace Saplin.CPDT.UICore.Controls
{
    public class ExtendedLabel : Label
    {
        public static readonly BindableProperty JustifyTextProperty =
            BindableProperty.Create(
                propertyName: nameof(JustifyText),
                returnType: typeof(Boolean),
                declaringType: typeof(ExtendedLabel),
                defaultValue: false,
                defaultBindingMode: BindingMode.OneWay
         );

        public bool JustifyText
        {
            get { return (Boolean)GetValue(JustifyTextProperty); }
            set { SetValue(JustifyTextProperty, value); }
        }
    }
}
  • 平台渲染器的示例,适用于WPFmacOS

1
为了让您的答案更完整,这里有一个Android/iOS/UWP的示例项目:https://github.com/nguyenthanhliemfc/LabelJustify - Jonx
感谢您的添加! - Maxim Saplin
1
由于我不理解的原因,这个解决方案在Android上可以正常工作,但是在iOS上使用FormattedText和Spans时,文本无法对齐,为了使其正常工作,您还必须在OnElementPropertyChanged中复制此实现。然后它就可以在iOS和Android上正常工作了。 - Jonx

9
现在实现这一点的方法是使用HorizontalTextAlignment,其中TextAlignment枚举的值为:
  • Center = 居中对齐的文本
  • Start = 左对齐
  • End = 右对齐
下面是一个居中显示标签及其文本的示例: <Label x:Name="Description" HorizontalTextAlignment="Center" VerticalOptions="Center" HorizontalOptions="Center" />

谢谢您的回答,但这只是让文本居中了吗? - ainer
1
是的,既然你提到了,我应该把我的回答表述为:“该选项不可用。这里是可用的选项。”如果您想要执行“完全对齐”,则需要为想要支持的每个平台创建自定义渲染器。此时,您将依赖于每个平台的功能集。iOS 允许您设置完全对齐的选项 [ NSTextAlignmentJustified],然后在 Android 上,您可以使用以下项目之一作为起点:https://github.com/bluejamesbond/TextJustify-Android / https://github.com/navabi/JustifiedTextView - Timothy Lee Russell

2
在XAML中,你可以使用HTML来调整文本的对齐方式。
<Label LineBreakMode="WordWrap" TextType="Html" TextColor="Black">
<Label.Text>&lt;p style=&quot;text-align:justify;&quot;&gt; 
Your text here
&lt;p&gt;</Label.Text>

1
使用 XAlign 属性。
Label lbl = new Label();
lbl.Text = "I'm a Label!";
lbl.XAlign = TextAligntment.Start; // Start, Center, End are valid

我了解这些选项。但我不知道如何调整文本对齐 - 即每行文字左右两端相等的缩进。这会拉伸单词之间的空隙以填充整行,就像在MS Word或其他文本编辑器中一样。 - ainer
啊,我明白了。据我所知,目前没有办法实现这个功能。你可以编写一个自定义渲染器来使用iOS的文本对齐功能,但我不确定在Android中是否有相应的方法。 - Jason

1
由于无法直接在标签内完成此操作,解决方法是使用Xamarin.Forms 3中的新FlexLayout。其思路是在空格处拆分文本,并在FlexLayout中插入相应的标签,并将JustifyContent设置为SpaceBetween
例如: XAML
<Frame
    HorizontalOptions="Center"
    Margin="20,50,20,0"
    Padding="10"
    WidthRequest="300"
    HasShadow="true">
    <FlexLayout
        x:Name="TextContainer"
        Direction="Row"
        AlignItems="End"
        JustifyContent="SpaceBetween"
        Wrap="Wrap"/>
</Frame>

代码后台

var textparts = "This is a long text to be justified"
                .Split(' ', StringSplitOptions.RemoveEmptyEntries)
                .Select(x => new Label
                {
                    Text = x,
                    FontSize = 12,
                    TextColor = Color.FromHex("#555555"),
                    Margin = new Thickness(1, 0)
                });

            foreach (var textpart in textparts)
                TextContainer.Children.Add(textpart);

这听起来是一个不错的解决方案,但是它不会对最后一行文本造成问题吗?比如,如果最后一行只有两个单词,你会在左边有一个单词,在右边有一个单词,这不是正常的对齐方式。 - morphinapg
对于那些寻找在 Android 8.1 以下版本上进行脏破解的人来说,这个方法是可行的。我还在末尾添加了几个空格,以便它看起来更好。 - Anton Maiorov

0

自定义标签


using System;
using Xamarin.Forms;

namespace YourNameSpace.Controls
{
    public class CustomLabel : Label
    {
        public static readonly BindableProperty JustifyTextProperty =
      BindableProperty.Create(nameof(JustifyText), typeof(bool), typeof(CustomLabel), false, BindingMode.TwoWay);

        public bool JustifyText
        {
            get { return (bool)GetValue(JustifyTextProperty); }
            set
            {

                SetValue(JustifyTextProperty, value);
            }
        }

        public CustomLabel()
        {
        }
    }
}

iOS自定义标签渲染器

using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using YourNameSpace.Controls;
using YourNameSpace.iOS.Renderers;

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

            if (Control == null || this.Element == null) return;

            Control.TextAlignment = UITextAlignment.Justified;

        }
    }
}

Android自定义标签渲染器

using Android.Content;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using YourNameSpace.Controls;
using YourNameSpace.Droid.Renderers;

[assembly: ExportRenderer(typeof(CustomLabel), typeof(CustomLabelRenderer))]
namespace YourNameSpace.Droid.Renderers
{
    public class CustomLabelRenderer : Xamarin.Forms.Platform.Android.LabelRenderer
    {
        public CustomLabelRenderer(Context context) : base(context)
        {
        }

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

            var element = (Element as CustomLabel);

            if (element != null && element.JustifyText)
            {
                if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
                {
                    Control.JustificationMode = Android.Text.JustificationMode.InterWord;
                }
            }
        }
    }
}

0

我已经成功地使用嵌套网格实现了这一点。希望这能帮助到某些人!

<Grid HorizontalOptions="Fill" Padding="5,2">
             <Grid  Margin="8, 85,8,0" VerticalOptions="Center" RowSpacing="0" >

                                    <Label Grid.Row="0" x:Name="PostTitle" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"
                                           Text="Display Text" Padding="10,10" LineHeight="20" BackgroundColor="Black" TextColor="WhiteSmoke" />

                                    <Label Grid.Row="1" x:Name="PostDate"  HorizontalTextAlignment="Center" VerticalTextAlignment="Center"
                                           Text="Your Text Here" FontSize="Micro" Padding="10,10" LineHeight="10" 
                                           BackgroundColor="Black" TextColor="WhiteSmoke" />

                                </Grid>

                            </Grid>

0
在 Xamarin IOS 中,如何使 UITableViewCell 的 TextLabel 文本两端对齐?
UIStringAttributes stringAttributes = new UIStringAttributes
{
    ParagraphStyle = new NSMutableParagraphStyle() { Alignment = UITextAlignment.Justified }
};

var attributedText = new NSMutableAttributedString(cell.TextLabel.Text);
attributedText.AddAttributes(stringAttributes, new NSRange(0, cell.TextLabel.Text.Length));
cell.TextLabel.AttributedText = attributedText;

0
你使用什么容器来保存这段文本?如果每个控件只有一行文本,拥有 HorizontalOptions 为 FillAndExpand 以及 XAlign 的 StackLayout 可能可以解决问题。

我使用了StackLayout。在这个问题上,我必须支持@Jason的观点。似乎无法实现文本两端对齐,只能居中对齐。 - ainer

0

试试这个:

<StackLayout HorizontalOptions="FillAndExpand" Padding="0, 10, 0, 10" Spacing="0">
      <Label Text="Test message" XAlign="Center"/>
      <Label FontSize="Small" Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." LineBreakMode="WordWrap"
XAlign="Center" />
</StackLayout>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接