When you develop forms or any screens with input fields, occasionally the inputs will be obscured by the keyboard when it appears. This is bad usability for the user who now has to input data without being able to see what they have typed! One solution is to slide the whole view so that the field being edited is always visible.



This solution I provide adds a few methods to UIView (yes i know, adding categories to cocoa classes is naughty) – which will determine how much to slide the view based on the inputs position on the whole screen, and then slide the view at the same speed as the keyboard slide entry. It then will slide back to where it was when you are finished editing.
It is pretty simple to do this – here is how I calculate where to scroll the view:
- (void) maintainVisibityOfControl:(UIControl *)control offset:(float)offset {
static const float deviceHeight = 480;
static const float keyboardHeight = 216;
static const float gap = 5; //gap between the top of keyboard and the control
//Find the controls absolute position in the 320*480 window - it could be nested in other views
CGPoint absolute = [control.superview convertPoint:control.frame.origin toView:nil];
//If it would be hidden behind the keyboard....
if (absolute.y > (keyboardHeight + gap)) {
//Shift the view
float shiftBy = (deviceHeight - absolute.y) - (deviceHeight - keyboardHeight - gap - offset);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3f]; //this is speed of keyboard
CGAffineTransform slideTransform = CGAffineTransformMakeTranslation(0.0, shiftBy);
self.transform = slideTransform;
[UIView commitAnimations];
}
}
..and then I reset the view afterwards using:
- (void) resetViewToIdentityTransform {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3f]; //this is speed of keyboard
CGAffineTransform slideTransform = CGAffineTransformIdentity;
self.transform = slideTransform;
[UIView commitAnimations];
}
You only need to make minimal changes to your own code, and call these methods from your UITextFieldDelegate methods (or other control delegates):
- (void) textFieldDidBeginEditing:(UITextField *)textField {
[self.view maintainVisibityOfControl:textField offset:0.0f];
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
if (textField == currentControl) {
//If the textfield is still the same one, we can reset the view animated
[self.view resetViewToIdentityTransform];
}else {
//However, if the currentControl has changed - that indicates the user has
//gone into another control - so don't reset view, otherwise animations jump around
}
}
Here is a copy of the XCode project:

Thanks
|
karthik |
i think it will really help me to do what i want,.. and i do no where to insert this block of code..
karthik |
i have to be clear first, please help me,.. because when the textfield will be visible,.. while tap the text field or pressing any key in keyboard,..
admin |
You need to set the delegate of the textfield to be the class that contains the ‘textFieldDidBeginEditing’ methods…. you can do this from interface builder or in your code, however you initialise them.
Read the documentation for UITextFieldDelegate.
alf |
Your code was exactly what I was looking for. But I’m having trouble using it with UITextViews. Do you have an example that uses them?
Basically I can get the code to work with them but I get this warning: incompatible Objective-C types ‘struct UITextView *’, expected ‘struct UIControl *’ when passing argument 1 of ‘maintainVisibityOfControl:offset:’ from distinct Objective-C type
Do you have a suggestion on how to get ride of the warnings?
interactivo |
helped me a lot thank you!
alop |
a small bug: if you switch from one field to another, while the keyboard view is visible, the selected field isn’t shown completely.
Dinesh |
Thanks a lot…!