在 UITableViewCell 中用 UITextView 替换 UILabel 后的布局问题 [英] Layout problems after replacing UILabel with UITextView in a UITableViewCell

查看:28
本文介绍了在 UITableViewCell 中用 UITextView 替换 UILabel 后的布局问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've got basic chat functionality as part of an App I'm building. It is basically a UITable View where the UITableViewCell only contains a UILabel (the chat message text) and a UIView (serving as a speech bubble, surrounding the text. Here's the code:

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 项更改:

My problem is this: I'm not feeding the UILabel with standard strings but with NSAttributedStrings, as I'd like to get some of the links in there clickable and parts of the text selectable by the user. So I've been told to use a UITextView instead of the UILabel. I've thus made the following 2 changes:

  1. var ChatMessageText = UILabel()改为var ChatMessageText = UITextView()
  2. 确实删除了 self.ChatMessageText.numberOfLines = 0 因为 UITextView 没有 numberOfLines 成员
  1. Changed var ChatMessageText = UILabel()to var ChatMessageText = UITextView()
  2. Did remove self.ChatMessageText.numberOfLines = 0 as UITextView doesn't have a numberOfLines member

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

Xcode doesn't complain and the app compiles and runs but it completely messes with my layout and I just can't figure out why. All the constraints from the UILabel should also work for the UITextView - at least I thought so. But here's how the screen looks like.

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

What am I doing wrong? Do I need to add / alter constraints?

推荐答案

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

By default, a UITextView has scrolling enabled.

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

While this seems obvious, that allows the user to enter more lines of text than will fit in the frame, and the user can scroll the text up and down.

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

In order for this to happen, UIKit has to know the frame of the text view. If the frame is not set, UIKit has no way to know how many lines to display, or how wide the view should be. So unless we have given the text view a full set of constraints, auto-layout will give it a size of .zero. Even if given a width (or max width) constraint, auto-layout still doesn't know how many scrollable lines of text we want displayed.

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

Setting .isScrollEnabled = false on the text view changes all of that.

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

Now, if we only constrained the position and width of the text view, UIKit will calculate the height based on the content size of the .text property.

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

This can be easily demonstrated. We'll create two text views, give them each top, leading and max-width (lessThanOrEqualTo) constraints, and the same text... but set .isScrollEnabled = false on one of them:

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

    }

}

结果:

我们添加了两个文本视图,但仅在顶部"一个(青色背景)上禁用了滚动.我们甚至没有看到第二个(绿色背景),因为自动布局给它的高度为零.

We've added two text views, but only disabled scrolling on the "top" one (cyan background). We don't even see the second one (green background), because auto-layout gives it a height of Zero.

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

Worth noting... if the text view has scrolling disabled and has editing enabled, it will automatically grow / shrink as the user adds / deletes text.

这篇关于在 UITableViewCell 中用 UITextView 替换 UILabel 后的布局问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆