ios 如何从底部向上填充 UITableView?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28105905/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:28:01  来源:igfitidea点击:

How to populate UITableView from the bottom upwards?

iosobjective-ciphoneuitableviewios8

提问by kai Taylor

is it possible to reverse the order of a tableView. I have searched a lot for a solution but all the results have not quite been a solution to what I am trying to achieve. They all suggest scrolling to the last position of a table with scrollToRowAtIndexPathand populating the data in reverse. But this doesn't work if the table content is dynamic and in some instances not all the cells have data. For example in a normal tableView the order is:

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



label 1

标签 1

label 2

标签 2

label 3

标签 3

empty

空的

empty

空的

scroll direction
v
V

滚动方向
v
V



the desired result would be:
scroll direction
^
^

所需的结果是:
滚动方向
^
^

empty

空的

empty

空的

empty

空的

label 3

标签 3

label 2

标签 2

label 1

标签 1



in this example if I used the suggested method of scrollToRowAtIndexPathand use the length of the array of objects, I would only get the third cell from the top. And end up with something like this:

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



unwanted outcome:

不想要的结果:

label 3

标签 3

label 2

标签 2

label 1

标签 1

empty

空的

empty

空的

scroll direction
v
V

滚动方向
v
V



any help would be great thank you.

任何帮助都会非常感谢。

回答by KlimczakM

To populate UITableViewfrom the bottom:

UITableView从底部填充:

- (void)updateTableContentInset {
    NSInteger numRows = [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);
}

To reverse the order of elements:

要反转元素的顺序:

dataSourceArray = dataSourceArray.reverseObjectEnumerator.allObjects;

Swift 4.2/5version:

斯威夫特 4.2/5版本:

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
        }
    }
    self.tableView.contentInset = UIEdgeInsets(top: contentInsetTop,left: 0,bottom: 0,right: 0)
}

Swift 3/4.0version:

斯威夫特 3/4.0版本:

self.tableView.contentInset = UIEdgeInsetsMake(contentInsetTop, 0, 0, 0)

回答by waynett

first reverse uitableview

第一个反向uitableview

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

then reverse cell in cell create.

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

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

    ...

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

回答by Akbar Khan

Swift 4.0 and 4.2 version

Swift 4.0 和 4.2 版本

First reverse UITableView in viewDidLoad

viewDidLoad 中的第一个反向 UITableView

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

Then reverse the cell in cellForRowAt.

然后反转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
    }

回答by Aaban Tariq Murtaza

Don't bother to write the code by yourself. Why don't you use ReverseExtension. Its very easy and will give you all required results. Please follow this url https://github.com/marty-suzuki/ReverseExtension

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

Note:Whenever you need to add a new cell, please insert newly added model at zeroth index of datasource array, so new cell should add at bottom. Otherwise it would add the cell at top and you would get confused again.

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

回答by Alexander W

Here is a refined solution of KlimczakM′s solution that works with autolayouted tableview cells (as well as the fixed ones). This solution also works with sections, section headers and section footers.

这是 KlimczakM 解决方案的改进解决方案,它适用于自动布局的 tableview 单元格(以及固定的单元格)。此解决方案也适用于节、节页眉和节页脚。

Swift 3.0:

斯威夫特 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)
}

NOTE:

笔记:

Above code is untested but should work. Just make sure that you cope for the height of any navbar or tabbar and you'll be fine. In the code above i only do that for the navbar!

上面的代码未经测试,但应该可以工作。只要确保你适应任何导航栏或标签栏的高度,你就会没事的。在上面的代码中,我只为导航栏这样做!

回答by Trung Phan

The simple way is use like UILabel multiple lines + autolayout. -> UITableView should resize it base on it content(aka intrinsic layout). Create your tableview and set base class following:

简单的方法是使用像 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)
}

}

}

Now set left right and bottom layout constraints for your tableview pin to it parent view. The most important is top layout constraint should set to great than or equal 0, This condition guaranteed table will not tall than it parent view.

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

回答by Gulz

I did in cellForRowAt method:

我在 cellForRowAt 方法中做了:

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

let currCellData = myArray.object(at: reverseIndex) 

and then you continue working with currCellData

然后你继续使用 currCellData

回答by Eran Goldin

This solution adjust the content inset as the content size changesusing KVO. It also takes the content inset into account when scrolling to top as simply scrolling to CGPointZerowill scroll to the top of the content instead of scrolling to the top of the table.

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

    }
}

回答by Maximo Lucosi

Swift 3.01 - Other solution can be, rotate and flip the tableView.

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

UITableView 将行锚定到底部

回答by Greg

If you have an array of object you display in cellForRowAtIndexPath:, lets say dataArrayyou can reverse it, or in cellForRowAtIndexPath:you can do something like that:

如果您有一个显示在 中的对象数组cellForRowAtIndexPath:,假设dataArray您可以反转它,或者cellForRowAtIndexPath:您可以执行以下操作:

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

I assume you keep strings in dataArray.

我假设您将字符串保存在 dataArray 中。