web-dev-qa-db-ja.com

UITableViewを下から上に配置する方法は?

tableViewの順序を逆にすることは可能ですか?私は多くの解決策を探しましたが、すべての結果は私が達成しようとしているものに対する解決策ではありませんでした。これらはすべて、scrollToRowAtIndexPathを使用してテーブルの最後の位置までスクロールし、逆にデータを取り込むことを提案しています。ただし、テーブルの内容が動的であり、場合によってはすべてのセルにデータがない場合、これは機能しません。たとえば、通常のtableViewでの順序は次のとおりです。


ラベル1

ラベル2

ラベル3

空の

空の

スクロール方向
v
V


望ましい結果は次のとおりです。
スクロール方向
^
^

空の

空の

空の

ラベル3

ラベル2

ラベル1


この例では、scrollToRowAtIndexPathの推奨メソッドを使用し、オブジェクトの配列の長さを使用すると、上から3番目のセルのみが取得されます。そして、このようなものになります:


望ましくない結果:

ラベル3

ラベル2

ラベル1

空の

空の

スクロール方向
v
V


どんな助けでも大歓迎です。

29
kai Taylor

テーブルにデータを入力するには下からこれを使用します:

- (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.バージョン:

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

最初の逆UitableView

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

次に、セル作成でセルを反転します。

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

    ...

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

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
    }
5
Akbar Khan

これは、自動レイアウトされたテーブルビューセル(および固定セル)で動作するKlimczakMのソリューションの洗練されたソリューションです。このソリューションは、セクション、セクションヘッダー、およびセクションフッターでも機能します。

Swift 3.

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)
}

注:

上記のコードはテストされていませんが、動作するはずです。 navbarまたはtabbarの高さに対応していることを確認するだけで大​​丈夫です。上記のコードでは、navbarに対してのみそれを行います!

3
Alexander W

簡単な方法は、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ピンの左右および下部のレイアウト制約を親ビューに設定します。最も重要なのは、最上位のレイアウト制約を0以上に設定することです。この条件は、テーブルが親ビューよりも高くないことを保証します。

2
Trung Phan

わざわざ自分でコードを書く必要はありません。 ReverseExtensionを使用しないのはなぜですか。その非常に簡単で、必要な結果がすべて得られます。このURLをフォローしてください https://github.com/marty-suzuki/ReverseExtension

注:新しいセルを追加する必要があるときはいつでも、データソース配列のゼロ番目のインデックスに新しく追加されたモデルを挿入してください。そうしないと、セルが一番上に追加され、再び混乱します。

2

CellForRowAtメソッドで行いました:

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

let currCellData = myArray.object(at: reverseIndex) 

そしてcurrCellDataを使い続けます

1
Gulz

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)

ITableViewアンカー行を下に

1
Maximo Lucosi

このソリューションは、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];

    }
}
0
Eran Goldin