【问题标题】:Why UITableViewCell shrinks contentView?为什么 UITableViewCell 会缩小 contentView?
【发布时间】:2019-01-23 09:03:02
【问题描述】:

这是我想做的UITableView

为了实现这一点,我将cell的contentView分成了三个部分。

1 - fromView:包含开始时间和班级类型。高度将是 contentView

的 30%

2 - infoView:包含时钟图像、班级名称和教授姓名。高度将是contentView 的 40%。

3 - toView:包含结束时间和位置。高度将是剩余的空间(30%)。

首先,在详细介绍之前,我决定只展示这个容器。为了理解一个问题,我画了它们(分别是绿色、红色、蓝色)。

在将它们添加到contentView 之后,以下是我对这些容器的约束:

   fromView.easy.layout(Top(), Left(), Right(), Height(*0.3).like(contentView))

    infoView.easy.layout(Top().to(fromView), Left(), Right(), Height(*0.4).like(contentView))

    toView.easy.layout(Top().to(infoView), Left(), Right(), Bottom())

似乎一切都是正确的。启动后,我以为我会看到它们,但发生了这样的事情:

我认为单元格不知道它需要多大,所以我决定实现以下功能:

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 150
}

在此之后,UITableView 比以前更正确地显示了容器。但是,我计划在该容器中添加一些UILabels 和其他views(看第一张图片)。换句话说,我不知道一个单元格需要有多大。它需要是一种动态的。无论如何,我尝试将这些标签添加到容器中,也许在那之后,一个单元格会计算出高度。这是我的做法:

func setupViews() {

    fromView.addSubviews(fromTime, classType)

    toView.addSubviews(toTime, room)

    infoView.addSubviews(clockImage, teacherName, subjectName)

    contentView.addSubviews(toView, fromView, infoView)



}

func setupConstraints() {

    fromView.easy.layout(Top(), Left(), Right(), Height(*0.3).like(contentView))

    infoView.easy.layout(Top().to(fromView), Left(), Right(), Height(*0.4).like(contentView))

    toView.easy.layout(Top().to(infoView), Left(), Right(), Bottom())

    fromTime.easy.layout(CenterY(), Left(8))

    fromTime.setContentHuggingPriority(.required, for: .horizontal)

    fromTime.setContentCompressionResistancePriority(.required, for: .horizontal)

    classType.easy.layout(CenterY(), Left(8).to(fromTime))

    clockImage.easy.layout(CenterY(), Left(16), Width(24), Height(24))

    subjectName.easy.layout(CenterY(-8), Left().to(classType, .left), Right())

    teacherName.easy.layout(Top(8).to(subjectName), Left().to(subjectName, .left), Right())


    toTime.easy.layout(CenterY(), Left(8))

    toTime.setContentHuggingPriority(.required, for: .horizontal)

    toTime.setContentCompressionResistancePriority(.required, for: .horizontal)


    room.easy.layout(CenterY(), Left(8).to(toTime))

}

但不管怎样,问题又出现了:

我认为,问题是我根据contentView 的高度给容器指定高度,但contentView 不知道它的高度。但我也不知道它需要有什么高度,因为它需要根据标签的大小而定。那么,如何解决这个问题呢?

【问题讨论】:

    标签: ios uitableview autolayout


    【解决方案1】:

    不要为容器设置高度。您必须确保单元格的顶部和底部通过约束连接。我的建议是摆脱容器,直接将所有标签和图像添加到单元格中,然后像这样创建约束。

    然后设置tableView.rowHeight = UITableView.automaticDimension,或者从tableView(_:heightForRowAt:)返回UITableView.automaticDimension

    【讨论】:

    • 感谢您的回答。删除容器是个好主意。但是,请查看显示“800”的标签。它需要低于professor's name,并且它需要与显示12:00 的timeLabel 一起水平放置。这就是我使用容器的原因。我认为容器可以帮助我解决这个问题。如何仅通过使用约束来实现?在图片中,您只显示了垂直约束。
    • 您可以使用约束使标签垂直居中。例如,您可以添加一个约束来对齐12:00800 标签的基线。您还可以添加约束以垂直对齐11:30practice 标签的中心(Y 中心)。等等。
    • 我决定使用你的方法。但是,我确信 AutoLayout 可以让我达到这样的效果。查看800 标签和12:00 标签。它们需要在一条水平线上。换句话说,我将800 设置为像CenterY().to(12:00) 这样的约束。我们在垂直轴上设置约束,但 AutoLayout 也要求我们在水平轴上。为此,我将800 设置为标记Left().to(professorName, .left) 之类的约束。但是,我们也没有考虑一个细节。现在,800 在垂直轴上取决于12:00,但professor's name 可以很长。所以如果是,它只是重叠800
    • 您可以 100% 实现此布局而不会重叠。您应该将 800 固定在教授姓名的底部,然后将 12:00 与 800 对齐。这样,800 将尽可能地下降,为教授姓名腾出空间,而 12:00 将始终在它旁边。
    • 最后一个问题是关于 UIImageView(clock's image)。它需要在单元格中垂直居中。这个要求打破了你的想法,因为你写道 12:00 需要与 800 对齐,但它也不必与时钟图像重叠。那么,时钟图像需要具备哪些约束条件?
    【解决方案2】:

    尝试对单元格内的主视图进行高度限制。

    【讨论】:

    • 感谢您的回答。你的意思是,给 contentView 提供高度限制?但是,正如我在问题中所说,我不知道它的确切高度。它需要依赖于单元格的内容。
    【解决方案3】:

    看起来您想要的是根据内容的自动布局计算出的动态高度。更新代表以返回 UITableViewAutomaticDimensionheightForRowAt 和一些好的估计,例如,150 的 estimatedHeightForRowAt

    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return 150
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }
    

    然后您可以使用自动布局设置内容的大小,表格会为您动态计算单元格的高度。

    估计高度用于滚动目的 - 良好的估计将为您提供良好的滚动体验(动态高度仅在显示单元格时计算,因此对于尚未显示的单元格,tableView 将在滚动时使用估计) .

    【讨论】:

    • 我像这样向contentView 添加了约束:contentView.easy.layout(Top(), Left(), Right(), Height(150)) 我还使用上面的代码来添加估计的高度。但是,您的建议真的能保证单元格将显示其中的所有数据吗?我的意思是,它只有关于估计高度的信息,你的意思是如果标签的内在内容大小会更大,单元格会自己计算高度?
    • @abay 我认为您不需要为contentView 明确设置约束 - 如果它的内容有明确的约束来告诉单元格内容与contentView 的关系就足够了。例如,您将view1 作为contentView 的子视图,然后将其顶部、左侧、右侧和底部锚点分别约束到contentView 的顶部、左侧、右侧和底部锚点。这会告诉单元格,contentView 应该和view1 一样大,反之亦然。现在,如果您添加一个约束,说 view1.height 是 100,那将告诉单元格 contentView.height
    • 也是 100 点高。现在,如果您设置自动单元格高度,这将在单元格显示时使用。如果您使用显式高度,例如 150,这将导致单元格高度和约束之间发生冲突。
    猜你喜欢
    • 1970-01-01
    • 2011-02-06
    • 1970-01-01
    • 2011-08-12
    • 2016-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-13
    相关资源
    最近更新 更多