UIAppearance Proxy Protocol Tutorial/Example

来源:互联网 发布:java连接rac io异常 编辑:程序博客网 时间:2024/05/20 22:35

http://www.ioslearner.com/uiappearance-proxy-protocol-tutorial/


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.

  1. UIActivityIndicatorView
  2. UIBarButtonItem
  3. UIBarItem
  4. UINavigationBar
  5. UIPopoverController
  6. UIProgressView
  7. UISearchBar
  8. UISegmentedControl
  9. UISlider
  10. UISwitch
  11. UITabBar
  12. UITabBarItem
  13. UIToolbar
  14. UIView
  15. UIViewController
We will take down each class that supports UIAppearance proxy one by one in this tutorial, however it is important to note here that from the above list, UIPopoverController, UIView and UIViewController are UIAppearance containers.

Let’s get it started

Ok, so let’s get started with the project. We open our Xcode (The Xcode must be version 4.2 or 4.3, because UIAppearance proxy is supported only in iOS 5.0 and above). We create a new project and name itAppearanceProxyDemo. We make sure that “Use Automatic Reference Counting” option is checked, and other two options are unchecked as follows:
Appearance Proxy- Create Project
To demonstrate UIAppearance containment, we will also make a UIView subclass, and name itMyCustomView.
We will open our ViewController.xib, drag a view, and make its class as MyCustomView. Along with that, we will drag lots of controls it, and our final app customized with the help of UIAppearance proxy protocol will appear as follows:
UIAppearanceProxyDemo 

UIAppearance UIActivityIndicatorViewUIActivityIndicatorView:

View Code OBJC
    [[UIActivityIndicatorView appearance] setColor:[UIColor orangeColor]];

As you can see, we set the color of our UIActivityIndicatorView as orange.

UINavigationBar:

UIAppearance UINavigationBar

UIAppearance UINavigationBar UIAppearanceContainer

View Code OBJC
    [[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:

UIAppearance UINavigationItem

UIAppearance UINavigationItem UIAppearanceContainer

View Code OBJC
    [[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: UIAppearance UIProgressView

View Code OBJC
    [[UIProgressView appearance] setProgressTintColor:[UIColor yellowColor]];    [[UIProgressView appearance] setTrackTintColor:[UIColor greenColor]];

UIAppearance UISegmentedControl

We set the tint color for the progress that has been made as yellow, and the

UISegmentedControl:

View Code OBJC
    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.
For demonstration to see how shadow text would look like, we will give the following values:
  • UITextAttributeTextShadowColor[UIColor blackColor]
  • UITextAttributeTextShadowOffset[NSValue valueWithUIOffset:UIOffsetMake(2.0,2.0)]
We will then have our segment control look like this:
UIAppearance UISegmentedControl Shadow offset

UIAppearance UISlider UISlider:

View Code OBJC
    [[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: UIAppearance UISwitch

View Code OBJC
    [[UISwitch appearance] setOnTintColor:[UIColor redColor]];

For UISwitch, we set the tint color as red color.

UITabBar: 

UIAppearance UITabBar

View Code OBJC
    [[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: 

UIAppearance UIToolbar

View Code OBJC
    [[UIToolbar appearance] setTintColor:[UIColor blueColor]];

We set the tint color of our tool bar as blue color.

UISearchBar: 

UIAppearance UISearchBar

View Code OBJC
    [[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.

Quick Tip

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 UIAppearance API.

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 fromFrameworks ->UIKit.framework -> Headers ->UISegmentedControl.h and search for the keywordUI_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:

UIAppearance trick

Give me the Code!

As usual, you can grab the source code for the tutorial: AppearanceProxyDemo.