【问题标题】:Make UITextView height dynamic, issue with constraint multiplier使 UITextView 高度动态,约束乘数问题
【发布时间】:2019-02-18 18:29:19
【问题描述】:

我有一个包含五个单元格的 UICollectionView。在那里,我有一个 UIImageView、两个 UILabel 和一个 UITextView。我想根据它包含的文本更改 textview 的高度,所以之后我可以根据 UITextView 的高度和它们上方的标签来设置整个单元格的高度。让我演示一下with a screenshot

所以,如您所知,红色背景显示 UITextView 的高度不正确。我这样设置 UITextView:

    let commentTextView: UITextView = {

    let textView = UITextView()
    textView.translatesAutoresizingMaskIntoConstraints = false
    textView.text = "This is just some text to act as a description"
    textView.textContainerInset = UIEdgeInsets(top: 0, left: -4, bottom: 0, right: 0)
    textView.font = UIFont.systemFont(ofSize: 16.0)
    textView.textColor = UIColor.darkGray
    textView.isEditable = false
    textView.isSelectable = false
    textView.backgroundColor = UIColor.red

    textView.frame.size.width = (UIScreen.main.bounds.width - 16 - 16 - 60 - 8)

    let numberOfLines = (textView.contentSize.height / textView.font!.lineHeight)
    var textViewHeight = (textView.font?.lineHeight)! * floor(numberOfLines)

    textView.frame.size.height = textViewHeight

    return textView

}()

我认为这不会造成错误的高度。我认为问题可以在我的约束中找到,它有一个高度约束(如果我删除它, UITextView 就会消失)。如果我更改乘数(当前设置为 0.3),我有不同的高度,但我希望这是动态的。所以在我看来,我需要在乘数内设置一个动态变量,但我不知道如何组合它。有人可以帮忙吗?这是我的限制:

        // top constraints
    addConstraints([NSLayoutConstraint(item: commentTextView, attribute: .top, relatedBy: .equal, toItem: workoutLabel, attribute: .bottom, multiplier: 1, constant: 2)])

    // left constraint
    addConstraints([NSLayoutConstraint(item: commentTextView, attribute: .left, relatedBy: .equal, toItem: profilePictureImageView, attribute: .right, multiplier: 1, constant: 16)])

    // right constraint
    addConstraints([NSLayoutConstraint(item: commentTextView, attribute: .right, relatedBy: .equal, toItem: self.commentTextView.superview, attribute: .right, multiplier: 1, constant: -16)])

    // height constraint
    addConstraints([NSLayoutConstraint(item: commentTextView, attribute: .height, relatedBy: .equal, toItem: self, attribute: .height, multiplier: 0.3, constant: 1)])

干杯!

【问题讨论】:

    标签: ios swift xcode constraints uitextview


    【解决方案1】:

    您可以考虑另一种方式来处理dynamic heightUITextView。众所周知intrinsic content size。您可以使用该技术实现动态高度。

    【讨论】:

    • 明天早上我会先看看这个。这是实现这一目标的更好/最佳实践方式吗?这在单元格内使用 TextView 是完全可能的(因为在您引用的示例中,他们在 viewDidLoad 中调用它)
    • intrinsic content size 决定UITextViewUILabel 的高度(或宽度)。它适用于AutoLayout。在UILabel中,当它的文本改变时,它的内在内容大小也会改变。
    • 该帖子对topleftright 进行了限制。但它不限制height。它的高度由intrinsic content size 动态决定,它基于text 长度。
    【解决方案2】:

    最初回答here

    不要更改或给您的UITextView 提供任何框架。只需给它leadingtrailingtopbottom 约束。然后,如果您的单元格能够自动调整大小,那么您无需为文本视图计算任何内容。

    使用自动布局来动态调整单元格大小时,您实际上不需要实现sizeThatFits(...)。如果约束设置正确,那么您只需要禁用UITextView 的滚动即可。

    来自代码:

    yourTextView.scrollEnabled = false
    

    来自 IB:

    选择您的文本视图并打开 属性检查器,然后


    现在,如果您在将单元格设置为动态大小时遇到​​问题,请查看this answer

    【讨论】:

    • 对于迟到的回复,我深表歉意。我已经想出了如何使用这个解决方案,现在 textview 确实适应了其中的文本(我可以通过设置背景颜色来看到这一点)。但是,正如您所建议的,我现在面临如何动态调整集合视图单元大小的困难。您所指的帖子是关于 TableView 的,但我似乎无法弄清楚如何使用它(rowHeight、estimatedRowHeight 是否只能在 Table Views 中访问?)您是否有机会通过 Collection View Cell 帮助我解决这个问题?
    • 好吧,集合视图单元格的动态大小超出了这个问题的范围。您应该注意这一点,或者根据您的需要提出一个单独的问题。我还看到您自己发布了答案。但是UITableViewCellUICollectionViewCell 具有动态大小的基本思想应该是相同的,即一组从左到右和从上到下扩展的完整约束 .
    • 因此,集合视图单元格需要一些额外的努力。我建议你仔细阅读this post 并弄清楚。注意那里的第一个,第二个和第三个答案中的每一个。这是一项乏味的工作,但最终的结果值得我希望的努力。
    • 在我看来,我很有野心去尝试实现它,因为我对 Swift 和 Xcode 还很陌生,而且这个问题有点复杂。话虽如此,您的参考资料非常有用,我今天将尝试弄清楚如何正确实施它。我将从一个新项目开始并尝试其中的所有内容,然后一旦我开始工作,我就可以继续我当前的项目。再次感谢您的参考 - 希望我能坚持下去。
    • 我现在正在尝试设置 layout.estimatedItemSize (只是设置为 1, 1 - 我猜这并不重要)然后我将我的 collectionView 上的 topAnchor、leftAnchor、rightAnchor 和 bottomAnchor 约束设置为self.view.topAnchor 等我的标签也有限制(例如“V:|-16-[v0]-2-[v1]-16-|”),因此它跨越整个宽度。它似乎是动态的,但是,当我运行应用程序时,它跨越了“需要”的宽度,所以我现在有三个相邻的单元格。我可以将宽度设置为屏幕宽度吗?我尝试在 sizeForItemAt 方法中这样做,但这根本不起作用。
    【解决方案3】:

    如昨天所述,我让 textview 根据@nayem 的回答调整其大小 - 谢谢!

    但是,我在使单元格高度动态化时遇到了另一个问题。我研究了不同的解决方案,没有任何工作,除非我自己计算高度并将其设置为要使用的高度。这适用于模拟器中的所有设备,只是想知道这是否是正确的方法。代码如下,上下左右分别设置约束。

        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    
        let dummyText = "Just a long text to see what will happen to the cell. Will it adapt or not? Let's find out!"
    
        let rectWidth = view.frame.width - 32 - 60 - 16
    
        let rect = NSString(string: dummyText).boundingRect(with:CGSize(width: rectWidth, height: 1000), options: NSStringDrawingOptions.usesFontLeading.union(NSStringDrawingOptions.usesLineFragmentOrigin), attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 16)], context: nil)
    
        let variableHeight = 16 + 20 + 2 + 20 + 2 + 16 + rect.height
    
        return CGSize(width: view.frame.width, height: variableHeight)
    
    }
    

    这是最好的方法吗?这会在以后引起问题吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-06
      • 2017-11-24
      • 1970-01-01
      • 2011-06-20
      • 2019-05-07
      • 2023-03-17
      • 1970-01-01
      • 2013-11-30
      相关资源
      最近更新 更多