jjzjj

ios - Messenger 风格的 UITextView 输入

coder 2024-01-28 原文

我正在将一个简单的聊天作为我应用程序的一部分。 我在 TableView Controller 和聊天 View Controller 中有一个聊天列表(即 friend ),显示每个聊天的消息。它们都嵌入到 NavigationController 中,而 NavigationController 又嵌入到 TabBarController 中。

我想将 UITextView 消息文本输入字段放置在我的 UITableVeiw 下面的 ChatViewController 中,它显示该聊天的消息。我还希望 UITextView 看起来像是嵌入在选项卡栏中。 到目前为止,我已经浏览了数十本手册教程和指南。

此处为 App 模拟器屏幕截图:顶部不错,底部有问题

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 被隐藏,我的自定义 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()
        }
    }
    

此时一切似乎都正常:

  • 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。 它修复了“ float 输入”问题,但是当 ChatsTableViewController 在没有 tabBar 的情况下显示时,它会增加大约一秒的延迟。看起来也不太好。

关于如何正确解决这个问题有什么想法吗? 我已经为这个问题苦苦挣扎了大约一个星期))

最佳答案

因为您的 ChatsTableViewController 嵌入在 UINavigationController 中并且您的 ChatViewController 被推送,您可以覆盖此 hidesBottomBarWhenPushed ChatViewController 将决定是否显示您的 View Controller :

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

这是隐藏选项卡栏的更好方法,因为 View Controller 的框架将被调整。

关于ios - Messenger 风格的 UITextView 输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46632270/

有关ios - Messenger 风格的 UITextView 输入的更多相关文章

  1. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  2. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  3. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  4. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  5. ruby - 鸭子输入字符串、符号和数组的优雅方式? - 2

    这是针对我无法破坏的现有公共(public)API,但我确实希望对其进行扩展。目前,该方法采用字符串或符号或任何其他在作为第一个参数传递给send时有意义的内容我想添加发送字符串、符号等列表的功能。我可以只使用is_a吗?数组,但还有其他发送列表的方法,这不是很像ruby​​。我将调用列表中的map,所以第一个倾向是使用respond_to?:map。但是字符串也会响应:map,所以这行不通。 最佳答案 如何将它们全部视为数组?String的行为与仅包含String的Array相同:deffoo(obj,arg)[*arg].eac

  6. ruby - 为什么不能使用类IO的实例方法noecho? - 2

    print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上

  7. c - Ruby - 源代码 - 编码风格 - 2

    查看Ruby代码,它具有以下proc_arity:staticVALUEproc_arity(VALUEself){intarity=rb_proc_arity(self);returnINT2FIX(arity);}更多的是C编码风格问题,但为什么staticVALUE在单独的一行而不是像这样的:staticVALUEproc_arity(VALUEself) 最佳答案 它来自UNIX世界,因为它有助于轻松grep函数的定义:$grep-n'^proc_arity'*.c或使用vim:/^proc_arity

  8. ruby - ruby 中的同一个程序如何接受来自用户的输入以及命令行参数 - 2

    我的ruby​​脚本从命令行参数获取某些输入。它检查是否缺少任何命令行参数,然后提示用户输入。但是我无法使用gets从用户那里获得输入。示例代码:test.rbname=""ARGV.eachdo|a|ifa.include?('-n')name=aputs"Argument:#{a}"endendifname==""puts"entername:"name=getsputsnameend运行脚本:rubytest.rbraghav-k错误结果:test.rb:6:in`gets':Nosuchfileordirectory-raghav-k(Errno::ENOENT)fromtes

  9. Ruby:如何将数组拼接成 Lisp 风格的列表? - 2

    这是我发现自己偶尔想做的事情。假设我有一个参数列表。在Lisp中,我可以像这样`(imaginary-function,@args)为了调用将数组从一个元素转换为正确数量的参数的函数。Ruby中是否有类似的功能?或者我只是在这里使用了一个完全错误的成语? 最佳答案 是的!它被称为splat运算符。a=[1,44]p(*a) 关于Ruby:如何将数组拼接成Lisp风格的列表?,我们在StackOverflow上找到一个类似的问题: https://stackov

  10. ruby-on-rails - 为什么用户必须输入 7 位数的 Twitter PIN 才能授予我的应用程序访问权限? - 2

    我正在为我的用户实现一些ruby​​onrails代码推特内容。我正在创建正确的oauth链接...类似http://twitter.com/oauth/authorize?oauth_token=y2RkuftYAEkbEuIF7zKMuzWN30O2XxM8U9j0egtzKv但在我的测试帐户授予对twitter的访问权限后,它会弹出一个页面,上面写着“您已成功授予对.我不知道用户应该在哪里输入此PIN以及他们为什么必须这样做。我认为这不是必要的步骤。Twitter应该将用户重定向到我在应用程序设置中提供的回调URL。有谁知道为什么会这样?更新我找到了thisarticle声明我需

随机推荐