it-swarm.com.ru

UITableView: правильный способ отображения разделителя для последней ячейки

Вопрос в том, какой самый правильный способ отобразить разделитель в последней ячейке таблицы/раздела. 

В основном это то, что я после.

enter image description here Это из нативного музыкального приложения, которое заставляет меня думать, что этого можно достичь с помощью UITableView, они не будут использовать какой-то частный API для разделителей ячеек, верно?

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

  1. Когда ячейка выделена/выделена ее разделитель и разделитель предыдущей ячейки автоматически скрываются (см. Второй снимок экрана с выбранным «Вы должны быть сумасшедшим»). И это Что-то, что я хочу, чтобы UITableView обрабатывал, а не делал сам, если я использую однопиксельную линию (Что особенно удобно, когда разделители ячеек не расширяют все До края представления таблицы. , разделители и выделенный фон ячейки не выглядят хорошо вместе).
  2. Я хотел бы держать свои клетки как можно более плоскими для прокрутки производительности.

Также есть что-то в справке UITableView, которая заставляет меня думать, что есть простой способ получить то, что я хочу:

В iOS 7 и более поздних версиях разделители ячеек не распространяются полностью на Край табличного представления. Это свойство устанавливает стандартную вставку для всех ячейки в таблице, так же как rowHeight устанавливает высоту по умолчанию для клетки. Он также используется для управления «дополнительными» разделителями, нарисованными в нижняя часть простых таблиц стилей.

Кто-нибудь знает, как именно использовать эти «лишние» разделители, нарисованные внизу простых таблиц стилей? Потому что это именно то, что мне нужно. Я думал, что присвоение separatorInsetUITableView, а не UITableViewCell поможет, но это не так, в последней ячейке все еще отсутствует разделитель.

Прямо сейчас я вижу только один вариант: иметь собственный нижний колонтитул раздела, чтобы имитировать разделитель для последней ячейки. И это не очень хорошо, особенно если вы хотите иметь фактический нижний колонтитул раздела, используя метод tableView:titleForFooterInSection:.

29
dariaa

Это сработало для меня, чтобы добавить разделитель в последнюю ячейку. повеселись!

self.tableView.tableFooterView = [[UIView alloc] init];
16
Timo Cengiz

Когда вы добавляете headerView или footerView к вашему TableView, последняя разделительная строка исчезнет. 

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

Для Swift 4.0

func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {

    let result = UIView()

    // recreate insets from existing ones in the table view
    let insets = tableView.separatorInset
    let width = tableView.bounds.width - insets.left - insets.right
    let sepFrame = CGRect(x: insets.left, y: -0.5, width: width, height: 0.5)

    // create layer with separator, setting color
    let sep = CALayer()
    sep.frame = sepFrame
    sep.backgroundColor = tableView.separatorColor?.cgColor
    result.layer.addSublayer(sep)

    return result
}
8
lukszar

Я только что нашел то, что работает для меня. В двух словах: присвойте вашему UITableView tableFooterView и установите высоту его фрейма в 0 . Это делает фактическое шоу сепаратора с правильными вставками.

Более подробно: если вы используете раскадровку, перетащите UIView в нижнюю часть вашего табличного представления (в древовидном представлении слева), чтобы оно отображалось чуть ниже ячейки табличного представления на том же иерархическом уровне. Это создает tableFooterView. Конечно, это можно сделать и программно.

Затем в реализации вашего UITableViewController:

UIView *footerView = self.tableView.tableFooterView;
CGRect footerFrame = footerView.frame;
footerFrame.size.height = 0;
[footerView setFrame:footerFrame];

Дайте мне знать, если это работает для вас! Это также может работать для первого разделителя, если вы используете вместо него tableHeaderView, хотя я не пробовал.

7
SimonFrr

Вы можете сделать что-то вроде этого, если вы не используете разделы: 

- (void)viewDidLoad
{
     self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(insetLeftSide, 0, width - insetRightSide, 1)];
}

Если вы используете разделы, внедрите нижний колонтитул в каждом разделе как один пункт View в методах

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
}

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

2
artud2000

Итак, вот супер простое решение в Swift 4 , которое работает:

Внутри override func viewDidLoad(){} я просто реализовал следующую строку кода:

    self.tableView.tableFooterView = UIView(frame: .zero)

Следовательно, это гарантирует, что только последняя ячейка получает вставку разделителя.

Это отлично сработало для меня, надеюсь, что и для вас!

2
Nii Mantse

У меня была похожая проблема, и я нашел обходной путь. Apple скрывает последний разделитель uitableviewcell и затем отображает его, если вы выбираете ячейку или вызываете select и снимите выделение с этой ячейки.

Так что я учил, что лучшее в - (void)layoutSubviews. Представление разделителя называется _separatorView и является частной собственностью. Используя выделенные/выделенные состояния ячейки, вы можете получить что-то вроде этого:

- (void)layoutSubviews
{
    // Call super so the OS can do it's layout first
    [super layoutSubviews];

    // Get the separator view
    UIView *separatorView = [self valueForKey:@"_separatorView"];
    // Make the custom inset
    CGRect newFrame = CGRectMake(0.0, 0.0, self.bounds.size.width, separatorView.frame.size.height);
    newFrame = CGRectInset(newFrame, 15.0, 0.0);
    [separatorView setFrame:newFrame];

    // Show or hide the bar based on cell state        
    if (!self.selected) {
        separatorView.hidden = NO;
    }
    if (self.isHighlighted) {
        separatorView.hidden = YES;
    }
}

Что-то вроде этого.

2
Cyupa

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

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

self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
self.tableView.separatorColor = [UIColor redColor];
self.tableView.separatorInset = UIEdgeInsetsZero;
2
Ilario

В iOS 8, если у вас простой стиль UITableView и вы добавили нижний колонтитул, последний разделитель пропал. Тем не менее, вы можете легко воссоздать его, добавив собственный вид разделителя в нижний колонтитул.

Этот пример точно имитирует стиль разделителя Today Widget

    override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {

        //create footer view
        let result = UIView()
        result.frame.size.height = tableView.rowHeight

        //recreate last cell separator, which gets hidden by footer
        let sepFrame = CGRectMake(15, -0.5, tableView.frame.width, 0.5);
        let vibrancyEffectView = UIVisualEffectView.init(effect: UIVibrancyEffect.notificationCenterVibrancyEffect())
        vibrancyEffectView.frame = sepFrame
        vibrancyEffectView.contentView.backgroundColor = tableView.separatorColor
        result.addSubview(vibrancyEffectView)
        return result
}
1
Vilém Kurz

Если вы добавите пустой нижний колонтитул, то просмотр таблицы удалит все оставшиеся разделители строк (для несуществующих ячеек), но все равно будет включать разделитель для последней ячейки:

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
    return [UIView new]; 
}
1
Oren

Swift 3

Я нашел эту старую проблему, поэтому я попробовал то же самое в Swift:

    tableView.tableFooterView = UIView()
    tableView.tableFooterView?.height = 0 // Maybe not necessary

Но это приводит к другой проблеме (в моем случае). Поэтому я решил это по-другому. Я добавил дополнительную ячейку в конце этого раздела, пустую и с высотой, равной нулю:

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
      return previousNumberOfRows + 1
    }

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
      return indexPath.row == previousNumberOfRows ? 0 : previousCellHeight
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
      if indexPath.row == items.count {
        return UITableViewCell()
    } else {
       previousCellInitialization()
    }

Это менее лаконичное решение, но работает в большем количестве случаев, если у вас есть несколько разделов, существующих представлений нижнего колонтитула ...

0
Cocatrix

Работает в iOS 7.x и 8.x (поместите его в cellForRowAtIndexPath):

(PS замените "max элементов вашего источника данных" на количество источников данных вашего массива)

 if (row == <max elements of your datasource>-1) {
     UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, cell.contentView.frame.size.height-1, self.view.frame.size.width, 1)];/// change size as you need.
     separatorLineView.tag = 666;
     separatorLineView.backgroundColor = [UIColor colorWithRed: 204.0/255.0 green: 204.0/255.0 blue: 204.0/255.0 alpha:1.0];
     UIView *separator = [cell.contentView viewWithTag:666];
     // case of orientation changed..
     if (separator.frame.size.width != cell.contentView.frame.size.width) {
        [[cell.contentView viewWithTag:666] removeFromSuperview];
        separator = nil;
     }
     if (separator==nil) [cell.contentView addSubview:separatorLineView];
 }
0
Alessandro Ornano

Это определенно поможет. За работой. но установить разделитель "none" из инспектора атрибутов . Написать следующий код в cellForRowAtIndexPath method

if(indexPath.row==arrData.count-1){
 UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0,           
 cell.contentView.frame.size.height - 1.0,      
 cell.contentView.frame.size.width, 1)];

    lineView.backgroundColor = [UIColor blackColor];
    [cell.contentView addSubview:lineView];
}
0
Mr.Javed Multani

Код ниже работал для меня:

UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 0.35)];
footerView.backgroundColor = [UIColor whiteColor];
CGRect frame = footerView.frame;
frame.Origin.x = 15;
frame.size.width = frame.size.width - 15;
UIView *blackView = [[UIView alloc] initWithFrame:frame];
[blackView setBackgroundColor:[UIColor blackColor]];
blackView.alpha = 0.25;
[footerView addSubview:blackView];
tableView.tableFooterView = footerView;

Надеюсь, это работает и для вас.

0
Ashik