そのブログ投稿は素晴らしいですが、いくつかの改善を提案したいと思います。まず、フレームの変更を監視するために登録できるため、通知の表示と非表示の両方を監視するために登録する必要はありません。次に、キーボードの CGRects を画面座標からビュー座標に変換する必要があります。最後に、iOS がキーボード自体に使用する正確なアニメーション カーブをコピーして、キーボードとトラッキング ビューが同期して動くようにすることができます。
すべてをまとめると、次のようになります。
@interface MyViewController ()
// This IBOutlet holds a reference to the bottom vertical spacer
// constraint that positions the "tracking view",i.e., the view that
// we want to track the vertical motion of the keyboard
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomVerticalSpacerConstraint;
@end
@implementation MyViewController
-(void)viewDidLoad
{
[super viewDidLoad];
// register for notifications about the keyboard changing frame
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillChangeFrame:)
name:UIKeyboardWillChangeFrameNotification
object:self.view.window];
}
-(void)keyboardWillChangeFrame:(NSNotification*)notification
{
NSDictionary * userInfo = notification.userInfo;
UIViewAnimationCurve animationCurve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] intValue];
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// convert the keyboard's CGRect from screen coords to view coords
CGRect kbEndFrame = [self.view convertRect:[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]
fromView:self.view.window];
CGRect kbBeginFrame = [self.view convertRect:[[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue]
fromView:self.view.window];
CGFloat deltaKeyBoardOrigin = kbEndFrame.origin.y - kbBeginFrame.origin.y;
// update the constant factor of the constraint governing your tracking view
self.bottomVerticalSpacerConstraint.constant -= deltaKeyBoardOrigin;
// tell the constraint solver it needs to re-solve other constraints.
[self.view setNeedsUpdateConstraints];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:animationCurve];
[UIView setAnimationBeginsFromCurrentState:YES];
// within this animation block, force the layout engine to apply
// the new layout changes immediately, so that we
// animate to that new layout. We need to use old-style
// UIView animations to pass the curve type.
[self.view layoutIfNeeded];
[UIView commitAnimations];
}
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillChangeFrameNotification
object:nil];
}
@end
キーボードを上げている間に方向を変えない限り、これは機能します。
数値キーボードに「完了」ボタンを追加するには、iOS 7 でキーボード アニメーションを模倣する方法についての回答でした。キーボード アニメーション カーブを正しく模倣する方法を示しました。
これらすべての通知ベースのソリューションに関して、最後に 1 つ注意してください。アプリ内の他の画面でもキーボードを使用すると、予期しない影響が生じる可能性があります。ビュー コントローラーは、割り当てが解除されていない限り、引き続き通知を受け取るためです。 、ビューがアンロードされている場合でも。これに対する解決策の 1 つは、通知ハンドラーに条件を付けて、View Controller が画面上にある場合にのみ動作するようにすることです。