it-swarm.com.ru

Как заполнить UITableView снизу вверх?

можно ли изменить порядок таблицы. Я много искал решение, но все результаты не совсем помогли достичь того, чего я пытаюсь достичь. Все они предлагают прокрутить до последней позиции таблицы с помощью scrollToRowAtIndexPath и заполнить данные в обратном порядке. Но это не работает, если содержимое таблицы является динамическим, и в некоторых случаях не все ячейки имеют данные. Например, в обычном tableView порядок:


этикетка 1

ярлык 2

ярлык 3

пустой

пустой

направление прокрутки
V
В


желаемый результат будет:
направление прокрутки
^
^

пустой

пустой

пустой

ярлык 3

ярлык 2

этикетка 1


в этом примере, если бы я использовал предложенный метод scrollToRowAtIndexPath и использовал длину массива объектов, я бы получил только третью ячейку сверху. И в конечном итоге что-то вроде этого: 


нежелательный результат:

ярлык 3

ярлык 2

этикетка 1

пустой

пустой

направление прокрутки
V
В


любая помощь будет здорово, спасибо.

26
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 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)
}
24
KlimczakM

первый обратный просмотр 

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

затем обратная ячейка в ячейке создания.

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

    ...

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

Вот усовершенствованное решение решения KlimczakM, которое работает с автоматически расположенными ячейками табличного представления (а также с фиксированными ячейками). Это решение также работает с разделами, верхними и нижними колонтитулами.

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

НОТА:

Выше код не проверен, но должен работать ... Просто убедитесь, что вы справитесь с высотой любой панели навигации или вкладки, и все будет в порядке. В приведенном выше коде я делаю это только для navbar!

3
Alexander W

Простой способ - использовать несколько строк UILabel + autolayout .-> UITableView должен изменить его размер на основе содержимого (так называемый внутренний макет) . Создайте табличное представление и установите следующий базовый класс:

class IntrinsicTableView: UITableView {

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

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

}

Теперь установите левое, правое и нижнее ограничения макета для вашего вывода таблицы, чтобы оно было родительским представлением Наиболее важным является ограничение верхнего макета, которое должно быть больше или равно 0. Это условие гарантировано, что таблица не будет выше родительского представления. 

2
Trung Phan

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 привязать строки к низу

1
Maximo Lucosi

Не пытайтесь написать код самостоятельно .. Почему бы вам не использовать ReverseExtension. Это очень просто и даст вам все необходимые результаты. Пожалуйста, следуйте этому URL https://github.com/marty-suzuki/ReverseExtension

Примечание: Всякий раз, когда вам нужно добавить новую ячейку, вставьте новую добавленную модель в нулевой индекс массива источника данных, чтобы новая ячейка добавлялась снизу. В противном случае это добавит ячейку сверху, и вы снова запутаетесь.

1
Aaban Tariq Murtaza

Я сделал в методе cellForRowAt:

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

let currCellData = myArray.object(at: reverseIndex) 

а затем вы продолжаете работать с currCellData

0
Gulz

Это решение корректирует вставку содержимого при изменении размера содержимого с использованием 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