UITableView установлен на статические ячейки.Можно ли скрыть некоторые ячейки программно? - PullRequest
126 голосов
/ 24 ноября 2011

UITableView установлен на статические ячейки.

Можно ли программно скрыть некоторые ячейки?

Ответы [ 22 ]

3 голосов
/ 29 января 2019

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

  1. создайте IBOutlet для вашего контроллера представления. @IBOutlet weak var myCell: UITableViewCell!

  2. Обновите myCell в своей пользовательской функции, например, вы можете добавить ее в viewDidLoad:

override func viewDidLoad() { super.viewDidLoad() self.myCell.isHidden = true }

  1. в вашем методе делегата:

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { let cell = super.tableView(tableView, cellForRowAt: indexPath) guard !cell.isHidden else { return 0 } return super.tableView(tableView, heightForRowAt: indexPath) }

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

1 голос
/ 22 августа 2012

Я нашел решение для анимации скрытых ячеек в статической таблице.

// Class for wrapping Objective-C block
typedef BOOL (^HidableCellVisibilityFunctor)();
@interface BlockExecutor : NSObject
@property (strong,nonatomic) HidableCellVisibilityFunctor block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block;
@end
@implementation BlockExecutor
@synthesize block = _block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block
{
    BlockExecutor * executor = [[BlockExecutor alloc] init];
    executor.block = block;
    return executor;
}
@end

Требуется только один дополнительный словарь:

@interface MyTableViewController ()
@property (nonatomic) NSMutableDictionary * hidableCellsDict;
@property (weak, nonatomic) IBOutlet UISwitch * birthdaySwitch;
@end

И посмотрите на реализацию MyTableViewController. Нам нужны два метода для преобразования indexPath между видимым и невидимым индексами ...

- (NSIndexPath*)recoverIndexPath:(NSIndexPath *)indexPath
{
    int rowDelta = 0;
    for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
    {
        BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
        if (ip.section == indexPath.section
            && ip.row <= indexPath.row + rowDelta
            && !executor.block())
        {
            rowDelta++;
        }
    }
    return [NSIndexPath indexPathForRow:indexPath.row+rowDelta inSection:indexPath.section];
}

- (NSIndexPath*)mapToNewIndexPath:(NSIndexPath *)indexPath
{
    int rowDelta = 0;
    for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
    {
        BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
        if (ip.section == indexPath.section
            && ip.row < indexPath.row - rowDelta
            && !executor.block())
        {
            rowDelta++;
        }
    }
    return [NSIndexPath indexPathForRow:indexPath.row-rowDelta inSection:indexPath.section];
}

Один IBAction при изменении значения UISwitch:

- (IBAction)birthdaySwitchChanged:(id)sender
{
    NSIndexPath * indexPath = [self mapToNewIndexPath:[NSIndexPath indexPathForRow:1 inSection:1]];
    if (self.birthdaySwitch.on)
        [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    else
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}

Некоторые методы UITableViewDataSource и UITableViewDelegate:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    int numberOfRows = [super tableView:tableView numberOfRowsInSection:section];
    for (NSIndexPath * indexPath in [self.hidableCellsDict allKeys])
        if (indexPath.section == section)
        {
            BlockExecutor * executor = [self.hidableCellsDict objectForKey:indexPath];
            numberOfRows -= (executor.block()?0:1);
        }
    return numberOfRows;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    indexPath = [self recoverIndexPath:indexPath];
    return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    indexPath = [self recoverIndexPath:indexPath];
    return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // initializing dictionary
    self.hidableCellsDict = [NSMutableDictionary dictionary];
    [self.hidableCellsDict setObject:[BlockExecutor executorWithBlock:^(){return self.birthdaySwitch.on;}] forKey:[NSIndexPath indexPathForRow:1 inSection:1]];
}

- (void)viewDidUnload
{
    [self setBirthdaySwitch:nil];
    [super viewDidUnload];
}

@end
1 голос
/ 27 сентября 2017

Простой метод, совместимый с iOS 11 и IB / раскадровкой

Для iOS 11 я обнаружил, что модифицированная версия Ответ Мохамеда Салеха работал лучше всего, с некоторыми улучшениями, основанными на документации Apple. Он хорошо анимирует, избегает уродливых хаков или жестко закодированных значений, а использует высоты строк, уже установленные в Интерфейсном Разработчике .

Основная концепция заключается в установке высоты строки на 0 для любых скрытых строк. Затем используйте tableView.performBatchUpdates для запуска анимации, которая работает последовательно.

Установить высоту ячейки

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if indexPath == indexPathOfHiddenCell {
        if cellIsHidden {
            return 0
        }
    }
    // Calling super will use the height set in your storyboard, avoiding hardcoded values
    return super.tableView(tableView, heightForRowAt: indexPath)
}

Вы хотите убедиться, что cellIsHidden и indexPathOfHiddenCell установлены в соответствии с вашим вариантом использования. Для моего кода это свойства моего контроллера табличного представления.

Переключение клетки

В любом методе, контролирующем видимость (вероятно, действие кнопки или didSelectRow), переключайте состояние cellIsHidden внутри блока performBatchUpdates:

tableView.performBatchUpdates({
                // Use self to capture for block
                self.cellIsHidden = !self.cellIsHidden 
            }, completion: nil)

Apple рекомендует performBatchUpdates свыше beginUpdates / endUpdates, когда это возможно.

1 голос
/ 26 ноября 2017

Swift 4:

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    var height = super.tableView(tableView, heightForRowAt: indexPath)
    if (indexPath.row == HIDDENROW) {
        height = 0.0
    }
    return height
}
1 голос
/ 14 июня 2016

В> Swift 2.2, я объединил несколько ответов здесь.

Создание выхода из раскадровки для ссылки на статическую ячейку.

@IBOutlet weak var updateStaticCell: UITableViewCell!

override func viewDidLoad() {
    ...
    updateStaticCell.hidden = true
}

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    if indexPath.row == 0 {
        return 0
    } else {
        return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
    }
}

Я хочу скрыть свою первую ячейку, поэтому я установил высоту в 0, как описано выше.

1 голос
/ 21 марта 2016

Ответ в swift :

Добавьте следующий метод в ваш TableViewController:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return indexPathOfCellYouWantToHide == indexPath ? 0 : super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}

если tableView пытается нарисовать ячейку, которую вы хотите скрыть, то он не будет отображать ее, потому что его высота будет установлена ​​на 0pt благодаря описанному выше методу, все остальное остается неизменным.

Обратите внимание, что indexPathOfCellYouWantToHide можно изменить в любое время:)

0 голосов
/ 17 июля 2019

У меня есть лучший способ динамически скрывать статические ячейки и даже секции без каких-либо взломов.

Установка высоты строки в 0 может скрыть строку, но это не сработает, если вы хотите скрыть всюраздел, который будет содержать некоторые пробелы, даже если вы скроете все строки.

Мой подход заключается в создании массива разделов из статических ячеек.Затем содержимое табличного представления будет управляться массивом раздела.

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

var tableSections = [[UITableViewCell]]()

private func configTableSections() {
    // seciton A
    tableSections.append([self.cell1InSectionA, self.cell2InSectionA])

    // section B
    if shouldShowSectionB {
        tableSections.append([self.cell1InSectionB, self.cell2InSectionB])
    }

    // section C
    if shouldShowCell1InSectionC {
        tableSections.append([self.cell1InSectionC, self.cell2InSectionC, self.cell3InSectionC])
    } else {
        tableSections.append([self.cell2InSectionC, self.cell3InSectionC])
    }
}

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

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return tableSections[section].count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    return tableSections[indexPath.section][indexPath.row]
}

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

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

Аналогичным образом вы можете создать массив заголовков заголовков разделов и массив заголовков нижнего колонтитула разделов для динамической настройки заголовков разделов.

0 голосов
/ 22 марта 2017

В дополнение к решению @Saleh Masum:

Если вы получаете ошибки автоматического макета , вы можете просто удалить ограничения из tableViewCell.contentView

Swift 3:

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    let tableViewCell = super.tableView(tableView, cellForRowAt: indexPath)

    if tableViewCell.isHidden == true
    {
        tableViewCell.contentView.removeConstraints(tableViewCell.contentView.constraints)
        return 0
    }
    else{
        return super.tableView(tableView, heightForRowAt: indexPath)
    }

}

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

0 голосов
/ 25 октября 2013

Для простейшего сценария, когда вы скрываете ячейки в самом низу табличного представления, вы можете настроить tableView contentInset после скрытия ячейки:

- (void)adjustBottomInsetForHiddenSections:(NSInteger)numberOfHiddenSections
{
    CGFloat bottomInset = numberOfHiddenSections * 44.0; // or any other 'magic number
    self.tableView.contentInset = UIEdgeInsetsMake(self.tableView.contentInset.top, self.tableView.contentInset.left, -bottomInset, self.tableView.contentInset.right);
}
0 голосов
/ 06 апреля 2014

Это новый способ сделать это, используя https://github.com/k06a/ABStaticTableViewController

NSIndexPath *ip = [NSIndexPath indexPathForRow:1 section:1];
[self deleteRowsAtIndexPaths:@[ip] withRowAnimation:UITableViewRowAnimationFade]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...