如何从底部向上填充UITableView?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何从底部向上填充UITableView?相关的知识,希望对你有一定的参考价值。
是否可以颠倒tableView的顺序。我已经搜索了很多解决方案,但所有结果都不是我想要实现的解决方案。他们都建议使用scrollToRowAtIndexPath
滚动到表的最后一个位置并反向填充数据。但是,如果表内容是动态的,并且在某些情况下并非所有单元都有数据,则这不起作用。例如,在普通的tableView中,顺序是:
标签1
标签2
标签3
空
空
滚动方向 在 该
期望的结果是: 滚动方向 ^ ^
空
空
空
标签3
标签2
标签1
在这个例子中,如果我使用scrollToRowAtIndexPath
的建议方法并使用对象数组的长度,我只会从顶部获得第三个单元格。并最终得到这样的东西:
意外结果:
标签3
标签2
标签1
空
空
滚动方向 在 该
任何帮助都会非常感谢你。
要从底部填充表,请使用以下命令:
- (void)updateTableContentInset {
NSInteger numRows = [self tableView:self.tableView numberOfRowsInSection:0];
CGFloat contentInsetTop = self.tableView.bounds.size.height;
for (NSInteger i = 0; i < numRows; i++) {
contentInsetTop -= [self tableView:self.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
if (contentInsetTop <= 0) {
contentInsetTop = 0;
break;
}
}
self.tableView.contentInset = UIEdgeInsetsMake(contentInsetTop, 0, 0, 0);
}
要反转元素的顺序,请使用:
dataSourceArray = dataSourceArray.reverseObjectEnumerator.allObjects;
Swift 4.2 / 5版本:
func updateTableContentInset() {
let numRows = tableView(self.tableView, numberOfRowsInSection: 0)
var contentInsetTop = self.tableView.bounds.size.height
for i in 0..<numRows {
let rowRect = self.tableView.rectForRow(at: IndexPath(item: i, section: 0))
contentInsetTop -= rowRect.size.height
if contentInsetTop <= 0 {
contentInsetTop = 0
}
}
self.tableView.contentInset = UIEdgeInsets(top: contentInsetTop,left: 0,bottom: 0,right: 0)
}
Swift 3 / 4.0版非常相似,只需用它来创建tableView
contentInset
:
self.tableView.contentInset = UIEdgeInsetsMake(contentInsetTop, 0, 0, 0)
如果你有一个对象数组你在cellForRowAtIndexPath:
中显示,让我们说dataArray
你可以反转它,或者在cellForRowAtIndexPath:
你可以做类似的事情:
NSString *yourObject = dataArray[[dataArray count] - 1 - indexPath.row];
cell.textLabel.text = yourObject
我假设你在dataArray中保留字符串。
首先反转uitableview
tableView.transform = CGAffineTransformMakeScale (1,-1);
然后在细胞中反转细胞。
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
...
cell.contentView.transform = CGAffineTransformMakeScale (1,-1);
以下是KlimczakM解决方案的精确解决方案,该解决方案适用于自动覆盖的tableview单元(以及固定的单元)。此解决方案还适用于节,节标题和节页脚。
Swift 3.0:
func updateTableContentInset(forTableView tv: UITableView) {
let numSections = tv.numberOfSections
var contentInsetTop = tv.bounds.size.height -
(self.navigationBar?.frame.size.height ?? 0)
for section in 0..<numSections {
let numRows = tv.numberOfRows(inSection: section)
let sectionHeaderHeight = tv.rectForHeader(inSection: section).size.height
let sectionFooterHeight = tv.rectForFooter(inSection: section).size.height
contentInsetTop -= sectionHeaderHeight + sectionFooterHeight
for i in 0..<numRows {
let rowHeight = tv.rectForRow(at: IndexPath(item: i, section: section)).size.height
contentInsetTop -= rowHeight
if contentInsetTop <= 0 {
contentInsetTop = 0
break
}
}
// Break outer loop as well if contentInsetTop == 0
if contentInsetTop == 0 {
break
}
}
tv.contentInset = UIEdgeInsetsMake(contentInsetTop, 0, 0, 0)
}
注意:
以上代码未经测试但应该有效。只要确保你应对任何导航栏或tabbar的高度,你会没事的。在上面的代码中我只对导航栏执行此操作!
不要费心自己编写代码。为什么不使用ReverseExtension。它非常简单,将为您提供所有必需的结果。请关注此网址https://github.com/marty-suzuki/ReverseExtension
注意:每当需要添加新单元格时,请在数据源数组的第0个索引处插入新添加的模型,因此新单元格应添加到底部。否则它会将单元格添加到顶部,你会再次感到困惑。
简单的方法是使用像UILabel多行+自动布局。 - > UITableView应根据其内容(又称内在布局)调整大小。创建您的tableview并设置以下基类:
class IntrinsicTableView: UITableView {
override var contentSize:CGSize {
didSet {
self.invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
self.layoutIfNeeded()
return CGSize(width: UIViewNoIntrinsicMetric, height: contentSize.height)
}
}
现在将tableview引脚的左右和底部布局约束设置为父视图。最重要的是顶部布局约束应设置为大于或等于0,此条件保证表不会高于其父视图。
我在cellForRowAt方法中做了:
let reverseIndex = myArray.count-indexPath.row-1
let currCellData = myArray.object(at: reverseIndex)
然后你继续使用currCellData
Swift 3.01 - 其他解决方案可以是,旋转和翻转tableView。
self.tableView.transform = CGAffineTransform.init(rotationAngle: (-(CGFloat)(M_PI)))
self.tableView.transform = CGAffineTransform.init(translationX: -view.frame.width, y: view.frame.height)
UITableView anchor rows to bottom
Swift 4.0和4.2版本
首先在viewDidLoad中反转UITableView
override func viewDidLoad() {
super.viewDidLoad()
tableView.transform = CGAffineTransform(scaleX: 1, y: -1)
}
然后在cellForRowAt中反转单元格。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "MyTableViewCell", for: indexPath) as? MyTableViewCell else { fatalError() }
cell.contentView.transform = CGAffineTransform(scaleX: 1, y: -1)
return cell
}
此解决方案使用KVO在内容大小更改时调整内容插入。当滚动到顶部时它也会考虑内容插入,因为只需滚动到CGPointZero
就会滚动到内容的顶部而不是滚动到表格的顶部。
-(void)startObservingContentSizeChanges
{
[self.tableView addObserver:self forKeyPath:kKeyPathContentSize options:0 context:nil];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if([keyPath isEqualToString:kKeyPathContentSize] && object == self.tableView)
{
// difference between content and table heights. +1 accounts for last row separator
CGFloat height = MAX(self.tableView.frame.size.height - self.tableView.contentSize.height, 0) + 1;
self.tableView.contentInset = UIEdgeInsetsMake(height, 0, 0, 0);
// "scroll" to top taking inset into account
[self.tableView setContentOffset:CGPointMake(0, -height) animated:NO];
}
}
以上是关于如何从底部向上填充UITableView?的主要内容,如果未能解决你的问题,请参考以下文章
如何将数据从 BottomSheetDialogFragment 返回到父片段
滚动 UITableView 时如何创建 NSLayoutConstraint