Custom Renderer for button with padding not properly sizing buttons in Android

CullenJCullenJ USMember ✭✭

I'm having a lot of trouble getting something that should be very simple to work. All I want is to have buttons with a little bit of padding around the text or icon in the UI. Following an answer on Stack Overflow, I created a custom renderer for a button with padding.

Xamarin.Forms ButtonWithPadding:

using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;

namespace Messenger.UI.Controls
{
    public class ButtonWithPadding : Button
    {
        public Thickness Padding
        {
            get { return (Thickness)GetValue(PaddingProperty); }
            set { SetValue(PaddingProperty, value); }
        }

        public static readonly BindableProperty PaddingProperty =
            BindableProperty.Create("Padding", typeof(Thickness), typeof(ButtonWithPadding), new Thickness(-1.0));
    }
}

iOS Custom Renderer:

using Messenger.UI.Controls;
using System;
using System.Collections.Generic;
using System.Text;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(ButtonWithPadding), typeof(Messenger.iOS.Controls.ButtonWithPaddingRenderer))]
namespace Messenger.iOS.Controls
{
    public class ButtonWithPaddingRenderer : ButtonRenderer
    {
        public ButtonWithPaddingRenderer() : base()
        {
        }

        protected ButtonWithPadding buttonWithPadding;

        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);

            if (buttonWithPadding == null)
                buttonWithPadding = e.NewElement as ButtonWithPadding;

            var iosButton = Control as UIButton;

            Thickness padding = buttonWithPadding.Padding;

            if (padding.Left > 0)
            {
                iosButton.ContentEdgeInsets = new UIEdgeInsets(
                    new nfloat(padding.Top),
                    new nfloat(padding.Left),
                    new nfloat(padding.Bottom),
                    new nfloat(padding.Right)
                );
            }

        }
    }
}

Android Custom Renderer:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Messenger.Droid.Controls;
using Messenger.UI.Controls;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using System.ComponentModel;

[assembly: ExportRenderer(typeof(ButtonWithPadding), typeof(ButtonWithPaddingRenderer))]
namespace Messenger.Droid.Controls
{
    public class ButtonWithPaddingRenderer : ButtonRenderer
    {
        public ButtonWithPaddingRenderer(Context c) : base(c) { }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);
            UpdatePadding();
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (e.PropertyName == nameof(ButtonWithPadding.Padding))
                UpdatePadding();
        }

        private void UpdatePadding()
        {
            ButtonWithPadding buttonWithPadding = Element as ButtonWithPadding;

            if (buttonWithPadding != null && buttonWithPadding.Padding.Left > 0)
            {
                Control.SetPadding(
                    (int) buttonWithPadding.Padding.Left,
                    (int) buttonWithPadding.Padding.Top,
                    (int) buttonWithPadding.Padding.Right,
                    (int) buttonWithPadding.Padding.Bottom
                );
            }

        }
    }
}

Finally, I have this XAML for displaying the buttons with padding:

<StackLayout BackgroundColor="#024985" Orientation="Horizontal" HorizontalOptions="FillAndExpand">

    <Button
        x:Name="HelpButton"
        Text="?"
        HorizontalOptions="EndAndExpand"
        VerticalOptions="CenterAndExpand"
        WidthRequest="26"
        HeightRequest="26"
        BorderRadius="13"
        TextColor="White"
        BackgroundColor="#327fc0"
        Clicked="OnHelpButtonClicked" />

    <controls:ButtonWithPadding
        x:Name="SettingsButton"
        Image="ic_settings"
        TextColor="White"
        BackgroundColor="#327fc0"
        HeightRequest="26"
        WidthRequest="26"
        BorderRadius="13"
        Padding="2"
        HorizontalOptions="End"
        VerticalOptions="CenterAndExpand"
        Clicked="SettingsButtonClicked" />

</StackLayout>

Sorry for all the code, but I thought I'd share everything I thought was relevant! Anyway, the buttons render correctly in iOS:


But fail to size properly in Android:


How can I fix this? Bonus points if you can tell me how to get rid of the drop shadow on the Android buttons as well! :)

Best Answer

  • CullenJCullenJ US ✭✭
    Accepted Answer

    I've done some more digging and realized this is just an issue with my not sizing the buttons correctly, not the custom renderer. iOS just doesn't allow you to shrink a button smaller than its image or text label.

Answers

  • CullenJCullenJ USMember ✭✭
    Accepted Answer

    I've done some more digging and realized this is just an issue with my not sizing the buttons correctly, not the custom renderer. iOS just doesn't allow you to shrink a button smaller than its image or text label.

  • iambyteiambyte Member

    I have used the same code as yours followed by stackoverflow, but in android, the padding has no effect on view, I am trying to set padding = "0" but still the button shows spaces around it. As you mentioned that "But fail to size properly in Android", How did you solve it for Android?

  • CullenJCullenJ USMember ✭✭
    edited July 2018

    @iambyte said:
    I have used the same code as yours followed by stackoverflow, but in android, the padding has no effect on view, I am trying to set padding = "0" but still the button shows spaces around it. As you mentioned that "But fail to size properly in Android", How did you solve it for Android?

    I wish I had a better answer for you, @iambyte , but unfortunately, I haven't been able to figure out a good solution for this yet. My current workaround is just setting the height and width of the buttons to a larger size manually. It's very frustrating that this doesn't seem to be working as advertised.

Sign In or Register to comment.