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

sgarcia.dev picture sgarcia.dev · May 16, 2015 · Viewed 17.1k times · Source

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.

Answer

Dbl picture Dbl · Mar 17, 2016

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