动态 UITableView 高度
Posted
技术标签:
【中文标题】动态 UITableView 高度【英文标题】:Dynamic UITableView height 【发布时间】:2015-12-23 06:00:54 【问题描述】:我想设置 UITableView 以匹配表格视图中所有内容的高度。
这是我的故事板
这个问题是顶部和底部的 ImageView 在屏幕上总是静态的。
表格视图中假设有 10 个项目,但由于屏幕尺寸限制,仅显示 7 个。我想在用户能够看到底部的 ImageView 之前显示所有 10 个。 (顺便说一句,所有 3 个视图,即图像视图和表格视图都在 uiscrollview 中)
理想
我必须处理的其他一些限制是表视图中的项目数是动态的,这意味着它可以是任何数量,通常小于 10,我稍后将从 api 检索。并且单元格高度也是动态的,具体取决于内容。
我才刚刚开始写一些简单的代码
class ExampleViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
@IBOutlet weak var tableView: UITableView!
var items: [String] = [
"Item 01", "Item 02", "Item 03", "Item 04", "Item 05",
"Item 06", "Item 07", "Item 08", "Item 09", "Item 10"]
override func viewDidLoad()
super.viewDidLoad()
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return self.items.count;
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
let cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
cell.textLabel?.text = self.items[indexPath.row]
return cell
【问题讨论】:
您是否尝试过 self.items.count*row_height 这将根据内容给出高度,但您也需要编写其他条件来检查屏幕高度 为什么不在tableview的页眉和页脚中添加顶部和底部的imageView? 页眉和页脚并没有真正起作用,因为顶部和底部的 imageView 只是视图的代表。实际上,它是一个包含更多组件、标签、图像和约束的视图。 尝试从底部和顶部布局指南的底部视图和顶部视图添加约束,并固定它们的高度,并将表格视图约束到它们各自的邻居,即顶部和底部。 你的意思是顶部和底部图像在视图上是静态的吗?因为如果它们在 屏幕 上是静态的,那么tableView
必须始终保持不变。
【参考方案1】:
将你的 UITableView 子类化以覆盖 intrinsicContentSize 为其 contentSize,如下所示:
override var intrinsicContentSize: CGSize
return contentSize
然后为您的表格使用自动行高,因此您的 exampleViewController 的 viewDidLoad 将具有:
tableView.estimatedRowHeight = 44
还有 UITableViewDelegate 函数:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
return UITableViewAutomaticDimension
当您从 API 接收数据并重新加载表时,只需调用:
tableView.invalidateIntrinsicContentSize()
这将告诉您的表格将其自身调整为与其内容相同的大小(因为覆盖),并根据需要移动您的底部图像。
如果您的故事板抛出一个错误,指出您的 UIScrollView 的高度不明确,因为 UITableView 没有高度限制,请选择您的 UITableView 并在 Size Inspector 中为其指定占位符固有大小。
【讨论】:
太棒了!我真的不敢相信这不是 ios 的一部分。这不是一个非常常见的用例吗? 感谢@MartinMassera!我同意,我花了一段时间才弄清楚如何最好地做到这一点,但我现在已经多次使用这种方法了。我不想子类化,但我认为它仍然是最干净的,而不是手动更新约束。 太棒了!最佳解决方案【参考方案2】:使用子类化技术的答案不完整。您还应该像这样覆盖layoutSubviews()
。
public class DynamicSizeTableView: UITableView
override public func layoutSubviews()
super.layoutSubviews()
if bounds.size != intrinsicContentSize
invalidateIntrinsicContentSize()
override public var intrinsicContentSize: CGSize
return contentSize
【讨论】:
感谢您的帮助,但我想对此进行限制。如果 tableview 大小大于安全区域大小,那么我想启用滚动并且此效果停止。有可能吗?【参考方案3】:更新 Swift 4 这段代码运行良好
self.scrollView.layoutIfNeeded()
self.view.layoutIfNeeded()
self.tableViewHeightConstraint.constant = CGFloat(self.tableView.contentSize.height)
【讨论】:
这个答案没有意义。【参考方案4】:您需要将 IBOutlet 设置为设置 tableView
高度的NSLayoutConstraint
(首先您需要创建具有任何值的高度约束,没关系),然后 ctrl 将其拖到您的类文件中
然后在您的viewWillAppear
中,您必须计算tableView
的高度并设置它。像这样:
var tableViewHeight:CGFloat = 0;
for (var i = tableView(self.tableView , numberOfRowsInSection: 0) - 1; i>0; i-=1 )
tableViewHeight = height + tableView(self.tableView, heightForRowAtIndexPath: NSIndexPath(forRow: i, inSection: 0) )
tableViewHeightLayout.constant = tableViewHeight
差不多就是这样。这会给你的 scrollView 内容大小,并且不应该引发任何警告。
【讨论】:
【参考方案5】:这是我在生产应用中使用的:
斯威夫特 5,2021 年
import UIKit
class DynamicTableView: UITableView
/// Will assign automatic dimension to the rowHeight variable
/// Will asign the value of this variable to estimated row height.
var dynamicRowHeight: CGFloat = UITableView.automaticDimension
didSet
rowHeight = UITableView.automaticDimension
estimatedRowHeight = dynamicRowHeight
public override var intrinsicContentSize: CGSize contentSize
public override func layoutSubviews()
super.layoutSubviews()
if !bounds.size.equalTo(intrinsicContentSize)
invalidateIntrinsicContentSize()
【讨论】:
【参考方案6】:您可能必须实现表格视图的内在内容大小。请检查此answer 看看是否有帮助。
我记得有这个问题,甚至创建了一个自定义的UITableView
子类。
#import "IntrinsicTableView.h"
@implementation IntrinsicTableView
#pragma mark - UIView
- (CGSize)intrinsicContentSize
return CGSizeMake(UIViewNoIntrinsicMetric, self.contentSize.height);
#pragma mark - UITableView
- (void)endUpdates
[super endUpdates];
[self invalidateIntrinsicContentSize];
- (void)reloadData
[super reloadData];
[self invalidateIntrinsicContentSize];
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
[super reloadRowsAtIndexPaths:indexPaths withRowAnimation:animation];
[self invalidateIntrinsicContentSize];
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation
[super reloadSections:sections withRowAnimation:animation];
[self invalidateIntrinsicContentSize];
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
[super insertRowsAtIndexPaths:indexPaths withRowAnimation:animation];
[self invalidateIntrinsicContentSize];
- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation
[super insertSections:sections withRowAnimation:animation];
[self invalidateIntrinsicContentSize];
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
[super deleteRowsAtIndexPaths:indexPaths withRowAnimation:animation];
[self invalidateIntrinsicContentSize];
- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation
[super deleteSections:sections withRowAnimation:animation];
[self invalidateIntrinsicContentSize];
@end
【讨论】:
【参考方案7】:Swift 5 更新。添加 maxHeight 以便您可以指定您希望 tableView 的高度
class SelfSizingTableView: UITableView
var maxHeight = CGFloat.infinity
override var contentSize: CGSize
didSet
invalidateIntrinsicContentSize()
setNeedsLayout()
override var intrinsicContentSize: CGSize
let height = min(maxHeight, contentSize.height)
return CGSize(width: contentSize.width, height: height)
【讨论】:
i.stack.imgur.com/YcdkR.png .... 我该怎么做...并且这种效果停止。有可能吗? @Maulikshah 您可以尝试将view
高度减去safe area
高度并将其设置为tableView
maxHeight。 tableView
将在达到其 maxHeight 时变为可滚动的。【参考方案8】:
在这种情况下,不要将底部单元格设为静态,使其成为表格视图的一部分,并使用表格视图委托方法将底部图像插入最后一行 - insertRowAtIndexPath
【讨论】:
【参考方案9】:在这种情况下,将底部的 imageView(red) 添加到表格页脚视图中。
要在UITableView
中添加页脚视图,您可以使用:
tableViewObj.tableFooterView = footerViewObj;
【讨论】:
【参考方案10】:也试试这个
in ViewDidLoad
self.table.estimatedRowHeight = 44.0 ;
self.table.rowHeight = UITableViewAutomaticDimension;
索引路径处的行高
-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
return UITableViewAutomaticDimension;
【讨论】:
【参考方案11】:这里很简单。
第一步:为表格视图设置高度限制
第 2 步:控制拖动约束
第 3 步:在返回行数之前。在 numberOfRowsInSection 方法中,做
tableViewHeightConstraint.constant = tableView.rowHeight * CGFloat(someArray.count)
当然你可以通过编程方式编辑高度锚点,这里的逻辑是根据单元格高度和单元格数量来调整表格视图高度。
【讨论】:
【参考方案12】:基于解决方案@nikans,用 Xamarin 编写
[Register(nameof(DynamicSizeTableView)), DesignTimeVisible(true)]
public class DynamicSizeTableView : UITableView
public override void LayoutSubviews()
base.LayoutSubviews();
if (Bounds.Size != IntrinsicContentSize)
InvalidateIntrinsicContentSize();
public override CGSize IntrinsicContentSize => ContentSize;
public DynamicSizeTableView(CGRect frame) : base(frame)
public DynamicSizeTableView(IntPtr handle) : base(handle)
【讨论】:
【参考方案13】:基于@rr1g0的解决方案
在 2020 年针对 Swift 5 进行了更新,并且也可以与带有部分的 TableViews 一起使用。
为 tableView 创建高度约束并为其创建一个出口。在 viewDidLayoutSubviews() 中使用以下代码:
var tableViewHeight: CGFloat = 0
for section in 0..<tableView.numberOfSections
for row in 0..<tableView.numberOfRows(inSection: section)
tableViewHeight += tableView(tableView, heightForRowAt: IndexPath(row: row, section: section))
tableViewHeightConstraint.constant = tableViewHeight
【讨论】:
不能调用非函数类型'UITableView?'的值 @zramled 你应该做错了什么。您的 tableView 属性是否命名为 tableView?你的网点设置正确吗? 当然。错误从这里开始' tableView(tableView, heightForRowAt: IndexPath( .....以上是关于动态 UITableView 高度的主要内容,如果未能解决你的问题,请参考以下文章
实现 UITableView (Slave) 的动态高度,它作为子视图添加到另一个具有动态高度的 UITableView (Master) 的自定义单元格中