iPad分屏键盘

9
我正在开发一款与iPad的iMessage应用程序类似的应用程序,用于消息传递。因此,在显示键盘时,消息视图底部有一个输入视图和输入附件视图。而且当键盘停靠或未停靠时,必须正确地调整消息视图的大小。
我的问题是来自UIKeyboardWillChangeFrameNotification的通知数据不一致。
首先,用户可以通过以下3种方式取消停靠键盘:
1. 按住右下角键,然后向上滑动 2. 按住右下角键,当菜单弹出时,选择“取消停靠” 3. 按住右下角键,当菜单弹出时,选择“拆分”
对于情况#1,UIKeyboardWillChangeFrameNotification中的通知数据是一致的。以下是数据:
userInfo = {
    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 0}, {768, 304}}";
}

对于第二和第三种情况,数据不一致,以下是我收到的内容:
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}}";
}

这里奇怪的是,在第二或第三种情况下监听UIKeyboardDidChangeFrameNotification时,数据如预期一样返回:
userInfo = {
    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 0}, {768, 304}}";
}

为什么通知数据不同?有人找到了检测分屏键盘事件的明确方法吗?
2个回答

3
没有明确的方法。
我将在以下步骤中解决这个问题:
  1. 获取当前方向。
  2. 如果方向为横屏,则获取 UIKeyboardFrameEndUserInfoKey 的 height。它必须等于 216。这意味着键盘处于拆分模式,否则不是;
  3. 如果方向为纵向,则获取 UIKeyboardFrameEndUserInfoKey 的 height。它必须等于 216。这意味着键盘处于拆分模式,否则不是;

我使用 convertRect 方法更新了我的 gist 示例。


这会让事情变得更加困难,因为iPad Mini已经推出了。我甚至还没有接触过iOS 7... - Takeshi Kaga
2
216 不是像素,它是独立于分辨率的点参数。但这在 iPhone 4s 和 5 上不起作用。而且 iPhone 没有分屏键盘。它们改变了形态因素。 - Bimawa
注意,这不是一个好的解决方案。键盘高度会根据语言环境、iOS版本和设备而变化。 - capikaw
@capikaw 216不是静态参数,它是与UIKeyboardFrameEndUserInfoKey键一起传递的数字。 - Bimawa

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的inputAccessoryView的UITextField / UITextView(您可以只使用一个空视图)。
注意: textField.inputAccessoryView.superview的行为相当棘手,并且通常取决于在调用superview之前是否显示了键盘。此外,为了通过App Store提交过程,我从私有类名称中删除了“UI”前缀。这并不能保证苹果不会标记您的应用程序,但此方法以前已经成功使用过。
我只在iOS7上进行了测试,但如果在其他版本的iOS上无法正常工作,则可以使用类似的方法。

这可能有效,但是为什么要访问subviews 0 0 1 0? - Daij-Djan
由于它通过查找实际呈现键盘的私有类来遍历视图层次结构。我使用Reveal查看键盘视图的状态。请参见此处 - cagey
这段代码显然不适合在生产环境中使用,但希望这个答案对一些人仍然有用。 - cagey
你不能使用类名,因为它们是私有的,所以在App Store上是不被允许的。显然,如果您将其实现到生产代码中,应编写比我的简短答案更安全的代码。UIKit生成键盘的方式每次都是一致的,所以这种方法确实可以可靠地工作。 - cagey
不可以,名称并不被认为是禁区 - 符号才是。我在N个应用程序中都这样做了,而且已经这样做了多年。 - Daij-Djan
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接