Xamarin Forms: How can I add padding to a button?

2019-03-09 20:02发布

问题:

I have the following XAML Xamarin.Forms.Button

<Button Text="Cancel" BackgroundColor="#3079a8" TextColor="White" />

I tried to add padding to it via the Padding property but that didn't work. After checking the forums and the docs, I realised there is no padding property in the documentation for Xamarin.Forms.Button (link to the docs) , is there some other type of quick fix to add just a little bit more padding to a button? A code example would be greatly appreciated.

回答1:

Update:

Padding has been added to the XF Button control in Xamarin.Forms v3.2+

<Button Padding="10,20,10,20" />

Old:

The best way to do it would be to increase the size of the button.

Then align the text as you see fit. Unfortunately it is about the best you can do. It works well if you have your text center aligned. Not so much if its left or right aligned.



回答2:

usage:

<controls:EnhancedButton Padding="1,2,3,4"/>

advantages:

  • no nasty sideeffects
  • no problem with alignments
  • no viewtree uglyness
  • no view depth incrementation

ios:

[assembly: ExportRenderer(typeof(EnhancedButton), typeof(EnhancedButtonRenderer))]
namespace YOURNAMESPACE.iOS
{
    public class EnhancedButtonRenderer : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);
            UpdatePadding();
        }

        private void UpdatePadding()
        {
            var element = this.Element as EnhancedButton;
            if (element != null)
            {
                this.Control.ContentEdgeInsets = new UIEdgeInsets(

                    (int)element.Padding.Top,
                    (int)element.Padding.Left,
                    (int)element.Padding.Bottom,
                    (int)element.Padding.Right
                );
            }
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            if (e.PropertyName == nameof(EnhancedButton.Padding))
            {
                UpdatePadding();
            }
        }
    }
}

android:

[assembly: ExportRenderer(typeof(EnhancedButton), typeof(EnhancedButtonRenderer))]
namespace YOURNAMESPACE.Droid
{
    public class EnhancedButtonRenderer : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);
            UpdatePadding();
        }

        private void UpdatePadding()
        {
            var element = this.Element as EnhancedButton;
            if (element != null)
            {
                this.Control.SetPadding(
                    (int)element.Padding.Left,
                    (int)element.Padding.Top,
                    (int)element.Padding.Right, 
                    (int)element.Padding.Bottom
                );
            }
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            if (e.PropertyName == nameof(EnhancedButton.Padding))
            {
                UpdatePadding();
            }
        }
    }
}

pcl:

public class EnhancedButton : Button
{
    #region Padding    

    public static BindableProperty PaddingProperty = BindableProperty.Create(nameof(Padding), typeof(Thickness), typeof(EnhancedButton), default(Thickness), defaultBindingMode:BindingMode.OneWay);

    public Thickness Padding
    {
        get { return (Thickness) GetValue(PaddingProperty); }
        set { SetValue(PaddingProperty, value); }
    }

    #endregion Padding
}

Solution using effects instead of renderers, to allow easy usage for more than one control:

XAML:

<Label Text="Welcome to Xamarin.Forms!" BackgroundColor="Red">
    <Label.Effects>
        <xamTest:PaddingEffect Padding="20,40,20,40"></xamTest:PaddingEffect>
    </Label.Effects>
</Label>

PCL:

[assembly: ResolutionGroupName("ComponentName")]
namespace XamTest
{
    public class PaddingEffect : RoutingEffect
    {
        /// <inheritdoc />
        protected PaddingEffect(string effectId) : base($"ComponentName.{nameof(PaddingEffect)}")
        {
        }

        public Thickness Padding { get; set; }
    }
}

Android:

[assembly: ResolutionGroupName("ComponentName")]
[assembly: ExportEffect(typeof(XamTest.Droid.PaddingEffect), "PaddingEffect")]
namespace XamTest.Droid
{
    public class PaddingEffect : PlatformEffect
    {
        /// <inheritdoc />
        protected override void OnAttached()
        {
            if (this.Control != null)
            {
                var firstMatch = this.Element.Effects.FirstOrDefault(d => d is XamTest.PaddingEffect);
                if (firstMatch is XamTest.PaddingEffect effect)
                {
                    this.Control.SetPadding((int)effect.Padding.Left, (int)effect.Padding.Top, (int)effect.Padding.Right, (int)effect.Padding.Bottom);
                }
            }
        }

        /// <inheritdoc />
        protected override void OnDetached()
        {
        }
    }
}


回答3:

you can wrap your button in a StackLayout and add padding to the StackLayout

 <StackLayout Padding="10,10,10,10">
     <Button Text="Cancel" BackgroundColor="#3079a8" TextColor="White" />
  </StackLayout>


回答4:

In iOS, you can use a simple custom renderer to add a bit of padding to the button:

[assembly: ExportRenderer(typeof(Button), typeof(iOSButtonRenderer))]
namespace My.App.iOS.Renderers.Button
{
    /// <summary>
    /// A custom renderer that adds a bit of padding to either side of a button
    /// </summary>
    public class iOSButtonRenderer : ButtonRenderer
    {
        public iOSButtonRenderer() { }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);
            Control.ContentEdgeInsets = new UIEdgeInsets(Control.ContentEdgeInsets.Top, Control.ContentEdgeInsets.Left + 10, Control.ContentEdgeInsets.Bottom, Control.ContentEdgeInsets.Right + 10);
        }
    }
}


回答5:

The simplest you can do is

<StackLayout  Margin="0,20,0,0" Orientation="Horizontal" Spacing="20"> 
        <Switch VerticalOptions="CenterAndExpand"  ></Switch>
        <Label VerticalOptions="CenterAndExpand" TextColor="White">Remember Me</Label>
        <StackLayout  HorizontalOptions="FillAndExpand"><Button VerticalOptions="CenterAndExpand" HorizontalOptions="FillAndExpand" Text="Sign In" TextColor="White" BackgroundColor="#5cb85c"  ></Button>
        </StackLayout>
</StackLayout>

[such a big headache working with xamarin forms :'(]



回答6:

It doesn't work for me in android. Looking at SetPadding function, I see that the Control has a minimum height of 132 and a minimum width of 242. I changed the SetPadding function in:

 private void SetPadding()
    {
        var element = Element as ExtendedButton;
        if (element != null)
        {
            Control.SetMinHeight(-1);
            Control.SetMinimumHeight(-1);
            Control.SetMinWidth(-1);
            Control.SetMinimumWidth(-1);
            Control.SetPadding(
                (int)element.Padding.Left,
                (int)element.Padding.Top - 6,
                (int)element.Padding.Right,
                (int)element.Padding.Bottom - 6);
        }
    }