9

メッセージングを行うiPadのiMessageアプリに似たアプリを作成しています。そのため、キーボードが表示されているときは、メッセージビューと入力アクセサリビューの下部に固定された入力ビューがあります。また、ドッキングまたはドッキング解除中にキーボードが表示されている場合は、メッセージビューのサイズを適切に変更する必要があります。

私が抱えている問題は、UIKeyboardWillChangeFrameNotificationから受信する通知データに一貫性がないことです。

まず、ユーザーがキーボードをドッキング解除する方法は3つあります。

  1. 右下のキーを押したまま、上にスライドします
  2. 右下のキーを押したまま、メニューが表示されたら、[ドッキング解除]を選択します
  3. 右下のキーを押したままにして、メニューがポップアップしたら、「分割」を選択します

ケース#1の場合、UIKeyboardWillChangeFrameNotificationからの通知データは一貫しています。データは次のとおりです。

userInfo = {
    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 0}, {768, 304}}";
}

ケース#2と#3の場合、データに一貫性がありません。受け取ったものは次のとおりです。

userInfo = {
    UIKeyboardAnimationCurveUserInfoKey = 0;
    UIKeyboardAnimationDurationUserInfoKey = "0.25";
    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {768, 304}}";
    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {384, 872}";
    UIKeyboardCenterEndUserInfoKey = "NSPoint: {384, 1136}";
    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 0}, {768, 304}}";
    UIKeyboardFrameChangedByUserInteraction = 0;
    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, -264}, {768, 304}}";
}

ここで奇妙なのは、ケース#2または#3でUIKeyboardDidChangeFrameNotificationをリッスンすると、データが期待どおりに受信されることです。

userInfo = {
    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 0}, {768, 304}}";
}

通知データが異なるのはなぜですか?誰かが分割キーボードイベントを検出する明確な方法を見つけましたか?

4

2 に答える 2

3

明確な方法はありません。

次の手順でこの問題を解決します。

  1. 現在の向きを取得します。
  2. 向きが横の場合、UIKeyboardFrameEndUserInfoKey の高さを取得します。それは 216 に等しい必要があります。これは、キーボードが分割モードであることを意味します。それ以外の場合はそうではありません。
  3. 向きが縦の場合、UIKeyboardFrameEndUserInfoKey の高さを取得します。それは 216 に等しい必要があります。これは、キーボードが分割モードであることを意味します。それ以外の場合はそうではありません。

たとえば、要点を更新します。convertRect メソッドを使用。

于 2013-07-10T09:35:32.850 に答える
1

これはややハックですが、キーボードが分割されているかどうかを判断するための信頼できる方法です。

NSArray *classPath = @[
  @"KeyboardAutomatic",
  @"KeyboardImpl",
  @"KeyboardLayoutStar",
  @"KBKeyplaneView",
  @"KBSplitImageView"
];
UIView *splitView = textField.inputAccessoryView.superview;
for (NSString *className in classPath) {
  for (UIView *subview in splitView.subviews) {
    if ([NSStringFromClass([subview class]) rangeOfString:className].location != NSNotFound) {
      splitView = subview;
      break;
    }
  }
}
BOOL isSplit = [splitView.subviews count] > 1;

明らかにこれが機能するためには、非 nil の UITextField/UITextView が必要ですinputAccessoryView(そのために空のビューを使用できます)。

注:の動作textField.inputAccessoryView.superviewは非常に厄介で、通常は を呼び出す前に一度表示されたキーボードに依存しますsuperview。また、App Store の送信プロセスを通過させるために、プライベート クラス名から「UI」プレフィックスを削除しました。これは、Apple があなたのアプリにフラグを立てないという保証ではありませんが、このアプローチは以前に成功裏に使用されています。

iOS7 でのみテストしましたが、他のバージョンの iOS で動作しない場合は、同様のアプローチを使用できます。

于 2014-03-15T00:09:51.260 に答える