I really used to find it painstaking to customize the UI of any app according to its theme, prior to iOS 5. But with the UIAppearance Protocol introduced by Apple, things have gotten a lot better. So in this tutorial, we will be using the UIAppearance protocol.
According to Apple:
“You use the
UIAppearance protocol to get the appearance proxy for a class. You customize the appearance of instances of a class by sending appearance modification messages to the class’s appearance proxy.”
Thus we can customize appearance of instances of those classes that provide support for the UIAppearance proxy. And quite interestingly, we can also customize the appearance of instances of a class when contained in a container class, by using appearanceWhenContainedIn: method.
So, you might be wondering which classes support this. I have compiled a list of classes that support this feature, in one way or the other.
Let’s get it started
[[UIActivityIndicatorView appearance] setColor:[UIColor orangeColor]];
As you can see, we set the color of our UIActivityIndicatorView as orange.
[[UINavigationBar appearance] setTintColor:[UIColor brownColor]]; [[UINavigationBar appearanceWhenContainedIn:[MyCustomView class], nil] setTintColor:[UIColor blackColor]];
Here, first we set the tint color of the navigation bar as brown color. But we have another utility that comes bundled with UIAppearance, where in, we can mention what kind of appearance we want when the object is contained in a particular UIAppearance container class. We set the tint color of the navigation bar as black when it is contained inside a container (or rather a class) of type MyCustomView. We can see, that we have two navigation bars in the screenshot above, the one in the main view is of brown color, and the one that is contained in our custom view automatically has a black color.
[[UIBarButtonItem appearance] setTintColor:[UIColor redColor]]; [[UIBarButtonItem appearanceWhenContainedIn:[MyCustomView class], nil] setTintColor:[UIColor magentaColor]];
Again, as we did for UINavigationBar, for UIBarButtonItem, we set the default tint color for all bar button items as red except in MyCustomView, where we set it as magenta. Similarly, we can also have a custom back button for our navigation bar!
[[UIProgressView appearance] setProgressTintColor:[UIColor yellowColor]]; [[UIProgressView appearance] setTrackTintColor:[UIColor greenColor]];
We set the tint color for the progress that has been made as yellow, and the
UIImage *segmentSelected = [[UIImage imageNamed:@"Segment_Selected.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12, 0, 12)]; UIImage *segmentUnselected = [[UIImage imageNamed:@"Segment_Unselected.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12, 0, 12)]; [[UISegmentedControl appearance] setBackgroundImage:segmentUnselected forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; [[UISegmentedControl appearance] setBackgroundImage:segmentSelected forState:UIControlStateSelected barMetrics:UIBarMetricsDefault]; [[UISegmentedControl appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys: [UIColor magentaColor],UITextAttributeTextColor, [UIColor clearColor], UITextAttributeTextShadowColor, [NSValue valueWithUIOffset:UIOffsetMake(0, 0)], UITextAttributeTextShadowOffset, [UIFont fontWithName:@"Courier-Oblique" size:16.0], UITextAttributeFont, nil] forState:UIControlStateNormal]; [[UISegmentedControl appearance] setDividerImage:[UIImage imageNamed:@"SegmentedControl_Divider.png"] forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
For segmented control, we give the image for the segments for both the control states i.e. UIControlStateNormal and UIControlStateSelected. We will also set the divider image. At last, we set the properties of the labels on the segments setTitleTextAttributes:. This method accepts a dictionary having the following:
- UITextAttributeTextColor – This is the color of the text. We give it a magenta color.
- UITextAttributeTextShadowColor – This is the shadow color. We give it as clearColor. If we want a kind of drop shadow around the text, we can give it some value.
- UITextAttributeTextShadowOffset – This is the offset with respect to the position of the text, at which the shadow text will appear. We give it (0,0) because we don’t want any offset here.
- UITextAttributeFont – We give the font for our text as Courier-Oblique with a size of 16.
- UITextAttributeTextShadowColor- [UIColor blackColor]
- UITextAttributeTextShadowOffset- [NSValue valueWithUIOffset:UIOffsetMake(2.0,2.0)]
[[UISlider appearance] setMinimumTrackImage:[UIImage imageNamed:@"Slider_Background.png"] forState:UIControlStateNormal]; [[UISlider appearance] setMaximumTrackImage:[UIImage imageNamed:@"Slider_Background.png"] forState:UIControlStateNormal]; [[UISlider appearance] setThumbImage:[UIImage imageNamed:@"Slider_Thumb.png"] forState:UIControlStateNormal];
For UISlider, we can set the minimum track image, maximum track image, and the thumb image. I once thought while using iBooks, on how to make a control similar to the iBooks slider, and Bingo, we get a slider exactly similar to the iBooks slider!
[[UISwitch appearance] setOnTintColor:[UIColor redColor]];
For UISwitch, we set the tint color as red color.
[[UITabBar appearance] setTintColor:[UIColor brownColor]]; [[UITabBar appearance] setSelectedImageTintColor:[UIColor greenColor]]; [self.myTabBar setSelectedItem:[self.myTabBar.items objectAtIndex:0]];
For tab bar, we set the tint color, and also the tint color for the selected items.
[[UIToolbar appearance] setTintColor:[UIColor blueColor]];
We set the tint color of our tool bar as blue color.
[[UISearchBar appearance] setImage:[UIImage imageNamed:@"Search_Icon.png"] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal]; [[UISearchBar appearance] setImage:[UIImage imageNamed:@"Search_Cross.png"] forSearchBarIcon:UISearchBarIconClear state:UIControlStateNormal]; UIImage *searchBg = [UIImage imageNamed:@"Search_Background.png"]; searchBg = [searchBg stretchableImageWithLeftCapWidth:10 topCapHeight:10]; [[UISearchBar appearance] setBackgroundImage:searchBg];
This is one of my favorites till now. It gives a completely new look to the search bar. Here ,we give an icon for the search bar, as well as an image for UISearchIconClear, the red circle with a cross inside it. This appears when we enter anything in the search field. We also set the background of our search bar.
Not every UI customization method in a class will respond to the appearance proxy protocol. Apple documentation clearly states:
“A class must adopt the
UIAppearance protocol to allow appearance customization using the
Another one is to open the class in Xcode, i.e. if we want to look at what methods are there in UISegmentedControl that support UIAppearance proxy, we can open UISegmentedControl.h from Frameworks ->UIKit.framework -> Headers ->UISegmentedControl.h and search for the keyword UI_APPEARANCE_SELECTOR.
Moreover, one more trick is to open the class reference, and there will be some methods under a heading that mentions something about customizing appearance. For e.g., in UITabBar class reference:
Give me the Code!
As usual, you can grab the source code for the tutorial: AppearanceProxyDemo.