27

iOS 6 の自動レイアウトに重点が置かれ、Apple エンジニア ( WWDC 2012 のビデオを参照) がビューのフレームを直接操作しないように勧告したことを考えると、自動レイアウトと NSLayoutConstraint のみを使用してキーボードを回避するにはどうすればよいでしょうか?

アップデート

これは合理的な解決策のように見えます:キーボードに敏感なレイアウトの例( GitHub ソース)ですが、ユーザーがデバイスを回転させ、キーボードが既に画面に表示されている場合に発生する可能性のある問題の 1 つです。

4

6 に答える 6

7

SpringフレームワークでKeyboardLayoutConstraintを使用することは、これまでに見つけた最も簡単な解決策です。 KeyboardLayoutConstraint

于 2015-02-01T17:05:02.347 に答える
7

そのブログ投稿は素晴らしいですが、いくつかの改善を提案したいと思います。まず、フレームの変更を監視するために登録できるため、通知の表示と非表示の両方を監視するために登録する必要はありません。次に、キーボードの 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 が画面上にある場合にのみ動作するようにすることです。

于 2013-11-23T01:09:11.300 に答える
6

My idea is to create a UIView, let's call it keyboard view, and place it to your view controller's view. Then observe keyboard frame change notifications UIKeyboardDidChangeFrameNotification and match the frame of the keyboard to the keyboard view (I recommend to animate the change). Observing this notification handles the rotation you mentioned and also moving keyboard on iPad.

Then simply create your constraints relative to this keyboard view. Don't forget to add the constraint to their common superview.

To get the keyboard frame correctly translated and rotated to your view coordinates check out the docs for UIKeyboardFrameEndUserInfoKey.

于 2012-11-28T21:07:06.313 に答える
1

私はあなたのためにそれをすべて行うライブラリを書きました(自動レイアウトとSprings&Strutsをサポートしています)

IHKeyboardAvoiding https://github.com/IdleHandsApps/IHKeyboardAvoiding

[IHKeyboardAvoiding setAvoidingView:self.myView]; を呼び出すだけです。

于 2014-12-15T00:47:02.403 に答える
0

キーボード ケースを使用した自動レイアウトには、静的なテーブル ビューを使用します。これにより、コードがはるかにシンプルになり、キーボードの高さを追跡する必要がなくなります。テーブル ビューについて学んだことの 1 つは、テーブルの各行をできるだけ狭くすることです。1 行に UI を縦方向に配置しすぎると、キーボードが重なる場合があります。

于 2012-11-02T17:59:48.480 に答える