Messenger样式UITextView输入

时间:2017-10-08 14:35:41

标签: ios swift uikit

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

我想将UITextView消息文本输入字段放在我的UITableVeiw下面的ChatViewController中,该字段显示该聊天的消息。我还希望UITextView看起来像是嵌入在标签栏中。 我已经阅读了数十本手册教程和指南,以及我到目前为止的所在地。

App模拟器截图:顶部很好,底部有错误

App simulator screenshots here: nice at the top, buggy at the bottom

Main.storyboard截图在这里

Main.storyboard screenshot here

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

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

    我在父ChatsTableViewController中再次显示它:

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

  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()
        }
    }
    
  7. 此时似乎一切正常:

    • TabBar隐藏在ChatViewController中,显示在ChatsTableViewController
    • 嵌入在stackView幻灯片中的textView和sendButton将向上和向下键盘,如上面的模拟器截图所示。

    当我在ChatViewController和ChatsTableViewController之间轻扫而不是使用NavigationControllers时,会出现BUG

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

    我尝试过移动

    tabBarController?.tabBar.isHidden = false
    

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

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

2 个答案:

答案 0 :(得分:0)

由于您的ChatsTableViewController已嵌入UINavigationController并且ChatViewController被推送,您可以覆盖hidesBottomBarWhenPushed中的ChatViewController,这将决定显示您的观点控制器与否:

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

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

答案 1 :(得分:0)

为什么要改变键盘显示/隐藏的约束。尝试Google inputAccesoryView,很多聊天都使用它。它的自然行为是使用键盘。以TryBook Messenger为例,看看刷卡如何将键盘和Textfield隐藏在一起,你无法用常规视图完成这种od行为。