【问题标题】:Leaving inputAccessoryView visible after keyboard is dismissed关闭键盘后让 inputAccessoryView 可见
【发布时间】:2012-06-01 21:02:49
【问题描述】:

我想做的是在 iPad 上的 Safari 中创建类似于“在页面上查找”搜索功能的功能。

我正在使用带有一些项目的UIToolbar,并通过在UITextField 上将其设置为inputAccessoryView 将其连接到键盘。像魅力一样工作,但有一件事我无法弄清楚。在 Safari 中,当您搜索某些内容时,键盘会消失,但工具栏仍保留在屏幕底部。

有没有人知道如何做到这一点?我能想到的唯一解决方案是响应键盘关闭事件,然后拉出UIToolBar 并创建一个自定义动画,将其移动到屏幕底部。但这是骇人听闻的。我正在寻找更优雅的解决方案。当键盘被关闭时,可以让我决定如何处理输入附件视图。

【问题讨论】:

    标签: ios user-interface uitoolbar uikeyboard


    【解决方案1】:

    根据之前的答案更新到 Swift 4。如果您通过storyboards 添加工具栏,您可以这样做

    class ViewController: UIViewController {
    
        @IBOutlet weak var textField: UITextField!
        @IBOutlet var toolbar: UIToolbar!
    
        override var canBecomeFirstResponder: Bool {
            get {
                return true
            }
        }
    
        override var inputAccessoryView: UIView {
            get {
                return self.toolbar
            }
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            textField.inputAccessoryView = toolbar
        }
    }
    

    在这种情况下,每当文本字段退出第一响应者时,它默认第一响应者为主视图。请记住,如果有多个 UI 元素并且第一响应者在辞职后默认为不想要的视图,您可能希望显式退出第一响应者,并将主视图设置为第一响应者。

    【讨论】:

      【解决方案2】:

      您可能还需要解决 inputAccessoryView 不遵守安全区域边距的错误,因此没有为 iPhone X 上的主页指示器腾出空间:iPhone X how to handle View Controller inputAccessoryView?

      当您有一个来自 xib 的 UIToolbar 并且您还使用该 UIToolbar 作为文本字段的 inputAccessoryView 时,我发现最简单的解决方案是,当您从覆盖的 inputAccessoryView 返回它时,将工具栏嵌入到 UIView 中,并使包含由 safeAreaInsets.bottom 更高的 UIView。 (其他解决方案建议将工具栏的底部约束到子类中的安全区域,但这会导致约束冲突,也意味着工具栏下的区域颜色错误。)但是,您还必须记住,文本即使屏幕上没有键盘(例如,如果有外部键盘),字段也可以具有焦点,因此在这种情况下,您也需要将文本视图的 inputAccessoryView 更改为此工具栏-in-a-UIView。事实上,总是使用包含视图并适当地调整它的大小可能会使事情变得更简单。无论如何,这是我对 inputAccessoryView 的覆盖:

          override var inputAccessoryView: UIView? {
      
          if toolbarContainerView == nil {
      
              let frame=CGRect(x: toolBar.frame.minX, y: toolBar.frame.minY, width: toolbar.frame.width, height: toolBar.frame.height+view.safeAreaInsets.bottom)
      
              toolbarContainerView = UIView(frame: frame)
      
          }
      
          if (toolbar.superview != toolbarContainerView) {
      
              //this is set to false when the toolbar is used above the keyboard without the container view
      
              //we need to set it to true again or else the toolbar will appear at the very top of the window instead of the bottom if the keyboard has previously been shown.
      
              toolbar.translatesAutoresizingMaskIntoConstraints=true
      
              toolbarContainerView?.addSubview(toolbar)
      
          }
      
          return toolbarContainerView
      
      }
      

      在这种情况下,重写 viewSafeAreaInsetsDidChange 以调整 toolbarContainerView 的大小可能是个好主意。

      【讨论】:

        【解决方案3】:

        添加到@arik 的答案,这里是 Swift 版本:

        class ViewController: UIViewController {
        
          @IBOutlet var textField: UITextField!      
        
          // Input Accessory View
          private var inputAccessoryToolbar: UIToolBar?
          override func canBecomeFirstResponder() -> Bool {
            return true
          }
          override var inputAccessoryView: UIView? {
            return inputAccessoryToolbar
          }
        
          override func viewDidLoad() {
            super.viewDidLoad()
            inputAccessoryToolbar = UIToolbar(frame: CGRectMake(0, 0, view.frame.size.width, 50))
            textField.inputAccessoryView = inputAccessoryToolbar
          }
        
          // UITextFieldDelegate
          func textFieldShouldReturn(textField: UITextField) -> Bool {
            becomeFirstResponder()
            return true
          }
        }
        

        感谢您提供干净的解决方案!

        【讨论】:

        • 在 Swift 3/4 中,canBecomeFirstResponderinputAccessoryView 现在是属性而不是函数/方法。
        【解决方案4】:

        这样做是这样的:

        将您的 UIToolbar 分配给视图控制器中的属性:

        @property (strong, nonatomic) UIToolbar *inputAccessoryToolbar;
        

        在您的顶视图控制器中,添加以下方法:

        - (BOOL)canBecomeFirstResponder{
        
            return YES;
        
        }
        
        - (UIView *)inputAccessoryView{
        
            return self.inputAccessoryToolbar;
        
        }
        

        然后(可选,因为通常不需要),只要键盘被隐藏,只需调用:

        [self becomeFirstResponder];
        

        这样,您的 inputAccessoryToolbar 将同时是您的视图控制器和文本视图的输入附件视图。

        【讨论】:

        • 它似乎在 iOS8 上不起作用,我得到 UIViewControllerHierarchyInconsistency,有什么想法吗?
        • 它确实适用于我的 iOS 8,所以我可能需要一个代码示例。
        • 刚刚创建了新的示例项目,通过情节提要在底部添加了视图,对其进行了出口,并在 inputAccessoryView 方法中返回了该视图...我得到了与我的项目相同的错误。
        • 我为iOS8打开了新问题,你可以在这里找到它stackoverflow.com/questions/28496409/…
        • 这应该被接受的答案:) 它在 iOS8 上工作
        【解决方案5】:

        我最终得到了未指定为输入附件视图的UIToolBar,并在UIKeyboardWillShowNotification / UIKeyboardWillHideNotification 上上下滑动

        【讨论】:

        • 谢谢,我想这确实是唯一的方法。
        • 这也是我目前正在做的事情,来到这里希望有另一种解决方案。不过我猜不是:(
        • @BradMoore,还有另一种解决方案。请查看我的回答。
        • 此解决方案是否与表格视图一起使用,以交互方式关闭键盘?
        猜你喜欢
        • 2015-04-14
        • 1970-01-01
        • 1970-01-01
        • 2014-05-14
        • 2018-06-11
        • 2017-11-17
        • 1970-01-01
        • 2021-03-28
        • 1970-01-01
        相关资源
        最近更新 更多