Frameworks • iOS • 55:38
UIKit provides powerful customization capabilities for iOS views and controls. Learn how to customize the look and feel of your app to embrace the new UI of iOS 7 and see how to effectively use tinting and images to create an immersive, high quality user experience.
Speaker: Jacob Xiao
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript has potential transcription errors. We are working on an improved version.
[Jacob Xiao]
Hello everyone. You've all seen iOS 7's amazing new design and big part of that change is there's a lot less ornamentation, which is a big part of what used to make a lot of applications unique. So you may be wondering how you can make your application stand out in this new world.
Well, there's still a lot of ways that you can customize your application including several new ones. So today, I'd like to talk about how you can customize your application to make it still have its own unique appearance, but fit in with the rest of the iOS 7 design.
I'll be talking about three things today: First, some of what's changed for customization in iOS 7. Then, some advanced topics for how you can customize your application and finally how you can create your own custom controls that work just as well as our UIKit controls. I'll be using a sample application today that looks like this.
It's a simple application that's a combination of messaging and what I think is the greatest game of all time, Tic-Tac-Toe. I think it's going to be a big hit. This is what it looks like today. It's a simple standard uncustomized iOS 7 application, but we're going to be customizing it to look like this.
And I'll be telling you all of the different customizations we use and how you can use them in your application as well. And one important note about this application is that it's actually available as sample code for you to download and look at. Just go to the developer website and in the prerelease section search for Tic-Tac-Toe. And I encourage you to take a look to see how all of these technique works.
But before I start, I wanted to mention one thing and that's that all of the existing customization techniques that we had still work great in iOS 7. And we use a lot of these in the sample application, things like UAappearance customization and resizable images. I'm not going to be talking about those today, but you can look at the last two years appearance customization talks in the last two WWDCs to check out some of the concepts.
Alright, let's get started with some of what's changed for appearance customization in iOS 7. One of the first things you'll notice is the Status Bar. The Status Bar has an entirely different look in iOS 7 and it has two different styles that you can use. The default style shows dark content on a white background and we have the new style called US Status Bar Light Content, which shows light colored content on a dark background. However, neither of these two styles actually draw the background themselves. I've shown them here with black and white backgrounds, but they're actually fully transparent.
And this means a lot for how you draw the Status Bar. You can now customize the background that's behind it by showing anything you want there. Of course, you'll want to be careful to make sure that you provide a background that keeps the Status Bar readable by giving it enough contrast and not being too busy, but you have a lot of freedom here.
And so, part of how we've let you draw this background is by changing the way that we lay out view controllers in iOS 7. We'll now layout the content of your view controller beneath the Status Bar, which is what allows you to draw this background. So if you'll look at what we've done in our sample application we have a simple white background and we're careful to not show our game content underneath the Status Bar to keep it visible.
However, in other views in our sample app, we actually haven't done anything for the background of the Status Bar. So, here in the messages and profiles view we're using a navigation controller. And any time that use a navigation controller it will actually draw the background beneath the Status Bar for you automatically. It does this by taking the background of the navigation bar that it shows and extending it to go beneath the Status Bar. This happens for you automatically if you're using a navigation controller so you don't have to worry about that.
Alright, there's another implication of this Status Bar change on your application and that's the default.png images you use. These are what we're using in our sample application for our startup images and the important thing here is that they have to be full-screen size images. So that means 320 x 480 points and 320 x 568 points.
And this allows you to draw in your default.png images backgrounds that goes behind the Status Bar, but don't include the Status Bar itself in your default.png image and that way as your application launches we'll draw a live Status Bar on top of it and it'll look great as you start out.
We've actually gone a little further and made it easier for you to create your own default.png images in iOS 7 by introducing a new system that allows you to set multiple sets of default startup images for different versions of iOS. Previously you could only have a single set that was used for all of the versions of iOS that your app ran on. In iOS 7 we're introducing a new key that you can use in your info.plist.
Just add the UI launch images values and you can add a dictionary with different information for kind of default.png images you want to use. And if you want to see all the details of how to set this up, check out the sample application which uses this. But the important thing is that this allows you to set different minimum iOS versions for your different sets of default.png images. So you can now create a full-screen sized default image for iOS 7 but still keep your older default images for older versions of iOS.
Alright, now you may have seen that many of our system applications have their own different key colors in iOS 7. And this color is used for drawing interactive elements in the application and also selectable elements. So, if you look at the buttons here and also the current day and calendar you'll see that they have different colors in these different applications. And this is a lot of what you can use to make your application different in iOS 7.
So even if you don't use any other customization techniques I'd really encourage you to choose your own key color for your application in iOS 7 and we've tried to make this really easy for you to do. In fact, you can customize the color, the key color of your entire application with just this one line of code.
So, the way this works is by extending a concept that we've had for a while in UIKit and that's called Tint Color. Tint Color used to be a property that several controls and views in UIKit had and affected how they drew their own content. But now we've taken Tint Color and added it to every UIview and it also has some new behaviors.
One of the most important behaviors of Tint Color now is the new inheritant system. And the way this works is that when you set a Tint Color on one view like the window it will actually flow down to all of the subviews of that window and recolor them as well.
So when we set the red color for our window we're actually recoloring the Pause and New Game buttons and also the content in the Tab bar. So, with this change to how Tint Color works the Tint Color Property that used to exist for navigation bars now has a different meaning. In iOS 6 if you set the Tint Color for a navigation bar it would recolor the background that was shown for the bar. So, if you set it to red you'd get this appearance.
Now, if you ran that same code in iOS 7 you'd get something very different. As I said, changing the tint color now affects the foreground interactive elements that are shown. So if you now set the Tint Color to red notice that the buttons that are in the navigation bar are changed to red instead of its background.
If you still do want to change the background of the bar itself we've added a new property that you can use to do that. All you have to do is set the Bar Tint Color your bar to whatever color you want to use and that will change the background of the bar instead of its foreground. Of course, you can combine these as well to set a different background and foreground color.
So, that's the new Bar Tint Color and you can use it on navigation bars, tool bars, search bars and tab bars. Another way that you can customize the backgrounds for your bars is by setting custom images on them just as you've traditionally done in iOS. And we're going to be using that for our sample application to set this custom image that looks kind of like a grid to match with our tic-tac-toe theme.
Now, traditionally in iOS you would set a 44 point tall background as your custom background image and this way it would be shown beneath the bar, which is 44 points tall and we would show a black background beneath the Status Bar and you can still do that in iOS 7. But as I mentioned earlier, navigation bars now often show a full larger content that shows the background beneath the Status Bar to get a kind of unified look there. And you can participate in this system with your custom background images as well.
To do that, all you have to do is set a 64 point tall background image instead of 44 points. When you do this, we'll automatically extend the backgrounds to go beneath the Status Bar as well and if you're wondering the 64 point height is the 44 of the navigation bar plus the 20 points of the Status Bar.
So this is what we'll be doing in our sample application using the full height background image and this-- these changes apply to landscape size background images as well. So, in those cases you would use 32 points tall for just the navigation bar background images or 52 points if you want the combined look.
Now, when you use navigation bars most of the time they appear at the top of your application, but they can also appear lower down and not part of the Status Bar. This usually happens when they're used in things like popovers. And we've actually introduced a new system so that you can set different custom background images for these two different cases.
To do this you can use a new setter called setBackgroundImage for bar position, barMetrics and this allows you to specify the top attached bar position for the case of a combined Status Bar and navigation bar or just the top bar position if you want to customize the background of a bar when it appears by itself.
So this way, you can set different custom background images that have exactly the right height for the navigation bars where it appears. And if you want, you can also use the bar position, any bar position to set a custom background images, image that applies to both cases. And this is great if you have a vertically resizable image because it will just be shown at exactly the right size.
Now, in older versions of iOS we had a behavior when you set a custom background image on a bar where if the height of your background image was taller than the bar's height we would extend that background to go beneath the bar and into the content below. And this allowed you to do things like have a shadow effect inside of your background image. But because of this new behavior where the background image of the bar can extend behind the Status Bar we no longer support that older shadow behavior. However, instead you can use a property called shadowImage that we introduced in iOS 6.
This lets you set your own dedicated shadowImage that's shown in just an area beneath your bar and above the content and that allows you to create exactly the custom shadow image that you want instead of including it as part of an overly tall background image for the bar.
So another big change with bars in iOS 7 is Translucency. By default, all of our bars are now translucent and this includes both the default and the black style navigation bars and it also applies to bars that you've set a custom Bar Tint Color for. When you set a custom background image the behavior is a little bit more complex, will actually analyze the background image that you set for the bar and determine whether the image has any transparency in it or not. We'll use that determination to set the Translucent Property of the bar so that it matches what you've set as a background image.
So these are all of the default values that bars have for a Translucent Property, but if you want to override that you can always set the Translucent Property directly to whatever you want. And this will, of course, change the appearance of the bar but it'll actually also have an effect on how view controllers are laid out in relation to that bar.
So by default in iOS 7, if you have a view controller that appears with bars like this top navigation bar or bottom tab bar, if the bar is translucent we'll lay out your view controller such that it's under both of those two bars. However, if those bars are opaque then we'll just lay out your view controller in the area between them.
So, this is something to keep in mind as you're designing your view controllers and how they're laid out. And there are also places that you can set the different behavior of these properties in the UIView controller. I don't have time to talk about all of-- how all of this works today, but you can look at the UIView controller header to see details of how that works.
Now, another change that you'll see with the buttons that appear both the navigation bars and in the rest of your application is that they no longer show any bezels around them by default. The new default appearance of our buttons is that they'll show either their text or their image and the tint color that they have.
So as you can see, we have this Edit and Compose buttons and they don't have any bezels. If you'd like to use some kind of outline, background or bezel in your buttons you can actually still use all of the customization techniques that we've had before to set a custom background image for your buttons and this will still draw bezels just as it has traditionally.
And this applies to the Back Button as well. Here, you'll notice that the Back Button shows just the back text and back chevron. And this is the default appearance that you can custom in actually two different ways. As I said, you can use our traditional older methods to set a background image for your Back Button and if you do that, we'll actually turn off the back indicator chevron that's shown here, because generally you'll include a back indicator as part of your background artwork. However, if you want to continue with the background list appearance of our buttons as we're doing in our sample application then instead you can customize the back indicator chevron. To do that we've introduced a new property to UI Navigation Bar called backIndicatorImage.
And this lets you set your own custom back chevron. This is the one we're using in our ample application. It's kind of a combination of the back chevron with the X from the tic-tac-toe game and that's what it looks like in context. However, one thing you want to keep in mind as we're customizing this back indicator is that it's also used for push and pop transitions of the navigation bar to make the text of the Back Button flow into and out of the back chevron.
So to do this effect, we actually show-- use a mask image that's a triangular shape to mask the text as its moving during the transition. And if you're changing the back indicator then you'll want to change this mask image as well. And you can use this other method backIndicatorTransitionMask Image to set a custom image for that. And in fact, these two properties are closely linked together. So if you want to customize the back indicator you have to set custom values for both of these two properties. Otherwise, we won't use the custom image that you set.
This is our custom back transition mask that we're using in our application and notice that when we use it the text of the Back Button as its flowing in is clipped to exactly match. As you're designing these two images you want to keep this in mind, the fact that they should exactly fit together so that the masking effect works as the text is moving.
Alright, our application also uses a Tab bar as part of its appearance. And the first thing you'll notice about Tab Bars in iOS 7 is that they're now wiped by default. But they also have a new bar style property that matches the rest of our bars in UIKit and this lets you set either a default bar style for dark text on a white colored background or a black bar style to get the inverse, light text on a dark background. And this is exactly the same behavior as all of the bar styles on our other bars.
[ Silence ]
Alright, now another thing you'll see as you look at Tab Bars in iOS 7 is that many of them have different print images for their selected and unselected states. So, if you look at this example from the Clock application, you'll see that all of the images, that all of the tabs have different selected images that are a little heavier and they have more fills than the outlines in the unselected images. We've made this easier for you to do in your application in iOS 7 as well.
So, traditionally UItabBarItem has had an image property that lets you set your own image on the tab bar item and that image was used both when the tab bar items was selected and unselected. You can still use that now but we've also introduced a new property called selected Image. And this lets you set a second image to override the image property when the tab bar is selected. So, if we use that in our sample application we can set three different images to have a heavier look as well when our different tabs are selected.
So, that's Tab Bars. Table Views also have many changes in iOS 7. One of the first things you'll see is that instead of the rounded rectangle appearance group style table views had in iOS 6, they now have an end-to-end design that looks more similar to the plain style table views.
However, they still do have differences. The backgrounds are now a darker gray and there's a larger space between the different sections. So, redesigning your app for iOS 7 you may want to consider using Group Style Table Views in different places. Another change with table views is their highlighted appearance of the rows in Table Views.
Before iOS 7 we would show a dark blue background behind a selected Table View cell and we would generally invert the content of the Table View cell to appear in white. However, in iOS 7 we show a more subtle gray background behind the selected Table View cell and generally now we don't invert the colors of the content. So as you're designing your new Table View cells you should consider leaving the colors as they are when your Table View cell becomes selected.
Now additionally, if you'd like to change the color of the background that's shown behind a cell when it's selected you can still use the same property we've had for a while, selectedBackgroundView. This lets you provide your own background view for the cell that's used in place of our standard one.
Something else we've introduced in iOS 7 is the new button type. We call this UIButton Type System. You can get it with the same button with type method. Now this button is a standard system button just like the ones that we use in navigation bars. And this new button type replaces the existing rounded Rec button type, which is now deprecated on iOS 7.
When you use this system style button you'll get all the default behaviors that we use for our buttons, which includes this appearance where they're shown without a bezel and with their text or image in the Tint Color of the application and you also get several animations and other effects for free.
So, you'll get a highlighted effect that looks like this where a window button is tapped will change its opacity to indicate that it's being pressed. And you'll also get a new selected appearance just by setting the selected property of the button to Yes. When you do that we'll show the selection indicator to show that your button has been selected.
So we're using these buttons in our sample application for the Pause and New Game buttons and also for this Reply Button that we show in the messages view. All of the other controls that we have in UIKit have all changed quite a bit as well in iOS 7. They all have different appearances and many of them have different metrics as well.
And the best way to deal with these metrics changes is to use Autolayout in your application so that you remain flexible to these changes and don't have to hard-coat in different sizes. However, despite these appearance changes all of the traditional methods that we have for setting, customizing images, colors and text attributes still work great on all of these controls. So you can still make them themed to exactly match your application just as you'd like.
Now, there's one last change in iOS 7 that will affect how you set up your customizations for your app and that's Asset Catalogs. Asset Catalogs are a new system that we've introduced that allows you to combine all of the images that you use into your application into one resource file.
And this lets you consolidate all of your images and also gives you several new capabilities. You can now set different images for different device types and scales and you can even do your slicing of your images right inside of Xcode. So, I would highly recommend that you use Asset Catalogs for all of your custom images in your iOS 7 application. Alright, so those are some of the basics of what's changed with customization in iOS 7. Now, let's talk about some advanced topics.
Earlier I mentioned Tint Color and how you can use one line of code to change the tint color of your entire application. But what's actually happening here? When I showed you the Tint Color on every view, it's actually a little bit more subtle than that. Conceptually, you can think of their being two different Tint Colors on each view. Now there's only one property. This is just a conceptual way to think about how this property works and try to help you understand the behavior of Tint Color in iOS 7.
So, I'll call these the Specific and Inherited tint color of the view. The Specific Tint Color is the one that you've set on a view with a tint color setter. The Inherited Tint Color on the other hand is what you get back when you call the tintColorGetter on the same view. And these two are not necessarily the same.
So, the reason that I call it an Inherited Tint Color is that if you haven't set a specific Tint Color on that view then it will actually inherit the Tint Color of its super view. And if it doesn't have a super view it will inherit a system default color, in this case, this blue color.
So, now if we look again at the example from earlier where we set a red tint color on our window you'll see that the setter sets the specific Tint Color for the window. After that happens the Inherited Tint Color will now use the specific Tint Color because it's non-nil instead of inheriting the system default.
After that all of the subviews that have nil as their specific tint color will inherit the tint-- the inherited Tint Color of their superview, the window, and they'll become red as well. Then that process will repeat until all of the views in that window that did have their own specific color have adopted the red tint color.
Now, if we then change the Tint Color of the window back to nil, we've essentially erased the Specific Tint Color for the window, which means it will go back to inheriting the system default and that change will be inherited by all of its subviews and so on until all of the views in the window will go back to the system default blue color.
So, this same behavior applies if you set the Tint Color on a subview of the window. So, now let's set the Tint Color of this Tab Bar to green. Once again when we call the setter, the setter for Tint Color we're setting the Specific Tint Color, which it then becomes the Inherited Tint Color and which then is also inherited by its children.
So now that we set a Tint Color for this subview hierarchy if we again go back and set the windows Tint Color to red, something a little bit different will happen. Once again, the Specific Tint Color becomes the Inherited Tint Color and now that color is inherited by-- by only the children that have a nil, a nil Specific Tint Color of their own. So you'll see that the Pause and New Game buttons become red, but the Tab Bar remains green.
[ Silence ]
Alright. So this is how you can get different colors for different parts of your view hierarchy. Now, there's one additional special behavior that Tint Color has and that's related to what happens when you show alerts and action sheets in your application. If you look closely when this alert is shown the background is dimmed, but also all of the places that show the Tint Color of the application have become desaturated and that happens automatically whenever an alert appears.
The reason we do this is so that those tint colors in the background don't interfere with your focus on the alert itself. And this is accomplished by a new property called TintAdjustMode. TintAdjustmentMode is closely related to Tint Color and it can have these three different values. When it's set to normal then we'll show the Tint Color of those-- of every view as its original saturated color and when it's dimmed then we'll automatically desaturate the tint color of those views for you. And we'll come back to the AutomaticTintMode a little bit later.
So, let's take a look at how TintAdjustmentMode works for view hierarchy. Every view has a TintAjusmentMode property as well and if you call the getter it defaults returning normal for all of these views. Now, when an alert appears it sets the TintAdjusmentMode of the window to be dimmed. Once that is dimmed then the Tint Color that's returned for the Inherited Tint Color of that window becomes a desaturated gray.
Then that will be inherited similarly to Tint Color by all of the subviews of the window so those views will become dimmed as their TintAdjusmentMode as well, which will cause their tint color to be desaturated and so on until the entire window becomes dimmed and has desaturated Tint Colors.
So, this is not only something that happens with system views like alerts. You can actually incorporate this into your own app as well. And we've done this in our sample application in the Messages view. Here when you tap on the Compose icon we show a new message sheet.
And when this sheet appears we like it to look similarly to how an alert appears. So, we'll set the TintAdjustmentMode of the window to be dimmed, but you'll notice that there's a problem here. Not only have we dimmed the window but if we show the new method sheet inside of the window then it will become dimmed as well. So, now our Cancel and Post button instead of being red are desaturated to gray as well.
So, how can we fix that problem? Well, when I showed you the TintAdjustmentMode property earlier, I left something out which you may have guessed by now and that's that there's a second TintAdjustmentMode conceptually as well. And this has the same Specific and Inherited TintAdjusmentMode just the way the Tint Color does. The specific TintAdjustmentMode review is what you've actually set with the TintAdjusmentMode setter and then the Inherited TintAdjustmentMode is what you get back with the getter. So again, this works the same way as Tint Color. And this is where the AutomaticTintAdjusmentMode comes into play.
When a view has the Automatic Specific TintAdjustmentMode then it will inherit its superview's TintAdjusmentMode and if its superview doesn't have one it will use the system default TintAdjusmentMode, which is normal. Again, this is the same way the tint color works where if the view has a nil specific tint color it will inherit its superviews and if it has no superview it will inherit the system default.
So, now if we look at the example again from earlier where we set the TintAdjustmentMode of the window to be dimmed we'll see that we're setting the Specific TintAdjustmentMode, which becomes the Inherited TintAdjustmentMode when its non-automatic and that's what desaturates the color of the view. And then it sends all of our subviews to Automatic TintAdjustmentMode, they inherit their superviews and become dimmed as well. Then they become desaturated ad that repeats throughout the entire window.
So, this is where we can take advantage of the same thing we did earlier with Tint Color to created a green subview hierarchy. Now we'll set the TintAdjusmentMode instead of the Tint Color of this subview, which is our Tab Bar in this case to be normal. Again, by setting the TintAdjusmentMode setter we're setting the Specific TintAdjustmentMode.
Then, since it's not automatic, our view will stop inheriting from its superview and become normal as well. Since it's normal its color will become resaturated and all of its subviews that have Automatic TintAdjusmentModes will inherit that as well. So, we'll have this kind of island of color within our greater view-- our greater window, which is otherwise desaturated.
Now that's what we can use to bring back the color to our-- to our new message sheets. But there's one last thing that we'll need to do, which is what we're going to do when the new message sheet disappears. So, if we look at the red and green example from earlier, when we set the TintAdjustmentMode of the window to be dimmed once again that will replace the inherited value and desaturate all of the views in that window. But if you look carefully, only the Inherited Tint Colors are changing. All of the Specific Tint Colors remain the same. So, the red and green are still there, they're just kind of hidden by the stimming effect.
And the great thing about that is that when we set the TintAdjusmentMode of the window back to be automatic our Inherited TintAdjusmentMode goes back to normal and all of our colors become resaturated to the same colors that they were originally. So, our view hierarchy returns to all of its reds and greens.
Alright, let's take that and use it in our new message sheet. So, here we have our window before we showed the new method sheet. Then as we show the sheet we'll set the windows TintAdjustmentMode to dim and the sheet's TintAdjustmentMode to normal. That way we get exactly what we want where we have our Cancel and Post button in red, even though the rest of the window is gray. And finally, when we dismiss the sheet we'll set the TintAdjusmentMode of the window back to be automatic, so return everything to its color. So, that's the Tint Color and TintAdjusmentMode properties and how to use them in iOS 7.
Now, another part of our Messages view is in the Navigation Bar at the top. We have a Favorites button that you can use to favorite messages that you're received. However, this is the artwork that we're using for that Bar Button item and notice that it has a gold radiant color in the artwork. But when we actually use it in the Navigation Bar it's just getting color to be red.
This is generally what you want actually. If you look the Compose button it's shown in red and that matches the rest of the Tint Color. But with our Favorite button we want to see this gold star so people will really feel happy when you favorite their messages. So, how can we fix this problem? Well we're using a concept called Template Images in iOS 7 to do this recoloring.
When an image is a template image, instead of being drawn as-- with its original colors the image is treated as a stencil. So, we'll take the shape of the image and we'll recolor it to be whatever the Tint Color is. And the great thing about Template Images is that they can be recolored to match the rest of the UI as the Tint Color changes.
However, sometimes you'll want to opt out and to let you control this behavior we have a new property on UIImage called Rendering Mode lets you control whether an image is treated as an original image and shown in its full colors or whether it's treated as a template image.
Here are the three different values for Image Rendering Mode and we'll use our star image as an example. Now, the important thing about how images are rendered is that it depends on what context they're used in. So, we'll talk about an ImageView and also a BarButtonItem like the one in our Navigation Bar.
The Automatic Image Rendering Mode means to render the image either as a template image or an original image depending on the context its used in. So, in our ImageView the image will just be treated as its original normal form and shown with its colors, but because a BarButtonItem defaults to showing it as a template image it'll be used as a template image there. With the AlwaysOriginal Rendering Mode the image will always be treated exactly in its original form and we won't touch any of the pixels.
With the AlwaysTemplate Rendering Mode we'll always treat it as a template image and it will always be recolored. So, you can think of the Automatic Rendering Mode as saying you figure out what to do with my image. And the AlwaysOriginal and AlwaysTemplate Rendering Modes as saying I want full control and this is what I'm specifying as a behavior for this particular image.
So, now let's go back to our Navigation Bar and see how that applies. When we create our image, in this case using image names, it's returned with the Automatic Rendering Mode by default. And again, this means to do the default for the context it's used in and that's why our image is getting recolored to red when we use it in a BarButtonItem.
So, all we need to do is use the Imagerendering Mode method on the image that we have and now we'll convert the ImagesRenderingMode into whatever we've specified. So, since we're passing an AlwaysOriginal our image now becomes an original image and it's shown in full color in the Navigation Bar.
Now, this same behavior applies to the Tab Bars and the Tab Bar items that shown within them. Here, by default an image that you set will be recolored to the Tint Color when the Tab Bar items is collected and it will be colored gray when the item is uncollected.
We used to have a method called, Set Finished Image with Finished Unselected Image. And that allowed you to set images that were used for this selected and unselected state and it wouldn't be recolored. So, this method was actually doing two completely separate things. One of them was specifying that the images that you set should not be recolored and the other was setting different selected and unselected images. So, we've actually deprecated this method in iOS 7 and you can now do either of these two things separately or, of course, combine them together.
You can use the AlwaysOriginal Rendering Mode to specify that the image you set should not be recolored and this was the finished part of the old method. And you can use the Image and SelectedImage properties that we talked about earlier to set images that are separate for the unselected and selected states. And, of course, you can use either of these separately or combine them together to get exactly the effect that you want.
So, in the profile view of our application we show that segmented control and this left the user to choose to be Xs or Os in our game. And we're just using a standard UI Segmented Control here. But we'd like to customize it a little to better fit with our applications.
So, first of we'll set a custom background image for the Segmented Control and notice that the background image that we set is not getting recolored along with the Tint Color. That's because Segmented Controls default to treating their background images as original images. So, they won't be recolored and, of course, you can use the AlwaysTemplate Rendering Mode if you want to opt back on into that behavior.
Now the foreground images the X and the O on the other hand, they're being recolored because they're getting treated as Template images. So, to opt them out of that we can use the same image with Rendering Mode Method and pass in the AlwaysOriginal Rendering Mode. And we'll use that here because in our application Xs are always red and Os are always green.
So, we want them to keep their original colors. Now, Steppers and System buttons have actually the same behavior we just talked about for Segmented Control. The thing to remember is that foreground images that you set default to being Template Images and background images default to being Original Images.
Everywhere else in UIKit that we use images defaults to treating them as original images. This includes things like Image Used and the images that you set in Table View Cells. So, if you look here in this section, the Statistics section of our Profile view, you'll see that when we set those images on our Table View Cells they look kind of plain because they're being-- they're just original images so they're just shown in their original color and we'd like to better match with the rest of our application by making them recolorized to match the Tint Color.
So, to do that we'll use the same Image with Rendering Mode Method and this time we'll convert them to Template Images. And this way they'll match the Tint Color and they'll change along with the rest of the application. So, this is a great technique to consider if you want to add some color and match-- better match with the rest of your application as it changes color and it saturates. So, let's talk about Status Bar, the Status Bar a little bit more.
The change to the Status Bar to make it always transparent means that it's really important that your application applies exactly the right background behind the Status Bar. And as I said earlier, it's the View Controller that provides that. Well, traditionally in iOS the Status Bar was actually controlled by UI Applications properties where you set the style and hiddenness.
And this made it very easy for different places in your application to set this Status Bar style and to stomp on the value that someone else had set. In iOS 7 we want to make it really easy for View Controllers to control exactly the Status Bar style that matches the background that they've shown.
So, we're introducing a new system to allow you to control the Status Bar's appearance. The way this works is in your View Controller you can override either of these two methods to specify whether you want the Status Bar to be hidden or not and what style you want it to be shown as when its visible.
And when you're using this new system the UI Application methods to set the Status Bar style won't do anything anymore. Instead we'll find the current View Controller that's underneath the Status Bar and we'll ask it what kind of Status Bar style it wants. So, this allows your View Controller to make sure that its background and its Status Bar match.
And actually the values that you return from these two methods don't have to be static values either. You can change them over time, but the important thing with changing them is that after you make a change you have to call setNeedsStatusBar AppearanceUpdate on the View Controller that's changed and this lets us know to update the Status Bar to match the changes that you've just applied. And then we'll redisplay the Status Bar just as you specified.
And these Status Bar changes apply actually to container View Controllers as well. So, all of our standard UIKit Container View Controllers like Tab Bar controllers and Navigation Controllers will implement this for you automatically. So, they'll automatically forward control of the Status Bar to whichever View Controller within them is underneath the area of the Status Bar.
And you can implement this in your own container of View Controllers as well. It's actually very easy. There's another two methods that you implement in your Container View Controller to return which of its children should be used for determining what the Status Bar should use for its style or for its hiddenness. And once again whenever you change the value return from one of these you can-- you need to call the same method, setNeedStatusBar AppearanceUpdates to let us know that the state of your View Controller has changed.
Now, this change to how the Status Bar is set up is a very big change and it's global to your entire application. So your application will either use entirely the new system or entirely the old system. And we have a global switch that you can use to specify which system to use. It's an info.plist key called UIViewControllerbase StatusBarAppearance. And you can set it to yes or no to opt into the new system or remain out of it.
We've used that- we've opted it into the system in our sample application and in most of our View Controllers we haven't had to override the default values of the two methods. But one place that we are using them is in our Game view here. This view defaults to showing a white background but when the game is over it'll actually invert the background to be black and so it will invert the Status Bar to match that change, like this.
And this is really easy to do. You just have to implement two pieces of code. First, override preferredStatusBarStyle and then we'll check if the game is finished or not and return either light content if it's over or default if it's still in progress and then when our game state changes we just call needStatusBarAppearanceUpdate, as I mentioned earlier. However, there's one special thing here, which is that we've put this call to update the appearance inside of an animation block.
And when you do this we'll automatically animate the Status Bar Appearance change to match the same animation as the block that it's inside of. So, we can animate along with our background color change and they'll both fit together perfectly. So, let's take a look at that again in slow motion.
Great, alright now let's talk about how you can create Custom Controls. We worked really hard on the UIKit Controls to make sure they always work great. And I'd like to show you how you can make your own Custom Controls work just as well. However, before you start making the Custom Control you should always consider whether there's a standard UIKit Control that you can use in customized to work the way that you'd like. So, in our Profile view we had a really Custom Segmented Control but we were able to customize it just by using images and rendering modes to get the appearance that we wanted.
If you use Standard Controls then you will automatically get consistency for your users and it'll be less work for you. This is always something to check before you start. Now the first Custom Control in our application is this Rating Control that's shown at the top of the Game History view. This is a pretty simple control that lets you set a rating, a number of stars for previous games that you've played.
And to tell you how we built this Custom Control I'd like to tell you a little secret about how we make our UIKit Controls. When we create a control like this UI Button in iOS 7, we don't actually start with a blank slate. Instead, we use other existing standard UI Views as pieces, building blocks to put together these controls. So a button consists of Image Views and UI Labels.
And when we do that it automatically gives us the great Text Rendering support from UI Label and it also gives us support for all of UI Image like Rendering Modes and Resizable Images in the UIImage View. Similarly steppers actually consist of an Image View and two buttons. And this gives us not only its appearance but also a lot of interactivity for free.
So, we've taken the same approach in our Custom Control and here we're using an image view to draw the background and we're using five different buttons to draw the foreground content. In fact, with button it's even easier for us here because we can set different selected and unselected images for the button and to toggle between them we can just set the Selective Properties of our buttons.
Now, an important thing that we had to do here when we wanted to use buttons inside of our custom control is to use the UI button type Custom. And when you use a Custom type button this opts you out of all of the standard system animations and appearances so that you can fully customize the button to look like exactly what you want.
One other thing you can do if you want to customize your button even further is to subclass the UI button and override these three methods. This lets you exactly control the positioning of the images and the text that's shown in the button so you can get exactly the effect that you want. So, now let's take a closer look at the background that we show.
As I mentioned earlier, it's an image that's being shown in an ImageView and we're actually dynamically creating this image at runtime, which is really easy to do with the UIGraphics function that allows you to create a new image context, draw into it and then pull out an image from the context.
So, we're using UI [Inaudible] path to do our drawings here and one thing you will notice in iOS 7 is that UI [Inaudible] path has a new, draws rounded rectangles in a new way in iOS 7, a bit smoother and more continuous. So you'll get better curves for your [Inaudible] paths automatically by using UI [Inaudible] path.
Once we have our dynamic image we just set it on the ImageView. However, we'd like this background image to follow the Tint Color of the application. And that's really easy to do. Just like before we'll set the Rendering Mode of the image by calling ImagewithRenderingMode after we've dynamically created the image and passing in AlwaysTemplate.
And we can actually combine the Rendering Mode call with Resizable Image calls. So after we change that Rendering Mode of our image we'll pass that Resizable Image with Cap Insets to make it both a template image and a Resizable Image. And this way our-- we can use this same background image in all of our ratings controls and no matter what size that they're shown as, so we can just reuse that one image.
No another way that we got a lot of the functionality of our Ratings Control for free is by subclassing UI Control. When you do that you'll automatically be able to participate in the Target Action System the UI Control Implements and, in fact, UI Control will even send all of the touch related action methods for you automatically. However we'd like to go even further with our Rating Control because we also have a value associated with the control which is its rating.
So, here when a user touches a button, after we set the rating we'll also send all target action events for the Value Changed UI Control Event. In this way we can use Value Changed Events in our View Controller to add ourself, the View Controller as a target and the Change Rating Method on our View Controller will automatically get called whenever the user changes the rating of the control.
So, the next view that we have, Custom View in our application is Account View. In our Profile we show you here the number of victories and defeats that you have and to make things a little more fun we'll show them as tally marks here. So, we're doing this just by overriding UIView and by implementing our own draw drawRect because this is a pretty simple to draw and it's one single continuous region. In our drawRect we're actually using our current Tint Color which allows us-- which we can set on the graphics context and then do any drawing that we do normally.
So, the Inherited Tint Color that's returned is actually guaranteed to always be nil because it'll inherit its superview if the Specific Tint Color of the view is nil and it'll use the system default color if it doesn't have a superview. So, we can always rely on the tint color to be a real color that we can use to draw with. However, there's one last thing that you need to know about Tint Color and that's how to update it when it changes.
Whenever the Tint Color changes we automatically call the tintColorDidChange method on all of your views. This is a new method that kind of behaves as a notification to your view to tell it needs to update anything that it has that was using old Tint Color. So, if we look at changing the Tint Color of the window to red after the Inherited Tint Color changes that tintColorDidChange fires to that view and the same thing happens for the subviews and their subviews. So, everything in the window will automatically get a tintColorDidChange notification either when its own Tint Color changes or when its Inherited Tint Color changes due to changes in superview.
And the same thing happens automatically for you when the TintAdjustmentMode changes for your view. So again, if we set the window to be dimmed its Inherited Tint Color will change to gray and tintColorDidChange will be called both on the window and all of its subviews and their subviews as their Tint Colors change as well.
So, going back to our Count view, all we need to do is override tintColorDidChange and then we'll just tell our view that it needs to redraw by calling setNeedstoSite. Of course, in our Count view we're using setNeedsto [Inaudible] so that we only have to redraw the part of our view that uses the Tint Color itself.
Now another place that we'd like to use Tint Color in our application is in this Table View Cell. Here we use the Tint Color as the detail labels text color and this will help emphasize the result of previous games. Once again, we use tintColorDidChange and this implementation will actually take the Tint Color of our current view and set it as the Text Color of our detail label. And this will make our detail label match the Tint Color and also automatically update as the Tint Color changes or becomes desaturated.
So, there's one last really important thing to consider when you're implementing Custom Controls and that's Accessibility. It's really important to implement accessibility in your apps and in your Custom Controls so that all of your users can really enjoy using your applications. It's also really easy to do. So, if we look at our Ratings Control it acts as kind of a container for the buttons that are inside of it.
So, we'll return No for is accessibility element of the control itself. And that will cause the accessibility system to look for the subviews of the control and treat them as accessibility elements. UI Button implements a lot of accessibility for us automatically so all we need to provide is an Accessibility Label for our button, for out buttons.
And Accessibility Label is essentially text that describes what the button is behaving as. So, we'll just use the number of stars as the Accessibility Label for our button and, of course, we used a localized string so that they'll automatically be translated as we translate our application into other languages. Now our other custom control is this Count view and we'll also need to add Accessibility here.
In this case since the view is just a single element we'll return Yes for its Accessibility element and then that top level view we'll be treated as an Accessibility element. We'll also need to return what kind of traits that it has. In this case we're essentially saying that our Count view is similar to an image, so we'll turn that as its trait. And finally, we'll need to return an Accessibility label that has text that described what that view represents. Since our Count view is essentially representing a number, we'll return a text version of that number.
Alright, so now we've fully customized our application and let's take a look at what it looks now. So, here's our new customized application. We'll start in the Game view and here we can just tap to play our pieces and you'll notice that when the game finishes we automatically transition the background slack and the Status Bar to match.
[ Applause ]
Also, when I pause the game you'll notice that our Pause button gets the selected appearance because we're using a System button and you'll notice that in our Tab Bar we have different images for the selected and unselected states. Next, let's take a look at messages. When we create a new message, notice that the composed image gets desaturated in the background but the Cancel and Post buttons remain fully saturated.
And after we post a message we can select it and make it a favorite image which we'll use our AlwaysOriginal favorite star image. You can also see here a System button that we've used where we haven't set the Rendering Mode and here our image is getting recolored. In the Profile view you can see our Segmenting Control where we customized the different images and Rendering Modes and as we change what piece we want to use you'll see that we're changing the Tint Color as well, which causes all of our Image views to update, our Custom subview and the Tab Bar.
Finally, in the History view you can see our Table View Cells which use the Tint Color for their detail label and inside of one of the History views you can see previous games and also our Rating Control including its background, which automatically matches the Tint Color. And finally, you can see our Custom Back Indicator. Great, so that's our customized application.
[ Applause ]
So, today I've showed you some of what's changed for Customization in iOS 7, a few advance topics like Tint Color and Image Rendering Mode and finally, we saw how to use your own Custom Controls to extend your application even further. So, I hope that you all go out and use these techniques to make your applications really great. Thank you.
[ Applause ]
[ Silence ]