Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

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

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.

  • IshaPIshaP Member ✭✭

    Hi @CullenJ , have you found any solution to the button padding problem?

Sign In or Register to comment.