'How to align image to the left and text to the center on a Xamarin button in iOS?

I want to align my text in the center, but the image on the left. I have tried it with HorizontalAlignment, but it aligns both. How to do it?



Solution 1:[1]

I took the time to actually understand how "insets" work, and wrote my own solution.

Ringotan


[assembly: ExportRenderer(typeof(Button), typeof(RingotanButtonRenderer))]
namespace MyAppNamespace
{
    public class MyButtonRenderer : ButtonRenderer
    {
        public override void LayoutSubviews()
        {
            base.LayoutSubviews();

            // Left-align the image and center the text
            // Taken from https://stackoverflow.com/a/71044012/238419
            if (Element.ContentLayout.Position == Button.ButtonContentLayout.ImagePosition.Left)
            {
                const int imageMargin = 20; // This might need to get multiplied by the screen density, not sure yet.  I'll update this later if it does.
                nfloat imageOffset = Control.ImageView.Frame.Left - imageMargin;
                Control.ImageEdgeInsets = new UIEdgeInsets(0, -imageOffset, 0, imageOffset);

                nfloat imageWidth = Control.ImageView.Frame.Width + imageMargin;
                nfloat textOffset = Control.TitleLabel.Frame.Left - (imageWidth + Control.Frame.Width - Control.TitleLabel.Frame.Width) / 2;
                Control.TitleEdgeInsets = new UIEdgeInsets(0, -textOffset, 0, textOffset);
            }
        }
    }
}

Notes:

  • If you want the text to be centered on the overall button, rather than centered on the available remaining space, set imageWidth = 0
  • If you only want this to apply to some buttons, create a new class that extends Button and set the ExportRenderer to that new class. Then only use that new class where you want the text centered.
  • This only works for left-aligned images, but similar math can be used for the other alignments
  • There seems to be a bug where Xamarin/iOS ignores the inset if you return to a page containing the button by hitting the 'back' button on the navigation menu. I haven't been able to find a workaround to this bug yet.

Solution 2:[2]

Try to use ButtonContentLayout.ImagePosition property:

https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.button.buttoncontentlayout.imageposition?view=xamarin-forms

Solution 3:[3]

do you know how I could set it from Control in ButtonRenderer?

You can change the ImageEdgeInsets and TitleEdgeInsets of the button in the renderer to change the image and title position:

[assembly: ExportRenderer (typeof(Button), typeof(MyButtonRenderer))]
namespace App650.iOS
{
    public class MyButtonRenderer : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);


            if (e.NewElement != null)
            {
                //Control is UIButton
                Control.ImageEdgeInsets = new UIEdgeInsets(0, Control.Frame.Size.Width - (Control.ImageView.Frame.Size.Width), 0, 0);
                Control.TitleEdgeInsets = new UIEdgeInsets(0, 0, 0, Control.ImageView.Frame.Size.Width);
            }


        }
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Alexey Strakh
Solution 3