简体   繁体   中英

Custom UIView is Pushing Partial Contents Up When the Keyboard is Shown

I have built out a custom UIView that I add to a UIViewController.

在此处输入图片说明

I would like for my custom UIView to move up to show any textfields hidden by the keyboard. However, it seems to only push other elements of the UIView up.

What did I do wrong? Without the keyboard:

在此处输入图片说明

Notice how the date and the company name get pushed up behind the UITextFields when the keyboard is shown

在此处输入图片说明

LogInViewController.m

@interface LogInViewController () <UITextFieldDelegate> {
    LoginView * loginView;
}
@property (nonatomic, assign) CGRect   keyboardFrame;
@end

- (void)viewDidLoad {
    [super viewDidLoad];

    loginView = [[LoginView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:loginView];

    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver:self selector:@selector(handleKeyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
    [nc addObserver:self selector:@selector(handleKeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

- (void)handleKeyboardDidShow:(NSNotification *)notification {
    NSTimeInterval animationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];

    _keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    _keyboardFrame = [self.view convertRect:_keyboardFrame fromView:self.view.window];

    [UIView animateWithDuration:animationDuration animations:^{
        CGRect frm = loginView.frame;
        frm.size.height = CGRectGetMinY(_keyboardFrame);
        loginView.frame = frm;
    }];
}

- (void)handleKeyboardWillHide:(NSNotification *)notification {
    NSTimeInterval animationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];

    [UIView animateWithDuration:animationDuration animations:^{
        CGRect frm = loginView.frame;
        frm.size.height = CGRectGetMaxY(self.view.bounds);
        loginView.frame = frm;
    }];
}

LoginView.h

@interface LoginView : UIView
@property (strong, nonatomic) IBOutlet UIView *contentView;
@property (weak, nonatomic) IBOutlet UITextField *txtUsername;
@property (weak, nonatomic) IBOutlet UITextField *txtPassword;
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *indicator;
@property (weak, nonatomic) IBOutlet UIButton *btnSignin;
@property (weak, nonatomic) IBOutlet UILabel *lblVersion;
@property (weak, nonatomic) IBOutlet UILabel *lblMessageArea;
@end

LoginView.m

@implementation LoginView
- (instancetype) initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if(self){

        [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil];
        [self addSubview:self.contentView];
        self.contentView.frame = self.bounds;
    }
    return self;
}
@end

You overwrite _keboardFrame, so the first assignment is useless.

    _keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    _keyboardFrame = [self.view convertRect:_keyboardFrame fromView:self.view.window];

I recommend to use UIKeyboardWillShowNotification to have a more consistent animations:

// for your code, I prefer case 1, to shift up the entire view. Anyway, if you want, you can use the second option that I've commented. But the best option is to use constraints, then update that constraint
- (void)keyboardWillShow:(NSNotification *)notification {
    NSTimeInterval animationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];

    CGFloat keyboardHeight = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;

    [UIView animateWithDuration:animationDuration animations:^{
        CGRect frm = loginView.frame;
        // 1. move up the view
        frm.origin.y = -keyboardHeight;
        // 2. change the height
        //frm.size.height = self.view.bounds.size.height - keyboardHeight;
        loginView.frame = frm;
    }];
}

- (void)keyboardWillHide:(NSNotification *)notification {
    NSTimeInterval animationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
        [UIView animateWithDuration:animationDuration animations:^{
            loginView.frame = self.view.bounds;
        }];
}

Is this ok for you?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM