Subscribe to this blog!

A custom view in iOS

iOS SDK gives you plenty of UI elements. Only armed with them you can develop pretty apps but there’ll be a time when you need to make awesome ones! For that, you’ll have to make your own UI widgets. To understand how to do it, I designed an app that shows charts with the accelerometer values.

Three simple steps for making a custom view

The first place to look for is, of course, the iOS developer library. In the ‘View programming guide‘ you can find a checklist for implementing custom views (‘Defining a custom view’ section).

My view gets the X,Y and Z values from the phone accelerometer and print them in a timeline chart. There are several items in that checklist but I don’t do any autoresizing and don’t have subviews so I skipped them.

Initialization methods

You’ll need to override the initWithFrame: and initWithCoder: methods. The former for creating the view programatically and the latter for using it in the interface builder.

Don’t be afraid. I wrote only the minimum code and it works flawlessly. The InitialSteps: method only set initial values and call the CreateGestureRecognizers: method (more on this later).

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self)
        [self InitialSteps];

    return self;
}

Drawing code

All the magic takes place in the drawRect: method. You have to override it and do your custom drawing in there. In my case, I first draw the X-Y axis. Then I transform the accelerometer values into screen coordinates and draw the dimensions lines if its button is lit. I won’t show you the code because it was made in ‘cowboy mode doing spaguetti code’ but trust me, drawing your custom view is quite easy. As the Apple guide says, you’re encouraged to write the minimum lines of code here and bound to do drawing operations. Any other task is not recommended.

Take this recommendation seriously and try to optimize the drawRect: method as much as possible. I did no clipping (draw only the values that fall within the view) and calculated the coordinates transformation inside the function. As a result, when there were lots of accelerometer values the screen refreshing slowed down. So be a nice guy and keep your draw method clean.

Gesture recognizers

If your custom view needs user interaction, you’ll have to attach the proper gesture methods. You can create your own ones or, more easily, use the ones that come in iOS. In my example, I needed to handle pinch (for zooming) and pan (for moving along the timeline). It’s quite easy to include them.

- (void)CreateGestureRecognizers
{
  UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]
                                      initWithTarget:self
                                      action:@selector(handlePinch:)];
  [self addGestureRecognizer:pinch];
  [pinch release];
    
  UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc]
                                          initWithTarget:self
                                          action:@selector(handlePanGesture:)];
  [self addGestureRecognizer:panGesture];
  [panGesture release];
}

Assign a method for each recognizer with the right signature. For example, the pinch method signature is (void)handlePinch:(UIGestureRecognizer*)sender. The sender gives you the current scale of the view, so you can do the proper calculations for zooming your content.

And that’s it! Quite simple, isn`t it? See the view in action!

  • http://twitter.com/tommypeps tommypeps

    muy wapo