InputAccessoryView停靠在底部

Sti*_*and 46 uitoolbar uinavigationcontroller uikeyboard uiresponder ios

我正在尝试实现与Apple的消息应用程序中底部文本输入栏类似的定位行为.

我尝试了许多方法,搜索高低,有许多类似的问题,但没有一个令人满意.

指定:

  1. UIToolbar视图的底部有一个
  2. 当键盘出现并消失时,工具栏将跟随键盘
  3. 当键盘可见时,工具栏应保持在键盘顶部
  4. 键盘隐藏后,工具栏将保持("停靠")在视图的底部

建议的解决方案:

手动设置工具栏的动画以响应键盘外观通知

此解决方案不符合第二个要求的特殊情况(工具栏是在键盘出现和消失时跟随键盘):

  • 在iOS 7中,UIScrollViewKeyboardDismissMode被介绍了.它启用了用于解除键盘的交互式手势.当用户翻过键盘的顶部边缘时,键盘框架逐渐跟随.此解决方案无法容纳此行为,只是将工具栏搁置在其动画位置.

此外,此解决方案也无法满足第三个要求的特殊情况(当键盘可见时,工具栏应保持在键盘顶部):

  • 回转.这个解决方案需要额外的,烦人的无关代码(我们将在下一个提出的解决方案中看到)来旋转工具栏以响应设备旋转.

此解决方案的另一个问题:

  • 键盘高度.使用此解决方案,工具栏不会被假定为键盘高度的一部分,因此必须编写其他代码以支持正确插入内容.

下一个提出的解

UIResponderinputAccessoryView

这个解决方案似乎是Apple打算支持这种行为的方式,因为它解决了手动设置工具栏动画的所有缺点.但是这个解决方案完全忽略了第四个要求(当键盘被隐藏时,工具栏保持("停靠")在视图的底部).


似乎解决方案是使用UIResponder's inputAccessoryView,但不知何故使得inputAccessoryView不移动到视图之下.我正在寻找干净的代码来实现这一目标.在其他地方有精心制作的,几乎是高贵的尝试,但如上所述,它们不符合要求.

在我的特定情况下,我希望使用UINavigationController工具栏,这需要额外的问题,因为这不是预期的行为UINavigationController.无论如何,我愿意介绍一些hacky修复来实现这一目标.

小智 57

我刚刚看到Jason Foreman(@threeve)的"解决方案".在视图控制器上(是的,视图控制器)添加inputAccessoryView:并返回要在底部停靠的视图并使用键盘移动.它只是有效.视图实际上不需要位于视图层次结构中,视图控制器将自动插入该视图.

编辑:还实现canBecomeFirstResponder并返回YES(如Max Seelemann所述).reloadInputViews也很方便.

  • 很高兴看到这个"神奇"解决方案的完整代码示例. (25认同)
  • 我得到`***终止应用程序由于未捕获的异常'UIViewControllerHierarchyInconsistency',原因:'子视图控制器:<UICompatibilityInputViewController:0x159ec54b0>应该有父视图控制器:<ULPostViewController:0x157dec330>但请求的父级是:<UIInputWindowController:0x1580f0800> ''这种方法有误.(iOS 8.3) (12认同)
  • 您应该添加视图控制器***需要从`-canBecomeFirstResponder`返回`YES`并且需要使自己成为第一个响应者.但在那之后 - 只是魔术.+100;) (2认同)

小智 30

Jonathan Badeen的上述解决方案为我工作.这里是来自Arik的代码,展示了如何实现它(这应该在适当的视图控制器中):

    - (BOOL)canBecomeFirstResponder{

        return YES;

    }

    - (UIView *)inputAccessoryView{

        return self.inputAccessoryToolbar;  
     // where inputAccessoryToolbar is your keyboard accessory view

    }
Run Code Online (Sandbox Code Playgroud)


jon*_*tyo 9

对于那些寻找Swift版本的人:

将工具栏(在我的情况下myToolBar')连接到视图控制器.然后覆盖canBecomeFirstResponder方法并覆盖getter inputAccessoryView变量.另外别忘了添加self.myToolBar.removeFromSuperview()或者xcode会抱怨.

class ViewController: UIViewController {

    @IBOutlet var myToolBar: UIToolbar!

    override func canBecomeFirstResponder() -> Bool {
        return true
    }


    override var inputAccessoryView:UIView{
        get{
            return self.myToolBar
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.myToolBar.removeFromSuperview()
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我用 STVC 测试过,但我不喜欢只为一个基本的 TextView 添加这么多代码,而且 STVC 不能完全适应故事板,需要使用 XIB。我最失望的是它不是一个真正的配件栏视图,它不适应 Whatsapp / iMessage 中的交互式关闭。我仍然没有找到更好的解决方案。但如果您只需要 100% 兼容简单输入 TextView 的故事板,那么值得查看 https://github.com/muukii/NextGrowingTextView。但是,这个也不适应配件栏视图.. (2认同)

小智 6

Slack的优秀人员:SlackTextViewController提供了一个优秀的,易于实现的开源解决方案.

以下是如何使用停靠工具栏分四步实现视图:

  1. 将pod安装到项目中.(http://cocoapods.org/?q=SlackTextViewController)
  2. 如果您正在Swift中编写应用程序,请创建一个标头以在Swift代码和它们的Obj-C类之间架起桥梁.这是一个很好的快速演练.(一旦将类翻译成Swift,就没有必要使用桥接头,任何人都希望就此进行协作?)
  3. 创建一个MessageViewController继承自SLKTextViewController,不需要再编写代码的代码:

    import Foundation
    import UIKit
    
    class MessageViewController: SLKTextViewController {
    
        required init(coder aDecoder: NSCoder!) {
            super.init(coder: aDecoder)
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 在Storyboard中,创建一个继承自MessageViewController的View Controller.
  5. 在设备或模拟器上测试应用程序,您将看到一个漂亮的停靠文本栏,当用户编写其他文本行时,它也会(作为奖励)扩展.

Slack团队的道具,用于提取这样一个有用的pod.