Endjin - Home

Button Visual States in Xamarin.iOS

by Pascal Arnould

One way to manage a button visual state in iOS is by setting a different background image for each one of the UIControlState values available: Normal, Disabled, Highlighted and Selected. If all you want is a solid colour background for each specific state, you still have to create separate images, save them as bundle resources and refer back to them in code. This feels like a lot of effort for something which should be a bit more straight forward. However one of the answers to this question on Stack Overflow provided a better solution by creating a 1×1 pixel image programmatically based on a given color. Here’s the direct port of the code in C#:

public static class ImageUtils
{
  public static UIImage ImageFromColor(UIColor color)
  {
      var rect = new RectangleF(0, 0, 1, 1);

      UIGraphics.BeginImageContext(rect.Size);

      var ctx = UIGraphics.GetCurrentContext();
      ctx.SetFillColorWithColor(color.CGColor);
      ctx.FillRect(rect);

      var img = UIGraphics.GetImageFromCurrentImageContext();
      UIGraphics.EndImageContext();

      return img;
  }
}

You can then use this utility method to create a button background images and set its visual states as shown below:

    [Register("CustomButton")]
    public sealed class CustomButton : UIButton
    {
        public const float DefaultHeight = 30f;

        private static readonly UIImage BackgroundDisabledImage =
                ImageUtils.ImageFromColor(UIColor.Gray);

        private static readonly UIImage BackgroundHighlightedImage =
                ImageUtils.ImageFromColor(UIColor.Orange);

        private static readonly UIImage BackgroundNormalImage = 
                ImageUtils.ImageFromColor(UIColor.Green);

        private static readonly UIImage BackgroundPressedImage =
                ImageUtils.ImageFromColor(UIColor.Red);

        public CustomButton(string title)
                : this()
        {
            this.SetTitle(title, UIControlState.Normal);
            this.SetTitleColor(UIColor.Black, UIControlState.Normal);
            this.SetTitleShadowColor(UIColor.White, UIControlState.Normal);

            this.SetBackgroundImage(BackgroundDisabledImage, UIControlState.Disabled);
            this.SetBackgroundImage(BackgroundHighlightedImage, UIControlState.Highlighted);
            this.SetBackgroundImage(BackgroundNormalImage, UIControlState.Normal);
            this.SetBackgroundImage(BackgroundPressedImage, UIControlState.Selected);

            this.Layer.BorderColor = UIColor.Yellow.CGColor;
            this.Layer.BorderWidth = 1.0f;
            this.Layer.CornerRadius = 5;
            this.Layer.MasksToBounds = true;
        }

        private CustomButton()
                : base(UIButtonType.Custom)
        {
        }
    }

Pascal Arnould on Twitter

About the author