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

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.


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()
        {
        }
    }
}

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>