Подтвердить что ты не робот

Группировка UITableview удаляет внешнюю разделительную линию

У меня есть сгруппированный UITableview, который создается программно. Кроме того, у меня есть ячейка с xib файлом, заполненная программным обеспечением tableview. Все идет нормально. Но я хочу только удалить внешнюю разделительную линию. Я использовал ниже код, но на этот раз удалил всю разделительную линию.

self.tableView.separatorColor = [UIColor clearColor];

Это не очень хороший вариант для моей ситуации. Вот скриншот, что я хочу сделать;

enter image description here

4b9b3361

Ответ 1

Здесь мое решение:

self.tableView.separatorColor = self.tableView.backgroundColor

@xxtesaxx, у вас должен быть настоящий тест

Ответ 2

После проверки иерархии представлений кажется, что каждый UITableViewCell имеет только три подпредставления: представление содержимого (UITableViewCellContentView) и два представления разделителя (_UITableViewCellSeparatorView). Я не фанат создания динамических классов из NSStrings (как и Apple Apple). Однако, поскольку contentView UITableViewCell доступен без использования частных API, решение оказывается довольно простым.

Идея состоит в том, чтобы просто contentView вашего UITableViewCell и удалить любые представления, которые не являются contentView:

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    let subviews = cell.subviews
    if subviews.count >= 3 {
        for subview in subviews {
            if subview != cell.contentView {
                subview.removeFromSuperview()
                break
            }
        }
    }
}

tableView(:willDisplayCell:forRowAtIndexPath:) вызывается несколько раз во время рендеринга табличного представления, поэтому вышеизложенное отслеживает состояние путем проверки количества подпредставлений в ячейке. Если у него есть три подпредставления, оба разделителя остаются без изменений. Он также удаляет только один из разделителей, но вы можете удалить оба, удалив break. Вы также можете указать, удалять ли верхний или нижний разделитель, проверив рамку подпредставления. Если начало оси Y кадра равно 0, это верхний разделитель. Если это не 0, это внизу.

Надеюсь это поможет!

Swift 4, Swift 4.2 Обновление:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    let subviews = cell.subviews
    guard subviews.count >= 3 else {
        return
    }

    for subview in subviews where NSStringFromClass(subview.classForCoder) == "_UITableViewCellSeparatorView" {
        subview.removeFromSuperview()
    }
}

Ответ 3

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

class Cell: UITableViewCell {

override func layoutSubviews() {
    super.layoutSubviews()
    for view in subviews where view != contentView {
        view.removeFromSuperview()
    }
}

Ответ 4

Google, даже в 2018 году, обслуживает эту страницу как лучший результат для этого вопроса. Мне не повезло в iOS 11 с любым из предоставленных ответов, поэтому вот что я придумала:

extension UITableViewCell {
    func removeSectionSeparators() {
        for subview in subviews {
            if subview != contentView && subview.frame.width == frame.width {
                subview.removeFromSuperview()
            }
        }
    }
}

Вызов .removeSectionSeparators() для любого экземпляра UITableViewCell теперь решит проблему. В моем случае, по крайней мере, разделители разделов являются единственными с той же шириной, что и сама ячейка (так как все остальные с отступом).

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

Я закончил тем, что поместил это в мой метод cellForRowAtIndexPath непосредственно перед тем, как вернуть возвращенную ячейку:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "MyReusableIdentifier", for: indexPath)

    Timer.scheduledTimer(withTimeInterval: 0.15, repeats: false) { (timer) in
        cell.removeSectionSeparators()
    }

    return cell
}

Это не выглядит так элегантно, но я еще не сталкивался ни с какими проблемами.

РЕДАКТИРОВАТЬ: Похоже, нам это тоже нужно (для повторно используемых ячеек):

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    cell.removeSectionSeparators()
}

Вот до/после на скриншотах с этим кодом:

До Before Separator Removal

После After Separator Removal

Ответ 5

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

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

К счастью, существует абсолютно простой и простой способ достижения такого вида:

введите описание изображения здесь

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

  • Создайте подкласс UITableViewCell
  • В вашей ячейке создайте свойство @IBOutlet weak var separatorView: UIView!
  • В вашей раскадровке выберите ячейку tableview и выберите свою собственную ячейку в качестве класса, который создает резервную копию ячейки. Примечание. Вы не должны использовать пользовательский стиль. Вы все еще можете использовать Basic, Subtitle и т.д.
  • Установите UITableView Separator Style на None, чтобы скрыть разделитель по умолчанию
  • Перетащите UIView на свою ячейку и измените ее размер так, чтобы она находилась внизу (или в верхней части) ячейки. Используйте Size Inspector Autoresizing, чтобы прикрепить его к началу/концу/дну и присвоить ему ширину гибкости (или Autolayout, но в этом случае чуть выше)
  • Подключите представление к розетке вашего класса ячеек
  • В вашем UITableViewDataSource cellForRowAtIndexPath: установите свойство isHidden вашего пользовательского разделителя на основе, если indexPath.row - это последняя строка (или первая, если ваш вид наверху) в разделе

Вот пример кода:

class MyCell: UITableViewCell {
    @IBOutlet weak var separatorView: UIView!
}

class ViewController: UITableViewController {


    override func numberOfSections(in tableView: UITableView) -> Int {
        return 3
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! MyCell
        cell.separatorView.isHidden = indexPath.row == 2
        return cell
    }

}

И вот несколько скриншотов:

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

Да, это какая-то работа, но при кодировании просто нет свободного места. В конце концов, мы программисты, и нам нужно делать кодирование. Всегда лучше потратить 5-10 минут на настройку, чем просто скопировать вставку какого-то взломанного кода, который не может продолжать работать в будущем, когда Apple решит изменить иерархию представлений.

На самом деле было больше работы написать этот ответ, чем реализовать разделитель. Я также искал легкое и быстрое решение, но, в конце концов, просто не было достаточно хорошего, которое, как мне казалось, стоило использовать.

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

Ответ 6

Вот что я, наконец, придумал:

введите описание изображения здесь

Я не мог найти лучшего способа, чем это. Но он работает для меня очень. Последняя попытка с Xcode Version 7.3.1 (7D1014). Эта процедура была выполнена через раскадровку.

В основном я добавляю UIView из 0.5 pt Height в UITableViewCell, а затем устанавливаю цвет фона для этого UIView. Установите родительский разделитель UITableView как None.

Вот подробности:

Учитывая, что вы уже установили свой UITableViewCell, пользовательский или по умолчанию. На первом этапе установите разделитель UITableView как None.

введите описание изображения здесь

Затем добавьте UIView из 1 pt Height и установите Background так, как вам нужно, в моем случае это красный цвет.

введите описание изображения здесь

введите описание изображения здесь

Начните устанавливать ограничения. Проблема заключается в том, чтобы установить высоту UIView как 0.5 pt. Это единственная проблемная проблема для этого рабочего процесса.

UIView с 0,5 pt Высота:

Разделите способ установки 0.5 pt высоты UIView.

Сначала (1) запишите вид, а затем (2) установите высоту как 0,5. Нажмите Enter.

введите описание изображения здесь

Наконец, ваш UIView будет похож на следующий.

введите описание изображения здесь

Мне не удалось установить высоту как 0,5, кроме этого.

Ответ 7

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

Вот мой код:

во-первых, вы должны сделать разделитель для очистки

tableView.separatorColor = UIColor.clear

Во-вторых, в функции cellForRowAt:

let bottomBorder = CALayer()

bottomBorder.frame = CGRect(x: 0.0, y: 43.0, width: cell.contentView.frame.size.width, height: 1.0)
bottomBorder.backgroundColor = UIColor(white: 0.8, alpha: 1.0).cgColor
cell.contentView.layer.addSublayer(bottomBorder)

здесь вы увидите такой интерфейс:

enter image description here

Ответ 8

Здесь решение. Это для статических ячеек. Если вы хотите динамический, просто перепишите "count". Надеюсь, что это поможет.

extension NSObject {
   var theClassName: String {
       return    NSStringFromClass(self.dynamicType).componentsSeparatedByString(".").last!
   }
}

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.separatorStyle = .None
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    let count = tableView.numberOfRowsInSection(indexPath.section)
    if ( indexPath.row != count - 1 ) {
        for view in cell.subviews {
            if view.theClassName == "_UITableViewCellSeparatorView" {
                view.backgroundColor = UIColors.redColor()
            }
        }
    }
}

Ответ 9

Пробовал различные решения на основе обходного пути cell.separatorInset = UIEdgeInsetsMake(), никто из них не работал должным образом.

Для моего проекта на основе iOS11 UITableViewStyleGrouped это сделало это:

self.tableView.separatorColor = self.tableView.backgroundColor;

Ответ 10

На основании ответа повара, но без таймера:

override func didAddSubview(_ subview: UIView) {
    super.didAddSubview(subview)
    if NSStringFromClass(subview.classForCoder) != "UITableViewCellContentView" && subview.frame.width == frame.width {
        subview.removeFromSuperview()
    }
}

Просто добавьте это в подкласс ячейки, и вам больше ничего не нужно. Работает на iOS 12.

Ответ 11

У меня была аналогичная проблема, когда у меня был Grouped UITableView с пользовательскими ячейками, все из которых были разработаны с использованием интерфейса Build как .xib файлов. Ячейки имели белый фон, удаляли разделители по умолчанию и добавляли мои собственные. У меня также были собственные заголовки заголовков для каждого раздела. Я установил высоту этих заголовков, чтобы быть 44 (может быть что угодно...). Между моими разделами был вид высоты в 1 пункт, который казался странным. По-видимому, система добавляет некоторые четкие фоновые представления между разделами, даже если мы укажем пользовательскую высоту, например 44, а пользовательский заголовок Header View, который мы возвращаем, имеет белый (или некоторый конкретный цвет фона). Цвет, который мы видим за этим четким представлением, - это цвет фона настольного представления. В моем случае как представления таблиц, так и ячейки должны были быть белого цвета, а установка фона в виде таблицы была белой, чтобы решить проблему (по крайней мере визуально, но то, что я хотел в любом случае). Второе решение состояло бы в том, чтобы стиль Table View был простым, но реализовать метод делегата UITableView для возврата 2 или более разделов, а также создать собственные заголовки, если вам нужно. Но это приведет к тому, что заголовок загорится некоторое время (пока прокручивается) до тех пор, пока заголовок заголовка следующего раздела не приблизится к нему, а затем он тоже начнет подниматься (и это может быть не то, что вы действительно хотите, но там может быть простым способом исправить это, но не уверен, хотя).

Ответ 12

Вы можете получить доступ к представлению, используя

override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {

    let header = view as! UITableViewHeaderFooterView 
    header.backgroundView . .....

Ответ 13

Попробуйте это, это удалит верхнюю разделительную линию.

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(indexPath.row == 0 && indexPath.section == 0) {
        for (UIView *view in  cell.subviews) {
            if ([NSStringFromClass([view class]) containsString:@"CellSeparator"]) {
                if (view.frame.origin.y == 0 && CGRectGetHeight(view.frame) < 1.01 ) { //Hide first UITableViewCellSeparatorView
                    NSLog(@"%s Remove View From Cell[Section:0 Row:0] for top border [%@]:%@",__FUNCTION__,NSStringFromClass([view class]),view);
                    view.hidden = YES; //Hide
                }
            }
        }
    }
}

Ответ 14

Для снятия верхней и нижней части разделительной линии для каждой секции. Добавьте это к вашей статической ячейке.

override func layoutSubviews() {
    super.layoutSubviews()

    //Get the width of tableview
    let width = subviews[0].frame.width

    for view in subviews where view != contentView {
        //for top and bottom separator will be same width with the tableview width
        //so we check at here and remove accordingly
        if view.frame.width == width {
            view.removeFromSuperview()
        }
    }
}

Результат как изображение ниже

enter image description here

Ответ 15

Здесь быстрое решение, которое работает на iOS 8 и 9.

Определите протокол с реализацией по умолчанию:

protocol CellSeparatorRemovable { }

extension CellSeparatorRemovable {
    func removeSeparatorLinesFromCell(cell: UITableViewCell, section: Int, row: Int, indexPath: NSIndexPath) {
        guard (section, row) == (indexPath.section, indexPath.row) else { return }

        for view in cell.subviews where view != cell.contentView {
            view.removeFromSuperview()
        }
    }
}

Затем, где бы вы ни захотели его использовать, совместите с протоколом CellSeparatorRemovable и вызовите его метод из …willDisplayCell…:

class SomeVC: UITableViewController, CellSeparatorRemovable {
    override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
        removeSeparatorLinesFromCell(cell, section: 1, row: 1, indexPath: indexPath)
    }
}

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