web-dev-qa-db-ja.com

自動レイアウト制約-キーボード

自動レイアウト制約のあるテーブルビューをスムーズにアニメーション化しようとしてスタックしました。私の.hの制約「keyboardHeight」への参照があり、これをIBでリンクしました。テーブルビューがポップアップしたときに、キーボードでテーブルビューをアニメーション化するだけです。これが私のコードです:

- (void)keyboardWillShow:(NSNotification *)notification
{
    NSDictionary *info = [notification userInfo];
    NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    CGRect keyboardFrame = [kbFrame CGRectValue];
    CGFloat height = keyboardFrame.size.height;

    [UIView animateWithDuration:animationDuration animations:^{
        self.keyboardHeight.constant = -height;
        [self.view setNeedsLayout];
    }];
}

重要なのは、アニメーションブロックが瞬間的で、キーボードがアニメーションを終了する前に空白が表示されることです。キーボードがアニメーションしているので、基本的にはビューの白い背景が表示されます。キーボードがアニメーションしている限り、アニメーションを長持ちさせることはできません。

私はこれを間違った方法でアプローチしていますか?前もって感謝します!

34
Marty W

このようにしてみてください:

self.keyboardHeight.constant = -height;
[self.view setNeedsUpdateConstraints];

[UIView animateWithDuration:animationDuration animations:^{
   [self.view layoutIfNeeded];
}];

これは(WWDCに従って)制約ベースのレイアウトを更新する正しい方法であるため、このパターンを覚えておいてください。後でNSLayoutConstraintを呼び出す限り、setNeedsUpdateConstraintssを追加または削除することもできます。

52
John Estropia

UITableViewControllerを使用している場合、contentInsetsを調整するために、キーボードのサイズはiOSによって自動的に調整されます。しかし、tableViewがUIViewController内にある場合、おそらくこれを使用したいと思います。

KeyboardLayoutConstraintSpring フレームワーク内。これまでに見つけた最も簡単な解決策。 KeyboardLayoutConstraint

14
James Tang

次のコードを試してください。この場合、テーブルビューは画面の下端に配置されます。

- (void)keyboardWillShow:(NSNotification *)notification { // UIKeyboardWillShowNotification

    NSDictionary *info = [notification userInfo];
    NSValue *keyboardFrameValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    CGRect keyboardFrame = [keyboardFrameValue CGRectValue];

    BOOL isPortrait = UIDeviceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation);
    CGFloat keyboardHeight = isPortrait ? keyboardFrame.size.height : keyboardFrame.size.width;

    // constrBottom is a constraint defining distance between bottom Edge of tableView and bottom Edge of its superview
    constrBottom.constant = keyboardHeight; 
    // or constrBottom.constant = -keyboardHeight - in case if you create constrBottom in code (NSLayoutConstraint constraintWithItem:...:toItem:...) and set views in inverted order

    [UIView animateWithDuration:animationDuration animations:^{
        [tableView layoutIfNeeded];
    }];
}


- (void)keyboardWillHide:(NSNotification *)notification { // UIKeyboardWillHideNotification

    NSDictionary *info = [notification userInfo];
    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    constrBottom.constant = 0;
    [UIView animateWithDuration:animationDuration animations:^{
        [tableView layoutIfNeeded];
    }];
}
8
Grigori A.

私が取ったアプローチは、キーボードのサイズに従うビューを追加することです。テーブルビューまたはテキスト入力などの下に追加すると、キーボードが表示されたときにプッシュされます。

これは、ビュー階層を設定する方法です。

NSDictionary *views = @{@"chats": self.chatsListView, @"reply": self.replyBarView, @"fakeKeyboard":self.fakeKeyboardView};
[self.view addVisualConstraints:@"V:|-30-[chats][reply][fakeKeyboard]|" views:views];

そして、キーボードサイズに続くビューの主要な部分は次のようになります。

- (void)keyboardWillShow:(NSNotification *)notification
{
    // Save the height of keyboard and animation duration
    NSDictionary *userInfo = [notification userInfo];
    CGRect keyboardRect = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    self.desiredHeight = CGRectGetHeight(keyboardRect);
    self.duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];

    [self animateSizeChange];
}

- (void)keyboardWillHide:(NSNotification *)notification
{
    self.desiredHeight = 0.0f;

    [self animateSizeChange];
}

- (CGSize)intrinsicContentSize
{
    return CGSizeMake(UIViewNoIntrinsicMetric, self.desiredHeight);
}

- (void)animateSizeChange
{
    [self invalidateIntrinsicContentSize];

    // Animate transition
    [UIView animateWithDuration:self.duration animations:^{
        [self.superview layoutIfNeeded];
    }];
}

この特定のビューにサイズ変更を処理させることの良い点は、ビューコントローラーに無視させることができ、アプリ内のすべての位置をシフトしたい任意の場所でこのビューを再利用できることです。

完全なファイルはこちらです https://Gist.github.com/shepting/6025439

2
Steven Hepting