【问题标题】:Layout problems after replacing UILabel with UITextView in a UITableViewCell在 UITableViewCell 中用 UITextView 替换 UILabel 后的布局问题
【发布时间】:2020-03-27 16:36:28
【问题描述】:

作为我正在构建的应用程序的一部分,我拥有基本的聊天功能。它基本上是一个 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)
    }

我的问题是: 我不是用标准字符串而是用 NSAttributedStrings 为 UILabel 提供,因为我想让其中的一些链接可点击,部分文本可供用户选择。 所以有人告诉我使用 UITextView 而不是 UILabel。因此,我进行了以下 2 项更改:

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

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

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

【问题讨论】:

  • 您是否在您的UITextView 上设置了.isScrollEnabled = false
  • @DonMag:天哪——这么小的东西却产生了这么大的影响。有点美。那解决了它。谢谢你的帮助!!!
  • 我添加了我的评论(连同解释和示例)作为答案,以使可能遇到此问题的其他用户受益。

标签: ios uitableview uitextview


【解决方案1】:

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

虽然这看起来很明显,但它允许用户输入的文本行数超过了框架的容量,并且用户可以上下滚动文本。

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

在文本视图上设置.isScrollEnabled = false 会改变这一切。

现在,如果我们只限制文本视图的 positionwidthUIKit 将根据 .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

    }

}

结果:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多