Custom Sub Views

Day 11

Placing and drawing UIView objects using the Object Library works a lot of the time, but there are instances where you’ll need to create your own custom views. A sub view is just a UIView object placed within a parent view. They can be created through the GUI by dragging out an object such as a button or label, or programatically.

There are two common reasons why you’d want to create a custom sub view:

  1. You want create a custom drawing on the screen; or
  2. You want to handle touch events in a way different from the defaults
I’m creating this using a new, single-view application project.

Create Custom UIView Subclass

With your project open, create a new file by going to File > New > New File.. (or press the + button at the bottom-left of the Project Navigator). Choose Objective-C Class:

Then enter a name for the custom view, making sure you choose UIView from the subclass dropdown:

Your new class’s implementation file will look something like this:

Note the drawRect: method is commented out by default. You should leave this commented out unless you plan on doing some custom drawing. In this case, I do want to draw a custom shape, so I’ll un-comment it and add the following (I’ll explain more about drawing in a later post):

Adding Custom View Using Storyboard

Now that I’ve created the view class, I need to add it to the screen. On the storyboard, drag out a generic View from the Object Library.

You can make the view as large or as small as you want by dragging out the handles or setting values on the right. Once placed, select the view and set its class to the one created earlier.

Now, once the app is run and the view loads, drawRect: will be triggered and everything that happens within that method will be run. In this case, a triangle will be drawn. Boom!

If you need to control your custom view in some way, you can create an IBOutlet for it in your controller just like any other object as described here.

Adding Custom View Programatically

There may be times when you want to create a sub view programatically. For example, say I wanted to make my triangle view appear on the click of a button.

To achieve that, let’s first delete the view object from the storyboard so that now my screen is completely empty.

First, import your custom UIView subclass to the header file of your View Controller. This ensures the Controller knows about your custom view so you can add an instance of it.

Then, add a new property, pointing to the new class, here’s what the header file looks like now:

Don’t forget to synthesize the property in the implementation file:

Next, add a button object on the screen and setup an IBAction for the button in your View Controller as described in a previous post.  You should end up with something similar to this:

Now, within this IBAction you’ll need to create a sub class, using the custom view we’ve created.

Here’s an explanation of what’s happening above:

  • Line 3: Make a CGRect that is used on the next line. The first two values (10,10) are for the x and y position within the parent view; the second two values (300,300) are the width and height of the frame.
  • Line 4: Initialise the MyCanvas view object. The CGRect values defined above will be used to define the size and position of the frame.
  • Line 5: Add the custom subview to the controller’s view.

If all went well, as soon as the user taps the button, a triangle should appear!

Opacity and Visibility

If you intend on playing with the view’s opacity, you’ll need to set your view’s “opaque” property to NO. For example:

By default, this property is set to YES, which means that it is assumed you will never change the opacity. This is for performance reasons.

Another property you may want to change is the visibility. If you want to hide your view, you can do so with the hidden property, e.g.:

Note that when hidden a view will also not handle events.

Redrawing The View

As you saw above, the drawRect: method is responsible for re-drawing your view. However, you should never call drawRect: directly. Instead you should use setNeedsDisplay, like so:

The above line lets the system know that you want to redraw the myCanvas view. As soon as it is ready (most likely instantly) the view will be updated.

Download Project File

In case it helps, I’ve uploaded the Xcode project file below:

DemoApp.zip