Knowledge is power. We love to share it.

News related to Mono products, services and latest developments in our community.

mario

Creating transparent rounded buttons in MonoTouch

09/27/2012Categories: Mobile

Almost every development famework provides a way to create custom UI controls. In iOS, such controls are called Views. Every view can hold a collection of child views, and each subview can hold even more views, etc. You’ll notice that I’m using a term "control" interchargeably with the term "view".

I wanted to create custom view which will have transparent background and circle drawn in middle and will behave as any other button. Also, our control will behave dynamically and have a different appearance that is controlled by application logic.  I have found numerous articles explaining how to draw custom graphics on a view, but there were very little information on how to change the control's appearance from the application code.

Creating Project And Views

We will create our control and test it in a Single View Application project, so we'll start by creating a new project in MonoDevelop.

New project

We will create our control as a new view without an accompanying controller, because it requires a parent view with a controller. We will add an empty class to our project and name it UICircleButton to follow the naming logic from MonoTouch.

New class

Since we want our control to behave like the standard UIButton view, we will inherit from it and change the generated code to call the base constructor.

Custom drawing in a view is done by overriding Draw() method. We’ll be moving this control around the screen and alter its appearance depending on the input data.

public override void Draw (RectangleF rect)
{
     base .Draw (rect);
       
     DrawCircle ();
}
public void MoveTo ( float x, float y, UIColor titleColor)
{
     this .X = x;
     this .Y = y;
     this .SetTitleColor (titleColor, UIControlState.Normal);
     InitView ();
     this .SetNeedsLayout ();
}

Be sure to call SetNeedLayout() here because our control is changing its position and we need to notify the application to "re-layout" the subviews. If you don’t call it, no changes will be visible. Note that if you call SetNeedLayout() then a call to SetNeedsDisplay() is not needed.

public override void SetTitleColor (UIColor color, UIControlState forState)
{
     base .SetTitleColor (color, forState);
     this .SetNeedsDisplay ();
}
We are overriding the existing SetTitleColor(), as SetNeedsDisplay() should be called to signal that a view needs to be redrawn, and I wanted to avoid calling it from the controller.

Adding Custom Graphics

To add custom graphics to the view you need to override the Draw() method of a base view add implement its drawing logic there. The process is really simple - we get the current graphics context, set some of our custom appearance properties, and add a circle to the context. We are drawing our circle in the top left corner.

public void DrawCircle ()
{
     CGContext cgCtx = UIGraphics.GetCurrentContext ();
     if (cgCtx != null ) {
         cgCtx.SetLineWidth (LineWidth);
 
         this .TitleColor (UIControlState.Normal).SetStroke ();
 
         cgCtx.AddArc (Radius, Radius, Radius - (LineWidth / 2), 0, 2F * ( float )Math.PI, true );
         cgCtx.StrokePath ();
     }
}

Using UICircleButton

We are using this control as any other control in MonoTouch - by creating a control instance, set the frame and add it as a subview of its parent. You can choose from several constructors:

var circle = new UICircleButton (50, 100, 20, 3, UIColor.Red); T

To move the control to another position and, optionally, set a new title color we can use:

circle.MoveTo (50, 100, UIColor.Red);

To set a different title and color use:

circle.SetTitleColor (UIColor.Blue, UIControlState.Normal);

As I said, this control is behaving as a standard UIButton control, so clicking outside the circle, but within the borders of the control (invisible corners), will still raise the control events. To avoid this you can override TouchDown() event and implement code that checks the exact coordinates of a click, and calculate if it happened within the specified radius around the control center. 

Sample Code

Attached is the sample application that contains all the code discussed in this post. When started, it displays the start view with the 'Click to draw' button. When this button is clicked, a rounded button will be created and placed on the screen. On each subsequent click on the button will change its color and/or position.

Rated 5.00, 3 vote(s).