uitableview: вложенные заголовки разделов - PullRequest
5 голосов
/ 04 октября 2011

Я пытаюсь реализовать uitableview со следующей структурой:

  • группа разделов 0
    • раздел 0
      • ячейка 0
      • ячейка 1
      • ячейка 2
    • секция 1
      • ячейка 0
      • ячейка 1
      • ячейка 2
  • группа секций 1
    • секция 0
      • ячейка 0
      • ячейка 1
      • ячейка 2
    • секция 1
      • ячейка 0
      • ячейка 1
      • ячейка 2

и он должен прокрутиться, как на следующем скриншоте (1-2-3-4): http://dl.dropbox.com/u/2213241/uitableview.png

Так что всегда видны два раздела.

Как мнереализовать это?Или кто-нибудь уже реализовал это?

Спасибо :)

Ответы [ 3 ]

3 голосов
/ 18 сентября 2014

Хитрость в том, чтобы иметь вложенные разделы, состоит в том, чтобы иметь два вида строк в табличном представлении. Один для представления второго уровня разделов, а другой для представления обычных строк в табличном представлении. Допустим, у вас есть двухуровневый массив (скажем, разделы) для представления элементов в табличном представлении.

Тогда общее количество секций, которое у нас есть, это просто количество секций верхнего уровня. Количество строк в каждом разделе верхнего уровня будет равно числу подразделов + количество строк в каждом подразделе.

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return self.sections.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSArray *sectionItems = self.sections[(NSUInteger) section];
    NSUInteger numberOfRows = sectionItems.count; // For second level section headers
    for (NSArray *rowItems  in sectionItems) {
        numberOfRows += rowItems.count; // For actual table rows
    }
    return numberOfRows;
}

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSMutableArray *sectionItems = self.sections[(NSUInteger) indexPath.section];
    NSMutableArray *sectionHeaders = self.sectionHeaders[(NSUInteger) indexPath.section];
    NSIndexPath *itemAndSubsectionIndex = [self computeItemAndSubsectionIndexForIndexPath:indexPath];
    NSUInteger subsectionIndex = (NSUInteger) itemAndSubsectionIndex.section;
    NSInteger itemIndex = itemAndSubsectionIndex.row;

    if (itemIndex < 0) {
        // Section header
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SECTION_HEADER_CELL" forIndexPath:indexPath];
        cell.textLabel.text = sectionHeaders[subsectionIndex];
        return cell;
    } else {
        // Row Item
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ROW_CONTENT_CELL" forIndexPath:indexPath];
        cell.textLabel.text = sectionItems[subsectionIndex][itemIndex];
        return cell;
    }
}

- (NSIndexPath *)computeItemAndSubsectionIndexForIndexPath:(NSIndexPath *)indexPath {
    NSMutableArray *sectionItems = self.sections[(NSUInteger) indexPath.section];
    NSInteger itemIndex = indexPath.row;
    NSUInteger subsectionIndex = 0;
    for (NSUInteger i = 0; i < sectionItems.count; ++i) {
        // First row for each section item is header
        --itemIndex;
        // Check if the item index is within this subsection's items
        NSArray *subsectionItems = sectionItems[i];
        if (itemIndex < (NSInteger) subsectionItems.count) {
            subsectionIndex = i;
            break;
        } else {
            itemIndex -= subsectionItems.count;
        }
    }
    return [NSIndexPath indexPathForRow:itemIndex inSection:subsectionIndex];
}

Вот подробный пост о том, как это сделать.

2 голосов
/ 04 октября 2011

Подклассы UITableView было бы хорошим вариантом, как предложил Робин.Я сам сделал нечто похожее на это, но я вложил в подкласс UITableViewCell и поместил в них UITableView s.В этом случае у вас будет базовый tableView, где каждый раздел будет группой.Каждая строка, потому что вы подкласс UITableViewCell, является тогда его собственным UITableView, который имеет свои собственные разделы и строки.Это должно дать вам внешний вид и функциональность, которую вы ищете.Я был бы рад помочь настроить его, если у вас возникли проблемы с его установкой, но это не так сложно сделать. Этот урок дает хороший пример того, как подкласс UITableViewCell, и является хорошим началом для

0 голосов
/ 13 ноября 2018

В случае, если кому-то интересна версия приведенного выше кода на Swift 4.2, вот она.

Чтобы иметь вложенные разделы, вам нужно иметь несколько видов строк в вашем tableView.Первый представляет второй уровень секций, а второй представляет стандартные строки в вашем tableView.Допустим, у вас есть двухуровневый массив (разделы) для представления элементов в вашем tableView.

Тогда общее количество разделов, которое у нас есть, это просто количество разделов верхнего уровня.Число строк в каждом разделе верхнего уровня будет равно числу подразделов + количество строк в каждом подразделе.

func numberOfSections(in tableView: UITableView) -> Int {
    return sections.count
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let sectionItems = sections[section]
    var numberOfRows: Int = sectionItems.count // For second level section headers
    for rowItems: [Any] in sectionItems as? [[Any]] ?? [] {
        numberOfRows += rowItems.count // For actual table rows
    }
    return numberOfRows
}

Теперь все, что вам нужно подумать, - это как создать строки дляTableview.Установите два прототипа в раскадровке с разными идентификаторами повторного использования, один для заголовка раздела и другой для элемента строки, и просто создайте правильный экземпляр на основе запрашиваемого индекса в методе источника данных.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var sectionItems = sections[indexPath.section]
    var sectionHeaders = self.sectionHeaders[indexPath.section]
    let itemAndSubsectionIndex: IndexPath? = computeItemAndSubsectionIndex(for: indexPath)
    let subsectionIndex = Int(itemAndSubsectionIndex?.section ?? 0)
    let itemIndex: Int? = itemAndSubsectionIndex?.row

    if (itemIndex ?? 0) < 0 {
        // Section header
        let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "SECTION_HEADER_CELL", for: indexPath)
        cell.textLabel?.text = sectionHeaders[subsectionIndex] as? String
        return cell
    } else {
        // Row Item
        let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "ROW_CONTENT_CELL", for: indexPath)
        cell.textLabel?.text = sectionItems[subsectionIndex][itemIndex ?? 0] as? String
        return cell
    }
}

func computeItemAndSubsectionIndex(for indexPath: IndexPath?) -> IndexPath? {
    var sectionItems = sections[Int(indexPath?.section ?? 0)]
    var itemIndex: Int? = indexPath?.row
    var subsectionIndex: Int = 0
    for i in 0..<sectionItems.count {
        // First row for each section item is header
        itemIndex = (itemIndex ?? 0) - 1
        // Check if the item index is within this subsection's items
        let subsectionItems = sectionItems[i] as? [Any]
        if (itemIndex ?? 0) < Int(subsectionItems?.count ?? 0) {
            subsectionIndex = i
            break
        } else {
            itemIndex -= subsectionItems?.count
        }
    }
    return IndexPath(row: itemIndex ?? 0, section: subsectionIndex)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...