Rahul Vyas
Rahul Vyas

Reputation: 28720

manage view with keyboard and autolayout in center

I have the following view hierarchy. View->container->2 UITextfields and 1 button in containerView. The container is in the center of the screen. What I want to do is to move the container up when keyboard appears and UITextfield is behind the keyboard and move back to center when keyboard disappear. Here is the screenshot for the same.

enter image description here

What constraints do I need to change or do I need to add constraints in code ?

Upvotes: 2

Views: 751

Answers (5)

Sheereen S
Sheereen S

Reputation: 1236

Get the frame of the container while keyboard show and update the new frame size. 'setTranslatesAutoresizingMaskIntoConstraints' is the right solution while updating frame of a view.It worked for me

enter image description here

 @implementation ViewController
{
CGRect defaultFrame;
}

- (void)viewDidLoad {
[super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
#pragma mark Notifications

- (void)keyboardWillShow:(NSNotification *)notification {
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
defaultFrame = self.ContentView.frame;

[self.ContentView setTranslatesAutoresizingMaskIntoConstraints:YES];
[self.ContentView layoutIfNeeded];

CGRect contentInsets = CGRectMake(defaultFrame.origin.x, (keyboardSize.height), defaultFrame.size.width, defaultFrame.size.height);
[UIView animateWithDuration:0.5f
                 animations:^{
                     self.ContentView.frame = contentInsets;

                 }
                 completion:^(BOOL finished){

                 }
 ];

self.ContentView.frame = contentInsets;

}

- (void)keyboardWillHide:(NSNotification *)notification {
[self.ContentView setTranslatesAutoresizingMaskIntoConstraints:NO];
[UIView animateWithDuration:0.5f
                 animations:^{
                     self.ContentView.frame = defaultFrame;
                 }
                 completion:^(BOOL finished){

                 }
 ];

}

Upvotes: 2

Bhaumik Desai
Bhaumik Desai

Reputation: 213

Seems like you have given correct constraints all you need to do now is to make a outlet of centre y constraint and change it's constant on keyboard show/hide events, Which you can grab with keyboardDidShow/keyboardWillShow and keyboardDidHide/keyboardWillHide notifications. that said you can also add cool animation effects for these changes. Try out let me know if you need example.

Edit:

add your viewcontroller as observer for two Notifications:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWasShown:)
                                             name:UIKeyboardDidShowNotification
                                           object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardDidHide:)
                                             name:UIKeyboardDidHideNotification
                                           object:nil];

Now suppose name of your constraint is "constraintForTopSpace",then add two methods for the notifications:

- (void)keyboardWasShown:(NSNotification *)notification {
    // Get the size of the keyboard.
    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    //Given size may not account for screen rotation
    int height = MIN(keyboardSize.height,keyboardSize.width);

    // Here you can set your constraint's constant to lift your container up.
    [UIView animateWithDuration:0.5 animations:^{
        [constraintForTopSpace setConstant:constraintForTopSpace.constant - height];
        [self.view layoutIfNeeded];
    }];
}

- (void)keyboardDidHide:(NSNotification *)notification {
    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    int height = MIN(keyboardSize.height,keyboardSize.width);

    // Here you can set your constraint's constant to move your container down.
    [UIView animateWithDuration:0.5 animations:^{
        [constraintForTopSpace setConstant:constraintForTopSpace.constant + height];
        [self.view layoutIfNeeded];
    }];
}

And you can also use UIKeyboardWillShowNotification/UIKeyboardWillHideNotification notification they will be triggered before the keyboard appears on screen, Its up to your requirements.

Here adding animation will give smooth look and feel. ;)

Upvotes: 0

Ketan Parmar
Ketan Parmar

Reputation: 27428

Take IBOutlet of your bottom constraint or top constraint of container view by ctrl+drag from respactive constraint.

If bottom constraint then increase the constant of constraint equal to keyboard height when keyboard appears and decrease same when keyboard disappear.

If using top constraint then decrease the constant equal to keyboard height when keyboard appears and increase same when keyboard disappear.

for example,

 topConstraint.constant = topConstraint.constant + keyboardHeight;

Update :

According to your constraint you should take outlet of vertically center or center x and you should do something like,

 self.verticallyCenter.constant =  self.horizontalyCenter.constant - 100 //here 100 is keyboardheight for example and do it in viewdidload

By this your container view will goes up to 100 pixels.

when resign keyboard you can add 100 to it's constant to get initial position back. Hope this will help :)

Upvotes: 0

Abhinandan Pratap
Abhinandan Pratap

Reputation: 2148

add UITextFieldDelegate in .h file and try the following code it will surely help you

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
    if (textField == username)
    {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardDidShowNotification object:nil];

    }
    if (textField == password)
    {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardDidShowNotification object:nil];

    }

    return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{

}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
    if (textField == username)
    {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardDidHideNotification object:nil];
    }

    if (textField == password)
    {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardDidShowNotification object:nil];

    }
    return YES;
}


- (void)keyboardWillShow:(NSNotification *)notification
{
    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    float newVerticalPosition = -keyboardSize.height + 100;

    [self moveFrameToVerticalPosition:newVerticalPosition forDuration:0.3f];
}


- (void)keyboardWillHide:(NSNotification *)notification
{
    CGFloat  kNavBarHeight =  self.navigationController.navigationBar.frame.size.height;
    [self moveFrameToVerticalPosition:kNavBarHeight forDuration:0.3f];
}


- (void)moveFrameToVerticalPosition:(float)position forDuration:(float)duration
{
    CGRect frame = self.view.frame;
    frame.origin.y = position;

    [UIView animateWithDuration:duration animations:^{
        self.view.frame = frame;
    }];
}

Upvotes: 0

user5917312
user5917312

Reputation:

As I understand the question, you are trying to shift the entire view when the UITextField becomes the first responder (i.e. adds the keyboard to the view)? If that is the case, I would add code in the UITextField delegate method:

#define VIEW_TAG 12345
#define kKeyboardOffsetY 80.0f

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    // get a reference to the view you want to move when editing begins
    // which can be done by setting the tag of the container view to VIEW_TAG
    UIView *containerView = (UIView *)[self.view viewWithTag:VIEW_TAG];
    [UIView animateWithDuration:0.3 animations:^{
        containerView.frame = CGRectMake(0.0f, -kKeyboardOffsetY, containerView.frame.size.width, containerView.frame.size.height);
    }];
}

- (void)textFieldDidEndEditing:(UITextField *)textField {
    UIView *containerView = (UIView *)[self.view viewWithTag:VIEW_TAG];
    [UIView animateWithDuration:0.3 animations:^{
        containerView.frame = CGRectMake(0.0f, self.view.frame.origin.y, containerView.frame.size.width, containerView.frame.size.height);
    }];
}

Upvotes: 0

Related Questions