【问题标题】:Messenger style UITextView inputMessenger 风格的 UITextView 输入
【发布时间】:2017-10-08 14:35:41
【问题描述】:

我正在将一个简单的聊天作为我的应用程序的一部分。 我在表视图控制器和聊天视图控制器中有一个聊天列表(即朋友),显示每个聊天的消息。它们都嵌入在 NavigationController 中,而 NavigationController 嵌入在 TabBarController 中。

我想将 UITextView 消息文本输入字段放在我的 UITableVeiw 下方的 ChatViewController 中,以显示该聊天的消息。我还希望 UITextView 看起来像嵌入在选项卡栏中。 我已经浏览了几十个手册教程和指南,这就是我目前所了解的。

此处的应用模拟器屏幕截图:顶部不错,底部有问题

此处为 Main.storyboard 截图

  1. 我使用 UITextView 而不是 UITextField,因为我希望它能够根据内容大小更改其大小
  2. 我使用 UIViewController 而不是 UITableViewController 来添加另一个 UIView 和 UITableView
  3. 我不使用实际的 UITabBar 来嵌入我的 UITextView,因为当 UITextView 需要更改其高度时,它的行为非常奇怪。据我了解,Apple 不支持将 UI 元素嵌入到 UITabBar
  4. 我所做的是在 ChatViewController viewWillAppear 中隐藏 TabBar:

    override func viewWillAppear(_ animated: Bool) {
        tabBarController?.tabBar.isHidden = true
    }       
    

    我在父 ChatsTableViewController 中再次显示它:

    override func viewWillAppear(_ animated: Bool) {
        tabBarController?.tabBar.isHidden = false
    }
    
  5. 一旦 TabBar 被隐藏,我嵌入 textView 和 sendButton 的自定义 stackView 就会取而代之,并按照我的意愿正常运行。

  6. 为了正确处理键盘行为,我为 inputStackView 底部约束(在屏幕截图中选择)提供了一个出口,我在 keyboardWillShow/Hide Notifications 上进行了更新。代码如下所示:

    @IBOutlet weak var inputBottomConstraint: NSLayoutConstraint!
    var inputBottomConstraintInitialValue: CGFloat!
    
    //MARK: - Keyboard handling
    private func enableKeyboardHideOnTap(){
    
        NotificationCenter.default.addObserver(self, selector: #selector(ChatTableViewController.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(ChatTableViewController.keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ChatTableViewController.hideKeyboard))
    
        self.view.addGestureRecognizer(tap)
    }
    
    @objc func hideKeyboard() {
        textView.resignFirstResponder()
    }
    
    @objc func keyboardWillShow(notification: NSNotification) {
    
        let info = notification.userInfo!
        let keyboardFrame: CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        let duration = info[UIKeyboardAnimationDurationUserInfoKey] as! Double
    
        UIView.animate(withDuration: duration) { [weak self] () -> Void in
            self?.inputBottomConstraint.constant = keyboardFrame.size.height + 8
            self?.view.layoutIfNeeded()
        }
    }
    
    @objc func keyboardWillHide(notification: NSNotification) {
    
        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
    
        UIView.animate(withDuration: duration) { [weak self] () -> Void in
            guard let `self` = self else { return }
            self.inputBottomConstraint.constant = self.inputBottomConstraintInitialValue
            self.view.layoutIfNeeded()
        }
    }
    

此时似乎一切正常:

  • TabBar 隐藏在 ChatViewController 中并显示在 ChatsTableViewController 中
  • 嵌入在 stackView 中的 textView 和 sendButton 将上下滑动键盘,如上面的模拟器屏幕截图所示。

当我在 ChatViewController 和 ChatsTableViewController 之间滑动而不是使用 NavigationControllers 时出现 BUG

当我开始滑回 ChatsTableViewController 时,它会执行 viewWillAppear 方法,因此 tabBarController 的 tabBar 变得可见。如果我没有完成对 ChatsTableViewController 的滑动并返回 ChatViewController,ChatViewController 的 viewWillAppear 会将其设置回不可见,但输入 stackView 不会回到它的初始位置。它只是挂在不可见的 tabBar 上方。

我试过移动

tabBarController?.tabBar.isHidden = false

ChatsTableViewController 中从 viewWillAppear 到 viewDidAppear。 它修复了“浮动输入”问题,但是当 ChatsTableViewController 显示没有 tabBar 时,它增加了大约一秒钟的延迟。看起来也不太好。

任何想法如何正确修复? 我已经在这个问题上苦苦挣扎了大约一周))

【问题讨论】:

    标签: ios swift uikit


    【解决方案1】:

    因为您的ChatsTableViewController 嵌入在UINavigationController 中并且您的ChatViewController 被推送,您可以在ChatViewController 中覆盖此hidesBottomBarWhenPushed,这将决定是否显示您的视图控制器:

    public override var hidesBottomBarWhenPushed: Bool {
        get { return true }
        set { super.hidesBottomBarWhenPushed = newValue }
    }
    

    这是在我的脑海中隐藏标签栏的更好方法,因为视图控制器的框架将被调整。

    【讨论】:

    • 这是一个很棒的解决方案!谢谢!它使一切都按我需要的方式工作。但是我还是不太明白,它的 set { ... } 部分是什么时候触发的?
    【解决方案2】:

    为什么要更改键盘显示/隐藏的约束。尝试谷歌输入AccesoryView,很多聊天都用它。使用键盘是很自然的行为。以 FaceBook Messenger 为例,看看滑动是如何将键盘和文本框隐藏在一起的,你无法在常规视图中完成这种奇怪的行为。

    【讨论】:

    • 非常感谢,我一定会尝试谷歌搜索并在这里使用 inputAccessoryView。
    猜你喜欢
    • 1970-01-01
    • 2018-12-23
    • 1970-01-01
    • 2015-02-06
    • 2019-05-07
    • 1970-01-01
    • 2011-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多