简体   繁体   中英

Multi-Line text Button Xamarin.Forms

theres is a way to set a multi-line text to a Xamarin.Forms Button??

I've tried Button.Text = "something \\n xxjjjxx" But don't work.

There is an excellent example on how to achieve this on Github. It is quite simple really. Just create your own control that inherits from ContentView and contains a grid.

[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());
    }
}

Then it can be used like this:

<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>

You can also place an image in the button by setting its content.

In my example I modified Dans original code in order to make the text bindable. Just set the Text value instead of the Content like this:

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

All credit goes to Danvanderboom for his example: ConentButton by Danvanderboom

This is mainly a problem with iOS because Android will wrap the text by default. I tried the solution provided by Kasper and it worked however the buttons do not have rounded corners and the appearance is not consistent with other buttons in my app.

A simple solution is to use a custom renderer (ButtonRenderer) to set the LineBreakMode to WordWrap. If you then set the width of the button in the Xaml you get words to appear on different lines.

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 does not require a custom renderer because it wraps by default.

This is a known issue with Xamarin Forms.

I don't think I've seen two lined buttons often. You have two options that I think might work:

  1. Create a Custom Renderer and Extend the respective Button Class to do more on each native platform. Might be a harder
  2. Create a Xamarin.Forms Class that extends a View that can contains a StackLayout and smaller elements such as multi-line labels, then you can use a TapGestureRecognizer to use with your view and treat it like a button.

简单的解决方案将使用:

&#x0a;

Expanding on fireydude's answer , I created a MultilineButton control and renderer for iOS so I could add text alignment. This uses the Xamarin.Forms.TextAlignment enum.

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;
        }
    }
}

Then use it within XAML:

<controls:MultilineButton Text="This Button is Centered!" HorizontalTextAlignment="Center" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM