繁体   English   中英

在 UITableViewCell 中用 UITextView 替换 UILabel 后的布局问题

[英]Layout problems after replacing UILabel with UITextView in a UITableViewCell

作为我正在构建的应用程序的一部分,我拥有基本的聊天功能。 它基本上是一个 UITable 视图,其中 UITableViewCell 仅包含一个 UILabel(聊天消息文本)和一个 UIView(用作围绕文本的语音气泡。这是代码:

class ChatMessageViewCellController: UITableViewCell {

    var ChatMessageText = UILabel()
    var ChatBubble = UIView()
    var leadingConstraint: NSLayoutConstraint!
    var trailingConstraint: NSLayoutConstraint!
    var isIncoming: Bool! {
        didSet {
            if self.isIncoming {
                self.ChatBubble.backgroundColor = UIColor(named: "customGrey")
                self.leadingConstraint.isActive = true
                self.trailingConstraint.isActive = false
            } else {
                self.ChatBubble.backgroundColor = UIColor(named: "customGreen")
                self.leadingConstraint.isActive = false
                self.trailingConstraint.isActive = true
            }
        }
    }



    override func awakeFromNib() {
        super.awakeFromNib()

        addSubview(ChatBubble)
        addSubview(ChatMessageText)

        self.ChatBubble.translatesAutoresizingMaskIntoConstraints = false
        self.ChatMessageText.translatesAutoresizingMaskIntoConstraints = false

        self.ChatBubble.backgroundColor = UIColor(named: "customGreen")
        self.ChatBubble.layer.cornerRadius = 10
        self.ChatMessageText.numberOfLines = 0
        self.ChatMessageText.textColor = .white
        self.ChatMessageText.font = UIFont.systemFont(ofSize: 15, weight: UIFont.Weight.light)

        let constraints = [
            self.ChatMessageText.topAnchor.constraint(equalTo: topAnchor, constant: 16),
            self.ChatMessageText.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -32),
            self.ChatMessageText.widthAnchor.constraint(lessThanOrEqualToConstant: 220),
            self.ChatBubble.topAnchor.constraint(equalTo: ChatMessageText.topAnchor, constant: -16),
            self.ChatBubble.trailingAnchor.constraint(equalTo: ChatMessageText.trailingAnchor, constant: 16),
            self.ChatBubble.bottomAnchor.constraint(equalTo: ChatMessageText.bottomAnchor, constant: 16),
            self.ChatBubble.leadingAnchor.constraint(equalTo: ChatMessageText.leadingAnchor, constant: -16),
        ]

        NSLayoutConstraint.activate(constraints)

        self.leadingConstraint = self.ChatMessageText.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 32)
        self.trailingConstraint = self.ChatMessageText.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -32)
    }

我的问题是这样的:我不是用标准字符串来提供 UILabel,而是用 NSAttributedStrings,因为我想在那里获得一些可点击的链接和用户可选择的部分文本。 所以我被告知使用 UITextView 而不是 UILabel。 因此,我进行了以下 2 处更改:

  1. var ChatMessageText = UILabel()更改为var ChatMessageText = UITextView()
  2. 删除self.ChatMessageText.numberOfLines = 0因为 UITextView 没有numberOfLines成员

Xcode 没有抱怨,应用程序编译并运行,但它完全弄乱了我的布局,我就是不知道为什么。 UILabel 的所有约束也应该适用于 UITextView - 至少我是这么认为的。 但这是屏幕的样子。

在此处输入图片说明

我究竟做错了什么? 我需要添加/更改约束吗?

默认情况下, UITextView已启用滚动。

虽然这看起来很明显,但它允许用户输入比框架更多的文本行,并且用户可以上下滚动文本。

为了实现这一点, UIKit必须知道文本视图的框架。 如果框架没有设置, UIKit就无法知道要显示多少行,或者视图应该有多宽。 所以除非我们给文本视图提供了完整的约束集,否则自动布局会给它一个.zero的大小。 即使给定宽度(或最大宽度)约束,自动布局仍然不知道我们想要显示多少可滚动的文本行

在文本视图上设置.isScrollEnabled = false改变所有这些。

现在,如果我们只限制文本视图的位置宽度UIKit将根据.text属性的内容大小计算高度。

这很容易证明。 我们将创建两个文本视图,给它们每个顶部、前导和最大宽度(lessThanOrEqualTo)约束,以及相同的文本......但在其中一个上设置.isScrollEnabled = false

class TextViewTestViewController: UIViewController {

    let nonScrollingTextView = UITextView()
    let scrollingTextView = UITextView()

    override func viewDidLoad() {

        super.viewDidLoad()

        let s = "This is a test string to demonstrate UITextView size behavior."

        [nonScrollingTextView, scrollingTextView].forEach {
            tv in
            tv.translatesAutoresizingMaskIntoConstraints = false
            tv.font = UIFont.systemFont(ofSize: 17.0)
            tv.text = s
            view.addSubview(tv)
        }

        let g = view.safeAreaLayoutGuide

        NSLayoutConstraint.activate([

            nonScrollingTextView.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
            nonScrollingTextView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
            nonScrollingTextView.widthAnchor.constraint(lessThanOrEqualToConstant: 300.0),

            scrollingTextView.topAnchor.constraint(equalTo: nonScrollingTextView.bottomAnchor, constant: 40.0),
            scrollingTextView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
            scrollingTextView.widthAnchor.constraint(lessThanOrEqualToConstant: 300.0),

        ])

        // disable scrolling on the "top" text view
        nonScrollingTextView.isScrollEnabled = false

        // top text view is cyan
        nonScrollingTextView.backgroundColor = .cyan

        // bottom text view is green (although we won't see it)
        scrollingTextView.backgroundColor = .green

    }

}

结果:

在此处输入图片说明

我们添加了两个文本视图,但只禁用了“顶部”一个(青色背景)的滚动。 我们甚至看不到第二个(绿色背景),因为自动布局给它的高度为零。

值得注意的是...如果文本视图禁用了滚动启用了编辑,它会随着用户添加/删除文本而自动增长/缩小。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM