[MUSIC] It's kind of a minor element, but it's something that can really disrupt the flow of a good user interface. And that's the appearance of the soft keyboard. When that keyboard comes on screen, it can cover over important information or it can change the layout pretty drastically, so at this lecture, I thought we'd present an example of how you can work with the keyboard in order to adjust the content that's underneath. I mean, the big picture is basically this, that you can have a full screen layout be using the full screen real estate of your phone or iOS device. And then when the soft keyboard comes up because the user is interacting with the text element or needs to enter text, that keyboard rises from the top. It can take up a third or a half of the screen depending on what size device you're working with, maybe a little less if you're on the iPad a little more if you're on an older iPhone or smaller iPhone. And so what we want to do is we ant to talk about that red distance of how we can leverage constraints in order to adjust our user interface to do that. So we're going to go through how we go about creating the user interface that's responsive to the soft keyboard. How do we do that? Well we're going to make a simple UI. We're just going to put one picture in it, and we are going to have a text field and a button. And what we're going to do is we are going to register within our view controller to be told of when keyboard events are going to happen. So we've seen kind of this pattern with the delegate pattern where we write code that gets informed of information when things happen. This is a little different because instead of getting information that's directed to a specific delegate, we're going to get information that is being broadcast across the phone. So any application can receive information about the keyboard coming or going. So it's not just one, like in the delegate, but we're going to respond to those events, and we're going to do something about it. And then we're going to animate our UI views in response to the keyboard, and we're going to leverage auto layout to do that. All right, so let's do that. Let's go to our X-code, and set up a project. We're going to start with a new project. And it'll be a single view project, and we will call it keyboardDemo. This will be a universal objective C app, and we will not use coordinator for this one. Okay, so we're going to create our main storyboard. We're going to create our image. We're going to create our UI. And in order to do that, what I want to do is I would like to actually specify a slightly different size, and figure out how to do that. View controller. That's what I want. I want the size. I'll do a 5.5 inch phone, since I think that's what the 6S plus is signed up to be. And, into this, we are going to start by adding an image view On image view that fills up the entire screen from the top all the way to the bottom. And this is going to be the thing that gets disrupted when we introduce the keyboard. And so we'll put some constraints down on that. And we'll say we want it to go from the very top to the left and to the right. And we'll add those constraints. Let me get a picture, a copyright free picture of myself to put in there. So here's a picture of myself. I'm going to put that into my assets folder if I can. Let's see, go to assets and take that picture and drop it into the assets. And we'll go back to our storyboard. And I'll select my image view, and once it's in there get my picture. All right, now it's important we get the aspect ratio right. In this case I want it to be scale to fill. But I know, I don't want to be crazy like that. Let's see, option command equal. I don't want it to, I don't want it to distort. Aspect fill, that's what I want. Great, All right. So the other thing I want to add is I want to add a text field to this. And that's going to give it make a little bit more sense when you're thinking about typing something in. And we will fill that up. And I would like a button. Put that button there and we're going to make that have the word resign, because that's going to cause the text field to let go of the keyboard, so that the keyboard will go away. All right, we can see it pretty well, so lets add some constraints there. We want these two items to be centered vertically. And we'd like this item to be aligned along the top and to the right. And we'd like this element, no that should be okay, right? Option command, nope. We'd like that item tracking the top and the right also. Option command equals, nope. And we will also add constraint to the left. And then option command equals. There we go, okay. All right, so that's where we're starting. And then, what we're going to need to do for that is we're going to need to go for our view control. And let's see what we've got here. And we are going to need to have access to our resign button, we're going to do something when our button gets tapped. Call it resignButton. And we're going to need access to our text field. And what we're going to do is when we click that resign button, we're going to say self self.textfield resign. What was it? It is resign. Okay Okay, see what we recommend. Okay, pause for a second. Unpause. It's not keyboard, it is FirstResponder, that we do there. Okay. I accidentally grabbed the wrong thing here, so that text field, it's a layout constraint and that's not what I want. So let's see if we can remove that connection and we'll get rid of that. And we'll select our text field, and see if we can do a better job of control dragging that into our code. So I had selected the wrong thing when I control dragged, and so as a result, resignFirstResponder wasn't available. Now that I have the correct thing dragged, now resignFirstResponder should work. Now if I run this, we should see that the keyboard comes and goes. And the picture stays the same, it gets covered up. In the simulator, it assumes that you've got a hardware keyboard. And so if you just start typing up here, for example. If I say hello world, it assumes that's coming from an external keyboard. If you want to have it appear as if it's coming from, if you want to use this soft keyboard, you have to hit Cmd+K in order to get it, and then you see that the picture gets covered up. In this case, maybe that's not what we want. We can hit hello and hit Return, and that places the text into the text box there. In order to let the keyboard go away, we have to resign First Responder. And so we've specifically done that here, and this button, that causes the soft keyboard to go away. So that explains those two things. Now when that keyboard goes up, we want to do something in response to that. So what we're going to do is we're going to register for events when that keyboard appears. We're going to do that in our code here for viewDidLoad. Okay, I'm going to go get some boiler plate, I'm going to go get some code that I templated for this. Get some code that I templated for this. Pause for a second. Okay, unpause. And I'm going to paste it in here and walk through it line by line. So for starters, what we utilize here is we utilize the NS notification center. This is the place in iOS that broadcasts out information about what's going on to the phone that your app may want to grab information from. There are lots of things that you can get info about but for starters, we're just going to get a connection to the notification center itself. Then what we want to do is we want to say hey, actually Notification Center, we want to be someone that's paying attention to what's happening. So if you could, could you just let us know when, in this case, the UI keyboard is about to show. So the notification that we're interested in is the UIKeyboardWillShow. We don't care which object sent it. And that's all we're asking for this time. This selector here is going to be a function that we are going to implement that will get called when this thing occurs, when the keyboard is about to show, when the iOS broadcasts that the keyboard is about to appear. Because we have registered for a notification, this function will get called when we implement it. All right, so that's what we need to do next. Let's implement this function. And we can do it down here. Great, this function has a particular signature. It receives a notification. And all we're going to do here for starters is we're just going to send something out to the log that says. The keyboard is about to appear. And we'll see if we can demonstrate the fact that we're receiving this signal. Okay, and it should show up in the log, let's see if that happens. So if we select here, oh, there it goes. And just before it appeared, it says the keyboard is about to appear. So great. And there it goes away. All right, now we need to decide to do something about that. Before we decide to do something about that, we actually need to. If in viewDidLoad, we register for notifications, we have to de-register for notifications. So we're going to do that when our object gets destroyed in the dealloc phase of our view controller's life cycle. So we're going to deallocate. When we deallocate, we're going to tell the NSNotificationCenter that we don't want to receive notifications anymore. So this just says, remove every notification that I've registered for. Okay, so when we do find out that the keyboard is about to appear, we're going to want to do something. Instead of logging it, what we want to do is we want to change the way the picture is displayed. And in particular, we want that display to shrink up so that my picture stays in the image as the keyboard rises up. And the way we're going to do that is we're going to change the position, the layout constraint that the image is attached to on the bottom. So, if we come over here, we see that the bottom layout guide is right here, and so we can adjust that constraint dynamically within the program. And so in order to do that we're going to need to have a hook to it. So we're going to bind that into our function here, and we'll call it bottom layout. And we're going to mess with that when the keyboard appears so that the bottom layout stays at the top of the keyboard as it comes up. All right so let's, so in order to do that, we're going to need to get information about where the keyboard is. We're going to need to animate it, and we are going to, yeah, I guess that's it. Okay, the first thing that we're going to do is we're going to get some information out of the notification that was sent to us by the system. So we get sent this object, this notification, and we're going to pull out some information. In particular, we want to pull out information about the keyboard, and about where the keyboard is. So we're going to. Declare a keyboard and then we're going to get information about where it is. So the way that we do that. This is just where you find it. You ask for the user info and then you want the rectangle that the keyboard fills and that is of type CG rectangle. And in order to get that you ask the info object, there's a dictionary that we've got, for the object that's associated with the key UIKeyboardFrameBeginUserInfoKey. All right, and what you want is you want the core graphic rectangle value. That's where the keyboard is. Once we've got that, we want to know a little bit about the animation that's currently going on with the keyboard. We want to know how long is that animation taking as it's coming up, and what's the shape of it? Does it come in quickly and go out quickly? Or does it ease in or ease out? What do we do? So to do that, we're going to grab the duration of the animation and we're just going to do the same pattern. We're going to get the information about our notification. We're going to get a particular object for this key, the key is UIKeyboardAnimationDurationUserInfoKey and we want the floatValue of it because that's how long this animation is going to take. We're going to get the curve associated with the animation so that's how does it ease in and ease out? And that's got it's own key UIKeyboardAnimationCurveUserInfoKey. We'll take the integer value. And then we are going to call a command here, self.view layoutSubviews. And what that's going to do is that's going to say hey, if there was any constraints and if the auto layout was waiting to do any laying out of the UI go ahead and do that layout now. Because everything else, everything we're about to mention, we want to animate. So we want to close out anything that was in process of animating or process of being designed, and then we want to animate our own stuff. All right, so the way we're going to do that, is we're going to, like in our table view, we have to create an animation transaction, and the way we do that is by calling the function UIViewBeginAnimations nil and context:nil. And this is going to say everything that comes after this should be one animation, so stop animation until we're done describing the next animation. And then when we say go, go ahead and complete animation. And our goal here is to have the bottom layout that the picture is anchored to Animate up at the same time as the keyboard. Right, so we're going to set that animation. We're going to say the animation is going to have a duration that we got from above that matches the keyboard. It's going to have a curve that matches the keyboard. And this function here says that if there's some other animation that's in process we want to take over that animation. We want to say that wherever the keyboard was or wherever our bottom layout constraint was previously. if it was in the middle of the animating, we want that animation to stop, and we want it to begin from where it is now to the point where we tell it to go. The other alternative is to allow the previous animation to finish before you start your animation. But, in this case, we're going to interrupt it. All right. So now we're going to create a UI. I'm sorry there. If we don't want to mess with the scroll, scroll view here. All we want to do is where we bound the lower notification up here to bottom layout. We want to set the bottom layout to be as high at the end of the animation as the keyboard is going to be at the end of the animation. And then we want the auto layout to go ahead and calculate where that's going to be. And then we want the UI view to go ahead and animate that process. Okay. So if all goes well, when we're notified that the keyboard is appearing, what we're going to do is we're going to move that bottom layout up and the picture, which is attached to it, should move up as well. And it should be animated at the same rate as the keyboard. All right, let's see if that works. Remember, previously the keyboard just slid over the image. All right this time though, you can see that the image shrinks and fills up the screen as the keyboard goes up. Now when we let it go, when we resign the control, it's not going to go back as smoothly. You can see that we never reset that animation at all, and so, yeah, it doesn't go back. It just stays there, so we need to fix that. All right, so in order to fix it, what we're going to do is we're going to copy this. Let's see. So this function's called moveKeyboardInResponseToNotification. Let's go ahead and change this name, and so we say, moveKeyboardInResponseToWillShowNotificat- ion. So we'll come down here and we'll say, moveKeyboardInResponseToWillShowNotificat- ion. And now what we want to do is we want to ask for another notification. And this notification that we're going to ask for is we're going to ask if the keyboard is going to be hidden. We're going to do the same thing. We register a function that we're interested in being called when the keyboard is about to hide. And actually, we're not going to do that one. And we'll say, moveKeyboardInResponseToWillHideNotificat- ion. So that has to be another method. And we're going to go ahead and just copy this method to create that. All right, WillHideNotification. Now in this case, as we go through and we get the information we don't actually care much about where the keyboard frame, the end user key says, because we know the keyboards going away and so we're just going to use cg. Pause for a second. Resume. A cg, basically a zero-rectangle, a rectangle that puts everything at the bottom. Otherwise, though, we can keep everything the same. And so the point is is that just the destination of this animation is different. So the keyboard going up, we're putting a destination where the keyboard is down at the bottom. And so now when we run this. When we click in the text view, the image goes up, and when we resign it, the image goes down. And I think that's a really nice behavior depending on your UI and how you want to design it. Now you may notice that this text box and this button don't do anything in response to the keyboard coming up and down. That's because we didn't animate them. We could have had them do something if we wanted to, but it makes sense in this context not to. And so then the last thing I wanted to point out is that there, and this is the thing I deleted there from the comments, is that there's another signal that you can request information to that has to do specifically with when the iPad keyboard breaks off from the bottom. And you may not be familiar with this behavior, but let's see if we can pull it up here. It will take a second to launch. There's another signal that says that if the iPad keyboard is detaching and moving, then do something in response to that. That's a pretty complicated animation though. And when you move the iPad keyboard, it actually kind of looks like it's floating on top of the content anyway. And since an iPad user can move the keyboard around at will, it's not quite as big a deal if they were to have the keyboard covering content. So here's an example of an iPad keyboard. We click here and it raises up really nicely. But with an iPad keyboard, you can break it apart. Whoops, let's try it. Usually you can. Let's see if I can do that. There you go. And when you do that, you can actually separate them. I can't quite figure out how to do that. There you go. We get an undocked keyboard like that and it responds as if. There we go. And it snaps in place if you decide to float the keyboard on top of it. You can actually split the keyboard too, but I don't know how to do that in the simulator. So basically, the keyboard can take up space, and being able to respond smoothly to the keyboard is kind of a nice effect. And the fact that the keyboard covers content isn't really a problem as long as you can adjust your UI to accommodate that change. Takes a little bit of work, but gives a nice appearance overall to your overall UI. Okay, that's it for this lecture. Thank you. [MUSIC]