App Frameworks • iOS • 47:11
With iOS 5, you can customize the look of your app controls using the new Appearance APIs. The new Appearance Proxy API allows you to efficiently apply a custom appearance to your views and controls, including built-in controls such navigation, tab, and toolbars. These customizations can be applied across your entire app or independently on a per-control basis.
Speakers: Marian Goldeen, Chris Parker
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Good afternoon. Welcome to Customizing the Appearance of UIKit Controls. My name is Chris Parker. I'm an iOS Frameworks Engineer. I work on UIKit. And we're going to spend the next hour or so talking about all the stuff that we've added to iOS 5 that allows you to get your custom look into your applications.
So our standard look is pretty straightforward, right? This is mail on the iPhone. We've got that sort of blue-gray look at the top for the navigation bars and the toolbars. That color scheme is pushed throughout the application as you navigate using push and pop and view controllers. The toolbar buttons are all that white etched look. And, you know, it's a very straightforward, it's a very clean, basic look. And it's a good starting point for a lot of applications.
But now that we've seen so many applications on the store and all of the really custom artwork things that people are doing to support their features and to really distinguish your applications, it's clear that we've needed a little more to be able to give you guys a lot more help in customizing UIKit.
The iPad has a very silver look to it, right? The toolbars and nav bars are all that gray look. All the gray tint color is pushed through it as well. Same thing. As you push and pop navigation controllers, you get, you know, that same gray bar. You'd like to be able to customize all of that stuff too.
So I thought we'd start with sort of a very basic application as an example here on the slides. You might be creating, say, a control application for a conference room. So you'll have things like the level of the house lights or the talk progress or the voltage that we've got wired up to the chairs. Yeah, you thought those power strips are all for you guys, right? And, you know, the projector being on or the demo computers being on and the bar button items that appear there.
And your designer comes to you and they say, you know, I've got a really great idea. Let's push a different color scheme through your entire application. Let's do that. So we've added tint color to almost every single control in UIKit. So if you've got a color scheme that you want to push through it, you can do this now.
So this includes things like the navigation bar and toolbar colors, the text that's in those buttons, the tracks for all the different UI sliders and progress indicators, the activity view, UI activity indicator view, right just to the right of the talk progress bar. You can color those now, too.
And you can get a, you know, you can choose your color scheme. We do take the tint color that you give us for all of these things and, you know, we might massage the color a little bit one way or the other depending on what the background of the control originally was. But you can get a nice blue look also just by pushing UI color blue color all the way through. You can also do some really terrible, awful things.
Don't ship this, please. So, you know, when your designer says, "Wow, maybe you shouldn't use quite those colors," they probably know what they're talking about. We've also gone through and put in support for going from this, which is again our very basic look, to something more like this. And that includes image support in almost every single control in UIKit.
So here is a UI navigation bar with a different image as its background. All of the tracks that are here for the UI slider, the button has a different color, but the chair voltage slider there has a different image for its minimum track. The talk progress bar has an image. The buttons all have their own images. These are all things that are built in right now. And the first thing to talk about here is navbar. Set background image for bar metrics.
Pre-iOS 5, we've seen some fairly novel approaches to getting this to work. We do support this. It's not obvious. If you need to do this kind of thing with a navigation bar, the way it works pre-iOS 4.0 is you would create your navigation controller in a nib, select the navigation bar in that nib, and set its custom class to your subclass. And then when that whole thing comes up out of the nib, you'll get your navigation bar in there. So you don't have to resort to the method swizzling and the category smashing to do this.
But in iOS 5.0 now, you just have to call setBackgroundImage for bar metrics and we'll take care of it for you. The bar metrics are just an enum. UI bar metrics default is the 44-point high UI navigation bar that you get on the phone in portrait and on the iPad in all orientations, right? The iPad's big enough that we don't have to shrink that bar.
UI bar metrics landscape phone is the one where when you rotate the phone to landscape phone, we make the navigation bar thinner because we want to get as much space as possible for the content of the navigation controller and not for the navigation Chrome itself, right? So we've also gone ahead and allowed you to do title text attributes.
So not only do we're putting images in here for customization, you're also going to be able to get your own fonts and colors and things like that into the nav bar. And it's not shown in this particular slide, but left bar button items and right bar button items. These are properties where you can set an array of bar button items rather than just one on each side.
And finally, also, Left Item Supplement Back Button is kind of neat. As you push and pop view controllers, the back button, since you could only have one, you had pretty much the back button and that was it. You can set this property and as you push view controllers in, if they have left items, they will show up to the right of the back button there. So you can start putting buttons up next to the back button and have those dynamically come and go. There's not a lot of space up in the navbar. You can see that right now. So this is sort of a used judiciously feature.
For bar button items, you can do the same thing. Set background image for state bar metrics. And for the back button, you can also set the back button background image for state bar metrics. So you'll be able to wedge in your own images for all of these buttons.
So as your designer comes up with their snow leopard print flavor of bar button items and they want to put something specific in there, you'll be able to actually accommodate that just by taking the images in and using them directly. Marian Goldeen, our iOS Frameworks resident mountain biker who puts us all to shame with her effort in getting into work every morning, is going to show you some of the customizing instances API that we've added to UIKit. So, Marian, for the demo.
Thank you, Chris. And we'll have our demo showing up here in a minute, I think. That looks better. All right. Thank you. So first I'm going to just walk you around this application, this demo application, to get you oriented. It's a simple application. It's a faux astronomy application using images from the Hubble telescope. And as you see, it's in a tab bar controller with two tabs. The first tab is just a regular old view controller. We have a toolbar at the top, and we have the beginnings of our theme with dark bars and reddish text.
The title is a custom view bar button item, which is a label that's been customized. And if we go over to the second view controller, we see that we have a navigation controller, and we have white text up there, which is unfortunate. And the same thing, it's got white text in the buttons, the next button and the back button.
And for the title, you know on iOS 4 we could do the same thing that we did in the toolbar, which is we could take a UI label and customize it and use it as a custom view for the title view. We're a little more stuck for the button items, and it's also kind of a pain to do that for every single view controller. So let's do it using our title text attributes.
Now we have to go find our code. And in application didFinishLaunchingWithOptions in the delegate method, in the delegate, we have-- That's where our navigation controller is set up, and it's a good place to set the title text attributes on our navigation bar. In this case, I'm only interested in the text color. You can set text color, shadow color, shadow offset, and also the font.
And we need to do the same thing for the navigation bar button items. Those are set up in the second view controller because, as you recall, the bar button items are associated with the navigation item for the view controller. And I took a shortcut, and I've only got one view controller class, but you could possibly have more than one. And to customize the back bar button item, we need to make a custom back bar button item. This is a template. We take certain things from it to construct your back item. And one of the things we do take from it are the title text attributes.
And we set them twice because I want one color for the normal state of the control And I want a slightly brighter color because my standard color has a diminished alpha to give it a sort of a diminished state because I want a quiet UI for the highlighted or pressed state of the control. And we want to do the same thing for the next item. And it's exactly the same thing. Set title text attributes for state. And let's take a look at how it looks.
Go over to our navigation bar. And sure enough, nice and red, just like we wanted for all of the views. Well, that takes care of the top bars. But looking down at the tab bar, it's blue. It's not red. We're OK with the unselected tab bar item with that gray, but we want red for the selected tint color, and we want red for that selected text color. Once again, we can take care of it. We have to remember where our instances are. The tab bar controller is again set up in the application delegate. Let's go back to that. The application did finish launching.
And you can get the tab bar from the tab bar controller. And you can set its selected image tint color to red color or any color you like. And we'll do our best to make it look nice for you. And the tab bar items, we have one for each view controller. One for the navigation controller that's set up here. Also, an application did finish launching.
And we're setting the title text attributes, this time just once for the selected control state, which is the state that the tab bar item is in when it is selected. And we need to set the same thing on the other tab bar item for the first view controller. Here in Init with NibName, where the tab bar item is set up, is a good place to also set its title text attributes. So now let's take a look at that tab bar.
and hooray! It's red. Yay! Yes. Well, that looks good, and it's all sort of red. It actually matches that nice image of the supernova remnant. But suppose we have some controls for scanning the universe, and we don't want them to be blue and white, so let's customize them.
All those controls are set up in the first view controller. I should point out to you that in order to set them up, I have IB outlets for all of them. I might want IB outlets for them for other reasons also, but I definitely need them to customize them this way.
And so we set the on tint color for the scan switch. We set the color for the spinner. The progress view, we can set the progress tint color and the track tint color. You'll notice I'm using the same color for both. In this case, we adjusted a little bit so that it'll actually look a little different.
For the slider, we're a little more prosaic, and you set all three colors, the thumb, the minimum track, the maximum track, and you just set them up. Now, the segmented control is what I'm going to do next, and tint color works on the segmented control in the bars, but we haven't applied it to the segmented control in Lucentive View like you saw there. But what you can do is you can customize the look of your app controls. So I'm going to customize its background images completely, and so my designer alter ego created some images that I can use for the segment background.
And I'm setting it for the normal control state. And in this case, the bar metrics don't apply to this particular segment of control. If it were in a navigation bar on the phone, it could very well apply. But since it doesn't apply, I'm using UI Bar Metrics default.
I also want to set this for control state selected. And a moment here, because Sigma Control is a little complicated. It doesn't just have a background. It also has the divider image. And the divider image-- in our case, I'm using the same divider image in all cases. No, thank you, Xcode. All right.
But in a more complicated image, you might have a case where the divider image would actually be different for shadows or whatever purpose, depending on which side there was a selected image. So that's what this for left segment state, right segment state arguments are all about. In my case, it's more simple and it doesn't matter, so they both get UI control state normal. And similar to the bar button items, I set the title text attributes. So let's see how that looks.
Much better, much more like the rest of the app. And I feel like, hey, this is pretty good. It's all black and red. I'm good to go. And then my designer says, well, actually, those images for the segmented control, they're all flat. And I want a consistent design language through this app.
And I want other images. I don't like this shiny bar. I don't like this shiny selection indicator image in the tab bar. I don't like these shiny buttons. I don't like these shiny buttons up here. Here's a bucket of flat artwork. Please put this into your app. Why, certainly, say I.
Let's see. We've got a background image for the toolbar, and here we are in our first view controller, and it's got an outlet for the toolbar. And it's actually the same background image for the navbar and the toolbar. Now, the toolbar has a special thing, toolbar position. Take a moment here. Toolbars can be at the top of your app or at the bottom, particularly on the iPad. And my artwork doesn't care, so I have UI toolbar position any. But of course, you could also have top or bottom if you had specific artwork for those positions.
So we have the toolbar, and we also have some other bars. We have a navigation bar background image. Again, the bar metrics. And we have a tab bar background image. No bar metrics for the tab bar because it's the same size. And we have the tab bar selection indicator image. And there was only a couple more, the back button and the next button. So let's take care of those.
And here's where we got the title text attributes. Notice with the back item, we have set back button background image. And we're doing a normal state and a pressed state. And for the next item, we have background image, just not back button background image, but just background image. And that should complete our customization of this application.
And there you go. You see the flat images. We still have our nice red colors. And perhaps you notice the-- can you see it well enough, the flat image down there around the tab? And also, maybe you can see these better up here at the top. And you see we have different ones for the pressed states. And now we have-- thank you.
This is kind of an overview of the customization. It is not at all a complete list of the customization methods that we have. Please feel free to read the headers and look for things that you might want to do because it's very likely to be there. But we have more in store for you, so I'd like Chris to come back and give us some more talking with some slides.
We were going to do the reading header thing, but I heard Craig did that joke on Monday, so I'm not going to do that here. Quick show of hands, how many of you completely lost track of where Marian was in the view controller stack customizing all of those various UI elements? Excellent. Don't feel bad. I get lost with it, too. It turns out that if we're going to write customization API to customize the entire look of an application all at once, it's really hard.
If you've used other frameworks that do this kind of customization for look and feel, there's lots of different axes you can control. There are lots of sort of out-of-band things that you call in order to get that custom look in terms of theme files and things like that into an application. We wanted to try and make this as easy as possible because it also turns out that using those customization APIs after you've built all of those things up is hard. So it's hard for us to write.
It's hard for you guys to use. So we wanted to do... We wanted to do three things. We wanted to make this API as easy as possible to provide a consistent look in your applications, and that look should support your application features. And we looked at what we were doing with all of the different customization in UIKit on a per-class basis and tried to work all of this out, and it was really difficult. So we went back and looked at how we configure individual instances. So this is a UI slider. You saw Marian's demo. Where she was customizing it by calling set minimum track tint color, and you pass it a color, and we go ahead and color that slider red.
But if you want to do this for every single slider in your application, well, there are a couple of different ways we could have approached it. You could wrap this method in a useR theme for every single different customization for your classes. Or we went ahead and introduced this idea of what's called the Appearance Proxy. So you will send the appearance message to the UISlider class.
That gives you back a proxy object that's going to stand in for all of the future customizations you're going to do for, in this case, a UISlider. You'll send that object the setMinimumTrack tint color, and every UISlider you create in your application now will have that tint color.
So if you know how to customize one instance, a specific instance of a control, you now know how to customize every single one of them. Again, this is called the Appearance Proxy. If you've done any of the desktop programming on the AppKit, they have a similar concept with the Animator Proxy.
You load up all the different animations you want. And when you commit the animations, the proxy plays those back. That's what this is basically doing here, but it's for appearance and for the customizations we've put. And all of these methods for like set minimum track tint color, they all participate in this system.
The header is uiappearance.h. We've defined a single protocol called the UIAppearanceProtocol, and we've applied this to UIView and a few other classes. So anything that conforms to the UIAppearanceProtocol, you can send the AppearanceClass method to. That gives you the proxy object to send all of your different customizations. And we've also gone through and tagged the methods that are currently supported with UIAppearanceSelector. And this is just a little pound to find that tells you which things we've worked on and tested out to make sure that they work.
We're sprinkling this through additional methods as we go, so this will start appearing in more and more places. But please do try all of these things out for that. And this system is going to let us do something a lot cleaner than what Marian was showing you earlier. And so she's going to show you more about AppearanceProxy basics and how to configure your application.
Thank you. So for this demo, I'm going to pretty much go through that app that I just went through before, and this time I'm going to do all the customizations using the Appearance Proxy. I've actually adjusted the app just a little bit and put two navigation controllers where I haven't set the bar style yet because I'm going to set them both at once. And I just want to take a minute and look at the pictures so you can see there's some neat-o pictures. Great website, hubblesite.org. Anyway... So let's get started and customize it using the Appearance Proxy.
So in this case, I'm going to just stay inside one method. In the application delegate, the application did finish launching method. And as I recall, I started with the bars, the navigation bars. So let's set the bar style on the navigation bar appearance. Similarly, we'll set the title text attributes. I'm going to take care of doing the bar customization that I did at the beginning of the demo before. And we need to set-- The tab bar selected image tint color. And I remember the bar button items. They had title text attributes.
Those title text attributes on the UI bar button item appearance will be applied to all the bar button items, including the back button. And so we've got the navigation bar, the tab bar, and the title text attributes. And, ah, we needed the tab bar item title text attributes.
So once again, you notice it particularly simplifies for those bar items in this particular demo. Let's take a look. And there we go. We have our selected image tint colors, and our navigation bar has been customized. After we did that, we took care of these controls. So let's take care of these controls.
In this case, we don't need any outlets for this, although, like I said, we might need them for something else. So we want our switches to have that on tint color. We want our activity indicator views to have a color. Take care of the progress view. The slider. And we can do the background images and such on the segmented control as well.
So here we go, background image for normal state and selected state, the divider image, and the title text attributes. So this should take care of our controls. And there we go, all nice and red. And of course, last but not least was the flat images for the bars. Let's take care of those.
The navigation bar. The toolbar. Counting on my fingers here. The tab bar. So the tab bar has both the background image and the selection indicator image. That belongs to the tab bar. And then we have the background image for UI bar button items. So this is the square image. And then we have-- The back button background image for UI bar button item, and that's the pointing image.
That covers it. I don't see any more gray code in there, so I think I got it all. And yep, we've got all of our flat images all in one place. And the customization will continue if I change the app. I don't have to worry about putting additional instance calls on every new instance that I add. Marian Goldeen, Chris Parker And that's a simple way to use the Appearance Proxy, but there's a more complicated way to use it, too. And Chris has some slides to help you get acquainted with that.
So there are a lot of really slick things here. But the appearance proxy lets you consolidate the repeated code of taking an instance and configuring it, and taking an instance and configuring it, and put all of that logic in one place so you can do it once. And you can break these up.
So for instance, if you know that you're never going to load a particular control until much later, you can call it just before you load that control and then go ahead and do it. So if there are places where you're worried about performance or you just don't want to do all of that right in one place, you can do it on an on-demand basis. It starts taking effect right after you call these things.
So your designer comes along and says, hey, you know what? We've got these buttons. And I want them to have the default look all the time, but I want them to have a different look only when they're contained in this other view controller. And in this case, I'm going to put a button into a navigation controller, and we want that to always have the red text color if it's in a navigation controller, but we want the default color at all other times. So the only other method in the Appearance Proxy protocol is Appearance When Contained In.
And this is a way that you can do fine-grain control over how the appearance of your app changes depending on what views and view controllers these things are all contained in. It takes a nil-terminated list of classes, and those classes will conform to the UIAppearanceContainer class. And this is an empty protocol that we use to tag the views and view controllers that participate in this containment system.
And it's as simple to use as the Appearance Proxy by default. So here is the button code to illustrate the concept that I just showed you in graphics there. UIButtonAppearanceWhenContainedInUINav igationControllerClass, setTitleColor, red color for control state, UI control state normal. So again, the same configuration API for an instance gets applied to this containment system.
And then when we go ahead and actually put that button into the nav controller, it changes color. You can do more complicated things. Like you can set the appearance when contained in a custom view controller in another view controller. So you can set up hierarchies for your appearance changes.
So in this case, this is an appearance proxy being asked for that when the button is in a custom view controller, which is itself inside a navigation controller, that should change. So here's the button with a bare custom view controller. into it, nothing happens. Put that whole thing into a UI navigation controller, and the title color turns red.
So when your designer says, well, I want just this corner of the application to look different, you'll be able to do that. You know they're thinking about it. You know they're out there in front of Photoshop going, oh, you know what we could do? So the way to read this is almost the way I read it before, which is it helps if you put the when contained in between each of the classes that you're passing in. So you would read this as the button's appearance when contained in a custom view controller when contained in a UI navigation controller. It sounds a lot like most of our selectors when you read it out, but it's very descriptive and it'll help you get the containment idea.
This works based on the outermost containment for composition. So if you have some competing containers where you might have A, B, and C, and if B and C are further out, the outermost containment winds up winning. It'll take some experimentation. It's worth opening up Xcode and creating a couple of different view controllers and putting them inside of each other to see exactly how this stuff plays out, but we'll have some documentation for this as well. Marian's going to show you now about how to use containment to tweak the look of your application in different circumstances.
Well, my Scanning the Universe app has had an upgrade. And now when I bring up my controls, I get a new little item up here. I actually want to just call this out here. That's a plain toolbar, but an item that's been tinted. It's not white. Just take note.
So there's our control panel. You notice we're getting those red looks from the Appearance Proxy, but our designers have given us an Emerald City look to apply only in these control panels. And we've got three of them for Auriga, Bootes, and Cygnus. And they all have to be green. The view for this view controller is a controls view class. So this is a trivial subclass of UIView, and I'm going to use it for my containment.
So here's our back in the application did finish launching method in the Appearance Containment App Delegate. We have all that stuff from the previous demo. And now we have our contained appearances. And the first one, this is just the plain old Appearance Proxy so that the controls view actually has a background color that is green.
And the next one, we want our labels. They've got their own color. But we want them when contained in the controls view class. I want to say a word here, which is that UILabel is a pretty general class. And there are subclasses lying around where you might be surprised. So if you just say UILabel appearance and change some stuff, you might get some changes you didn't expect. So you would proceed with caution and probably always want to use containment if you were sending messages to an appearance proxy for UILabel. Similarly for UISwitch.
UI slider. And then UI button here. You notice I'm setting a background image. The particular button I'm using in this control panel doesn't accept tint color. Some of our buttons do, but you can set the background image on any of them. I believe that's not new, but we're sending it to the Appearance Proxy. So we have a normal state and a pressed state, and then title color. And let's take a look.
And it's green. You notice that the red switch down there stayed red, and these switches are green. We're all happy about that, and then our designer says, "Well, I want the Bootes View Controller to be blue because it's the booties' blue view controller. Okay. And you say, "Well, but you want Auriga and Cygnus to still be green." They're like, "Yes." That content view, the controls view, is contained in the view controller, and each of these three view controllers is their own class, so we can use the containment in the Bootes view controller to control the appearance of that pane.
So we just basically run through the same thing except with the different colors and images for the appearances when contained in the BoOT's ViewController class. So in this case, these controls, even though they are contained in the controls view, they are also contained in the Boötes view controller. And that's the more external container. So it's the one that will rule for these ones.
So let's look at that. And of course, the first one that we look at is the Bootes ViewController, supposedly. There we go. And it's blue. Hooray. And as you saw-- and Signes are also green. And everything's working as planned. And then our designer has another idea and says, the three fates, Clotho, Atropos, and Lachesis, are much more important than the three musketeers, Athos, Porthos, and Eremis, and they deserve a switch color all of their very own.
Well, of course, you're like, no problem. Containment will do it. And because you were precognitively designing your demo app, you've already got your switches in their own view. So there's an invisible subview here containing those switches. And I've called it Important Controls View. And like Controls View, it's another trivial subclass of UI view being used purely for containment. And I say, OK, how about that? The ones that are in the Port and View Controller They're going to be this important color. And I think I'm going to be good, but you might be seeing that other gray text and thinking, huh.
And so I go and I look. Did it work? It did not work. And the reason it didn't work is because for this containment, it's the outermost container that's ruling when the specificity is the same. So these switches, the three fate switches, are contained in the important views controller, important controls view, but they're also contained in the controls view, which is the outermost, and so that appearance is winning. So this is one place where we'd use the specificity.
Because if they are also contained in something that contains the controls view, then we'll be good. And those three view controllers, Oraiga, Bootes, and Cygnus, are all subclasses of a common view controller called a controls view controller. Say that three times fast. And so if we extend our containment so that we want the switch that's contained in the important controls view class when it's contained in a controls view controller class, we want it to be this important color. So let's look at this wonderful importance.
There they are. They're yellow, and it's the same for all three panels. That. And, of course, Cygnus is just a repeat of Auriga. Now, at this point, I could be done. I've pretty much showed you the containment. But I have one little extra thing that if you've been to What's New in Cocoa Touch and some other talks, you might have heard about. And I just wanted to throw it in there to remind you, which is that we have places all over UIKit now where you can set background images.
So much everywhere you can set an image, you can set an animated image. And that's-- the animated images is pretty nifty. A bunch of images, I don't know if you can read that, but they're all enumerated, and I just say I want my Cygnus button animated image duration of one second, and I have one for... One for normal and one for pressed. And then I can have a nice pulsing button. It's kind of fun.
for the Cygnus button. Okay, so I'm-- I'm really not quite done. Because you guys are saying, yay, that button's pulsing. And I'm saying, oh, no. Because the center of that button is going translucent. So what's that white stuff behind it? It's supposed to be green behind it. This one's supposed to be subtle because it's not pressed.
And that one, when you touch it, is supposed to be more dramatic. But it's less, and there's something blue behind it. Well, what's going on is I just set that image on a rounded, racked button. And it has its own drawing. And we're seeing a little bit of a collision here.
So if you see something like this, and you want things to uncollide in your buttons, it's a good idea to set up your button-- and John Ebrecht set it up as a custom button because you are customizing it. And then you won't have to worry about UIKit drawing getting in there and fighting with what you want to have happening.
Okay, and so now it's more subtle. Actually, I'm not sure if you can see it very well, but it is pulsing. You can see and what I wanted, where you have a more vivid pulse on the pressed. You can see that more, and we don't have the rounded rect fighting with the custom drawing. So I think that's a good overview of the new stuff we have in store for the appearance customization. And Chris has a few more slides to point out what's going on behind the scenes a bit.
[Transcript missing]
And it does update in real time. It happens only at the hierarchy change point, right? So if you're going to be dynamically changing this stuff, you'll have to take the view out of the view hierarchy and put it back in in order to get it to happen.
So we've spent a bunch of time in pushing all of these different customization APIs all the way through UIKit, but your designer then says, "Hey, you know what? I've got this button, and I want it to have the same color no matter where it appears in the UI.
Right, so we've got this button. This app button isn't making anybody nervous, is it? And if I call Customization API on that particular instance-- remember, we've got all these other customization rules going on for buttons. They're getting tinted. There's an animated image on the back. But I'm going to go ahead and call Set Title Color for Control State on this particular instance of the button.
Now, when I, you know, it goes ahead and it's, okay, it's green. I've updated that color. Now, when I go ahead and put that into the navigation controller, if we think back to the original containment example, this has a custom view controller inside a nav controller. We're saying any button that appears in there is going to be red.
Well, you take this button that you customized individually and put it in there, it's not going to be red. It's going to stay green because we also keep track of all of the individual instance customizations you do, and we keep our hands off them. So you'll be able to actually say, for this button only, ignore all the rules and make sure it's always green. So you'll be able to also customize individual instances.
So we pushed all this stuff through into the headers. We've got lots and lots and lots of customization opportunities now. So you should be able to get your custom look into your application and customize it really easy using the Appearance Proxy. We've also provided a really sophisticated containment model so that you can tune the appearance of your application based on context and the containment hierarchy of your view controllers. And we've also put all of the image stuff in there so you can completely customize your look and push all of those images into every single UIKit control. So we're here in the labs for the rest of the week.
You can also get more information from our Application Frameworks Evangelist, Bill Dudney. There will be docs in the iOS Development Center about all of the appearance stuff that we've talked about today. And, you know, come see us in the labs with all your questions and your code. We'd love to talk to you. Thank you very much.