如何从底部向上填充UITableView?

时间:2015-01-23 08:36:59

标签: ios objective-c iphone uitableview ios8

是否可以颠倒tableView的顺序。我已经搜索了很多解决方案,但所有结果都不是我想要实现的解决方案。他们都建议使用scrollToRowAtIndexPath滚动到表的最后一个位置并反向填充数据。但是,如果表内容是动态的,并且在某些情况下并非所有单元都有数据,则这不起作用。例如,在普通的tableView中,订单是:


标签1

标签2

标签3

滚动方向
v
V


期望的结果将是:
滚动方向
^
^

标签3

标签2

标签1


在这个例子中,如果我使用scrollToRowAtIndexPath的建议方法并使用对象数组的长度,我只会从顶部获得第三个单元格。并最终得到这样的东西:


不必要的结果:

标签3

标签2

标签1

滚动方向
v
V


任何帮助都会非常感谢你。

11 个答案:

答案 0 :(得分:26)

要从底部填充表 ,请使用以下内容:

- (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 2.2 版本(已更新):

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.rectForRowAtIndexPath(NSIndexPath(forItem: i, inSection: 0))
        contentInsetTop -= rowRect.size.height
        if contentInsetTop <= 0 {
            contentInsetTop = 0
        }
    }
    self.tableView.contentInset = UIEdgeInsetsMake(contentInsetTop, 0, 0, 0)
}

Swift 3.0 + / 4.0 版本(已更新):

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 = UIEdgeInsetsMake(contentInsetTop, 0, 0, 0)
}

答案 1 :(得分:6)

第一个反向uitableview

    tableView.transform = CGAffineTransformMakeScale (1,-1);

然后在单元格中创建反向单元格。

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

    ...

    cell.contentView.transform = CGAffineTransformMakeScale (1,-1);

答案 2 :(得分:3)

这是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的高度,你会没事的。在上面的代码中,我只为导航栏执行此操作!

答案 3 :(得分:2)

最简单的方法是使用UILabel多行+自动布局。 -> UITableView应该基于其内容(即固有布局)调整其大小。 创建您的表视图并设置以下基类:

class IntrinsicTableView: UITableView {

override var contentSize:CGSize {
    didSet {
        self.invalidateIntrinsicContentSize()
    }
}

override var intrinsicContentSize: CGSize {
    self.layoutIfNeeded()
    return CGSize(width: UIViewNoIntrinsicMetric, height: contentSize.height)
}

}

现在将tableview的pin设置为其父视图的左右和底部布局约束。 最重要的是,顶部布局约束应设置为大于或等于0,此条件保证表的高度不会大于其父视图的高度。

答案 4 :(得分:1)

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

答案 5 :(得分:1)

不要费心自己编写代码。 为什么不使用ReverseExtension。它非常简单,将为您提供所有必需的结果。请关注此网址 https://github.com/marty-suzuki/ReverseExtension

注意:每当需要添加新单元格时,请在数据源阵列的第0个索引处插入新添加的模型,因此新单元格应在底部添加。否则它会将单元格添加到顶部,你会再次感到困惑。

答案 6 :(得分:0)

此解决方案使用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];

    }
}

答案 7 :(得分:0)

我在cellForRowAt方法中做了:

let reverseIndex = myArray.count-indexPath.row-1

let currCellData = myArray.object(at: reverseIndex) 

然后继续使用currCellData

答案 8 :(得分:0)

Swift 4.0和4.2版本

viewDidLoad中的第一个反向UITableView

import boto3

cluster_name = 'name_of_your_cluster'

client = boto3.client('emr')

clusters = client.list_clusters()
your_cluster = [i for i in clusters['Clusters'] if i['Name'] == cluster_name][0]
response = client.describe_cluster(ClusterId=your_cluster['Id'])

然后反转cellForRowAt中的单元格。

override func viewDidLoad() {
        super.viewDidLoad()
        tableView.transform = CGAffineTransform(scaleX: 1, y: -1)
}

答案 9 :(得分:0)

     //Add these lines where you want to reload your tableView  
let indexpath = IndexPath(row: self.Array.count-1, section: 0)
                                self.tableView.scrollToRow(at: indexpath, at: .top, animated: true)
                                self.updateTableContentInset()
    
    
    
    //Add this function below
    func updateTableContentInset() {
        let numRows = self.tableView.numberOfRows(inSection: 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
                break
            }
        }
        self.tableView.contentInset = UIEdgeInsets(top: contentInsetTop,left: 0,bottom: 0,right: 0)
    }

答案 10 :(得分:-2)

如果您在cellForRowAtIndexPath:中显示了一个对象数组,可以说dataArray可以将其反转,或者cellForRowAtIndexPath: 你可以这样做:

NSString *yourObject = dataArray[[dataArray count] - 1 - indexPath.row];
cell.textLabel.text = yourObject

我假设你在dataArray中保留字符串。