多行文本按钮 Xamarin.Forms

10

有没有一种方法可以在 Xamarin.Forms Button 中设置多行文本?

我已经尝试过 Button.Text = "something \n xxjjjxx" ,但不起作用。

5个回答

14

一个简单的解决方案将会使用:




1
简单易用,对我来说完美无缺... 文本="第一行 第二行"... 谢谢 - DRapp
这应该在顶部 ^^^ - marc

5

在Github上有一个非常好的例子,展示了如何实现这个功能。实际上很简单,只需要创建自己的控件,继承自ContentView,并包含一个网格。

[ContentProperty("Content")]
public class MultiLineButton : ContentView
{
    public event EventHandler Clicked;

    protected Grid ContentGrid;
    protected ContentView ContentContainer;
    protected Label TextContainer;

    public String Text
    {
        get
        {
            return (String)GetValue(TextProperty);
        }
        set
        {
            SetValue(TextProperty, value);
            OnPropertyChanged();
            RaiseTextChanged();
        }
    }

    public new View Content
    {
        get { return ContentContainer.Content; }
        set
        {
            if (ContentGrid.Children.Contains(value))
                return;

            ContentContainer.Content = value;
        }
    }

    public static BindableProperty TextProperty = BindableProperty.Create(
        propertyName: "Text",
        returnType: typeof(String),
        declaringType: typeof(MultiLineButton),
        defaultValue: null,
        defaultBindingMode: BindingMode.TwoWay,
        propertyChanged: TextValueChanged);

    private static void TextValueChanged(BindableObject bindable, object oldValue, object newValue)
    {
        ((MultiLineButton)bindable).TextContainer.Text = (String)newValue;
    }

    public event EventHandler TextChanged;
    private void RaiseTextChanged()
    {
        if (TextChanged != null)
            TextChanged(this, EventArgs.Empty);
    }

    public MultiLineButton()
    {
        ContentGrid = new Grid
        {
            VerticalOptions = LayoutOptions.FillAndExpand,
            HorizontalOptions = LayoutOptions.FillAndExpand
        };

        ContentGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
        ContentGrid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) });

        ContentContainer = new ContentView
        {
            VerticalOptions = LayoutOptions.FillAndExpand,
            HorizontalOptions = LayoutOptions.FillAndExpand,
        };

        TextContainer = new Label
        {
            VerticalOptions = LayoutOptions.Center,
            HorizontalOptions = LayoutOptions.FillAndExpand,
        };
        ContentContainer.Content = TextContainer;

        ContentGrid.Children.Add(ContentContainer);

        var button = new Button
        {
            VerticalOptions = LayoutOptions.FillAndExpand,
            HorizontalOptions = LayoutOptions.FillAndExpand,
            BackgroundColor = Color.FromHex("#01000000")
        };

        button.Clicked += (sender, e) => OnClicked();

        ContentGrid.Children.Add(button);

        base.Content = ContentGrid;

    }

    public void OnClicked()
    {
        if (Clicked != null)
            Clicked(this, new EventArgs());
    }
}

然后可以像这样使用:

<local:MultiLineButton x:Name="AssessmentToolDetailButton" 
    WidthRequest="100" HeightRequest="60" BackgroundColor="Blue">
    <StackLayout HorizontalOptions="Center" VerticalOptions="CenterAndExpand">
        <Label Text="Hello" TextColor="White" Font="16"/>
        <Label Text="World" TextColor="White" Font="16"/>
    </StackLayout>
</local:MultiLineButton>

您还可以通过设置按钮的内容来放置图像。

在我的示例中,我修改了丹的原始代码以使文本可绑定。只需设置Text值而不是Content,如下所示:

<local:MultiLineButton Text="{Binding Description}" />

所有的荣誉归功于Danvanderboom提供的示例: ConentButton by Danvanderboom


这个解决方案对我有效,但我的按钮需要有圆角,以便与其他所有内容保持一致。 - fireydude
@fireydude 你可以轻松地按照自己的喜好设计按钮样式。在上面的代码中,您只需要在添加到网格中的Button上设置属性即可。我只设置了Vertical,Horizontal和BackgroundColor,但您也可以设置Borders。例如:BorderRadius = 4,BorderWidth = 2,BorderColor = Color.White, - Kasper
完美而干净的代码!只有一个小注释。按钮点击无效,我使用了轻拍手势代替。 - Neal Gabriel

4

这主要是 iOS 的问题,因为 Android 默认会自动换行。我尝试了 Kasper 提供的解决方案,虽然可以解决问题,但按钮没有圆角,外观与应用中的其他按钮不一致。

一个简单的解决方案是使用自定义渲染器(ButtonRenderer)将 LineBreakMode 设置为 WordWrap。如果您在 Xaml 中设置按钮的宽度,则可以使单词出现在不同的行上。

iOS

public class WrappedButtonRenderer: ButtonRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
    {
        base.OnElementChanged(e);

        Control.TitleEdgeInsets = new UIEdgeInsets(4, 4, 4, 4);
        Control.TitleLabel.LineBreakMode = UILineBreakMode.WordWrap;
        Control.TitleLabel.TextAlignment = UITextAlignment.Center;
    }
}

Android默认情况下不需要自定义渲染器,因为它具有默认的包装功能。

这是Xamarin Forms中已知的问题


如果我把这个放到 StackLayout 中,这对我无效。 - testing
@fireydude,你知道如何为TabbedPage选项卡按钮做到这一点吗? - Async-

2

我认为我很少见到两行按钮。您有两个选择,我认为可能会起作用:

  1. 创建自定义渲染器并扩展相应的按钮类以在每个本地平台上执行更多操作。这可能会更困难。
  2. 创建一个Xamarin.Forms类,该类扩展了可以包含StackLayout和诸如多行标签之类的较小元素的视图,然后您可以使用TapGestureRecognizer与您的视图一起使用,并将其视为按钮。

1

fireydude的回答的基础上,我创建了一个MultilineButton控件和iOS渲染器,以便我可以添加文本对齐。这使用Xamarin.Forms.TextAlignment枚举。

MultilineButton.cs

using Xamarin.Forms;

namespace APP_NAMESPACE.Controls
{
    public class MultilineButton : Button
    {
        public static readonly BindableProperty HorizontalTextAlignmentProperty = BindableProperty.Create(
            propertyName: "HorizontalTextAlignment",
            returnType: typeof(TextAlignment),
            declaringType: typeof(MultilineButton),
            defaultValue: TextAlignment.Start
        );

        public TextAlignment HorizontalTextAlignment
        {
            get { return (TextAlignment)GetValue(HorizontalTextAlignmentProperty); }
            set { SetValue(HorizontalTextAlignmentProperty, value); }
        }
    }
}

MultilineButtonRenderer.cs

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

[assembly: ExportRenderer(typeof(MultilineButton), typeof(MultilineButtonRenderer))]
namespace APP_NAMESPACE.iOS.Renderers
{
    public class MultilineButtonRenderer : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);

            if (Control == null) { return; }

            UIControlContentHorizontalAlignment horizontalAlignment;
            UITextAlignment textAlignment;

            // We have to use ButtonRenderer, so cast the Element to MultilineButton to get the HorizontalTextAlignment property
            var button = (MultilineButton)Element;
            if (button == null) { return; }

            switch(button.HorizontalTextAlignment)
            {
                case TextAlignment.Center:
                    horizontalAlignment = UIControlContentHorizontalAlignment.Center;
                    textAlignment = UITextAlignment.Center;
                    break;
                case TextAlignment.End:
                    horizontalAlignment = UIControlContentHorizontalAlignment.Right;
                    textAlignment = UITextAlignment.Right;
                    break;
                default:
                    horizontalAlignment = UIControlContentHorizontalAlignment.Left;
                    textAlignment = UITextAlignment.Left;
                    break;
            }

            Control.HorizontalAlignment = horizontalAlignment;
            Control.TitleLabel.LineBreakMode = UILineBreakMode.WordWrap;
            Control.TitleLabel.TextAlignment = textAlignment;
        }
    }
}

然后在XAML中使用它:
<controls:MultilineButton Text="This Button is Centered!" HorizontalTextAlignment="Center" />

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