読者です 読者をやめる 読者になる 読者になる

Keep It Real BLOG

ソフトウェアエンジニア。1児の父。 酒、ラーメン、サッカー好き。旅行も好きですが、普段は出不精で大抵たまプラーザ界隈に居ます。

iOSアプリでキーボード表示時にUITextViewが隠れてしまう問題について

f:id:naohide_a:20151202195340j:plain iOSアプリでキーボード表示するとUITextViewが隠れてしまう問題が起きたので、調査しました。

参考にしたのは、以下の記事2つ。 ・UITextView がキーボードに隠れないようにするキーボード表示するとTextViewが隠れてしまう問題

ただし、どちらも試してみたのですが、フルサイズでUITextViewを表示している際は良いのですが、UITextViewの上部になにか置いてる場合等は、問題が起こってしまったり、キーボードを閉じる際に問題が生じてしまったので、以下のように改善しました。良いとこ取りな感じで。

.hファイル

@interface TestViewController : UIViewController<UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource>
{
    CGRect textViewFrameSaved_;
    BOOL registered_;
}

@property (strong, nonatomic) IBOutlet UITextView *textView;

.mファイル

- (void)viewWillAppear:(BOOL)animated
{
    // super
    [super viewWillAppear:animated];
    
    // Register for notifiactions
    if (!registered_) {
        NSNotificationCenter *center;
        center = [NSNotificationCenter defaultCenter];
        [center addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
        [center addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
        
        registered_ = YES;
    }
}

- (void)viewWillDisappear:(BOOL)animated
{
    // super
    [super viewWillDisappear:animated];
    
    // Unregister from notification center
    if (registered_) {
        NSNotificationCenter *center;
        center = [NSNotificationCenter defaultCenter];
        [center addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
        [center addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
        
        registered_ = NO;
    }
}

- (void)keyboardWillShow:(NSNotification*)notification
{
    textViewFrameSaved_ = _textView.frame;
    
    // Get userInfo
    NSDictionary *userInfo;
    userInfo = [notification userInfo];
    
    // Calc overlap of keyboardFrame and textViewFrame
    CGFloat overlap;
    CGRect keyboardFrame;
    CGRect textViewFrame;
    keyboardFrame = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    keyboardFrame = [_textView.superview convertRect:keyboardFrame fromView:nil];
    textViewFrame = _textView.frame;
    overlap = MAX(0.0, CGRectGetMaxY(textViewFrame) - CGRectGetMinY(keyboardFrame));
    
    // Calc textViewFrameEnd
    CGRect textViewFrameEnd;
    textViewFrameEnd = _textView.frame;
    textViewFrameEnd.size.height -= overlap;
    
    // Animate frame of _textView
    NSTimeInterval duration;
    UIViewAnimationCurve animationCurve;
    void (^animations)(void);
    duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    animationCurve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
    animations = ^(void) {
        _textView.frame = textViewFrameEnd;
    };
    [UIView animateWithDuration:duration delay:0.0 options:(animationCurve << 16) animations:animations completion:nil];
}

- (void)keyboardWillHide:(NSNotification*)notification
{
    if (!CGRectIsEmpty(textViewFrameSaved_))
    {
        _textView.frame = textViewFrameSaved_;
        textViewFrameSaved_ = CGRectZero;
    }
}

自分はこれで、UITextViewが画面の途中に有っても問題なく動作しました。