Как создать панель инструментов между строками UITableView - PullRequest
25 голосов
/ 10 мая 2011

Меня интересует, как tweetbot выполняет следующие действия:

Enter image description here

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

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

Ответы [ 6 ]

29 голосов
/ 03 сентября 2011

Лучший способ сделать это - добавить фиктивную ячейку ниже ячейки, которая была нажата.

Сначала вы должны отслеживать, какая ячейка была нажата, и действовать соответственно.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    //if user tapped the same row twice let's start getting rid of the control cell
    if([indexPath isEqual:self.tappedIndexPath]){
        [tableView deselectRowAtIndexPath:indexPath animated:NO];
    }

    //update the indexpath if needed... I explain this below 
    indexPath = [self modelIndexPathforIndexPath:indexPath];

    //pointer to delete the control cell
    NSIndexPath *indexPathToDelete = self.controlRowIndexPath;

    //if in fact I tapped the same row twice lets clear our tapping trackers 
    if([indexPath isEqual:self.tappedIndexPath]){
        self.tappedIndexPath = nil;
        self.controlRowIndexPath = nil;
    }
    //otherwise let's update them appropriately 
    else{
        self.tappedIndexPath = indexPath; //the row the user just tapped. 
        //Now I set the location of where I need to add the dummy cell 
        self.controlRowIndexPath = [NSIndexPath indexPathForRow:indexPath.row + 1   inSection:indexPath.section];
    }

    //all logic is done, lets start updating the table
    [tableView beginUpdates];

    //lets delete the control cell, either the user tapped the same row twice or tapped another row
    if(indexPathToDelete){
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPathToDelete] 
                          withRowAnimation:UITableViewRowAnimationNone];
    }
    //lets add the new control cell in the right place 
    if(self.controlRowIndexPath){
        [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:self.controlRowIndexPath] 
                          withRowAnimation:UITableViewRowAnimationNone];
    }

    //and we are done... 
    [tableView endUpdates];  
} 

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if(self.controlRowIndexPath){
        return modelArray.count + 1;
    }
    return self.modelArray.count;
}

Кроме того, верните соответствующую высоту для вашей ControlCell.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath   *)indexPath 
{
    if([indexPath isEqual:self.controlRowIndexPath]){
        return 45; //height for control cell
    }
    return 70; //height for every other cell 
}

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

- (NSIndexPath *)modelIndexPathforIndexPath:(NSIndexPath *)indexPath
{
    int whereIsTheControlRow = self.controlRowIndexPath.row;
    if(self.controlRowIndexPath != nil && indexPath.row > whereIsTheControlRow)
        return [NSIndexPath indexPathForRow:indexPath.row - 1 inSection:0]; 
    return indexPath;
}

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

18 голосов
/ 10 мая 2011

В tableView:didSelectRowAtIndexPath: вы удаляете вид инструмента из последней выбранной ячейки. Если такого представления нет, вы создаете новое. Затем вы добавляете этот вид во вновь выбранную ячейку. Сохраните indexPath выбранной строки.

В tableView:heightForRowAtIndexPath: вы проверяете, совпадает ли indexPath с сохраненным indexPath. Если они равны, вы возвращаете высоту, равную высоте обоих видов. Если оно не равно, просто верните высоту «реальной ячейки».

Поместите все ваши звонки в didSelectRowAtIndexPath между [tableView beginUpdates] и [tableView endUpdates], чтобы получить анимацию для изменения высоты.

2 голосов
/ 28 января 2013

Код rjgonzo работает нормально, за исключением случая, когда у вас есть только 1 строка в табличном представлении.Когда есть только 1 строка (и 1 объект в модели данных таблицы), вы получите исключение NSRange при вызове insertRowsatIndexPath (s).Чтобы это исправить, я проверил, есть ли в модели данных только 1 объект, и если да, то я добавляю строку в текущий indexpath (вместо controlindexpath), что приводит к логическому добавлению строки над первой строкой, а затем я вызываю moveRowAtIndexPath дляпоменять местами после вызова [self.tableView endUpdates].Анимация отображается, как и ожидалось, с контрольной строкой, которая кажется скользящей вниз от 1-й строки.

if(self.controlRowIndexPath){

//Check to see if the datamodel only has 1 object

 if([self.objects count]==1){
//If so then insert the row above the row
    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                              withRowAnimation:UITableViewRowAnimationNone];

    }
    else
    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:self.controlRowIndexPath]
                          withRowAnimation:UITableViewRowAnimationNone];

 }

[self.tableView endUpdates];

//if the row was inserted above the 1st row then switch the rows

 if([self.objects count]==1)
 [self.tableView moveRowAtIndexPath:self.controlRowIndexPath toIndexPath:indexPath];
1 голос
/ 10 мая 2011

Я бы не добавил подпредставление к UITableViewCell, я бы добавил еще одну строку к UITableView. Таким образом, UITableView позаботится об анимации. (И я не думаю, что это возможно для анимированных UITableViewCell изменений высоты ...)

Используйте просто

- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation

добавить строку. И

- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation

чтобы удалить его.

0 голосов
/ 25 января 2012

@ rjgonzo это прекрасно работает, но есть небольшая проблема с тем, как вы храните indexPathToDelete. Так как это просто еще один указатель на self.controlRowIndexPath, после очистки или переназначения self.controlRowIndexPath indexPathToDelete будет не тем, что вы хотели, а tableView deleteRowsAtIndexPaths: withRowAnimation: call вызовет сбой SIGBART.

так, вместо

    //pointer to delete the control cell
    NSIndexPath *indexPathToDelete = self.controlRowIndexPath;

и

    //lets delete the control cell, either the user tapped the same row twice or tapped another row
    if(indexPathToDelete){
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPathToDelete] 
                      withRowAnimation:UITableViewRowAnimationNone];
    }

следующий код должен работать нормально:

    //pointer to delete the control cell
NSIndexPath *indexPathToDelete = [NSIndexPath indexPathForRow:self.control_row_index_path.row inSection:self.control_row_index_path.section];
    ...
    ...
    //lets delete the control cell, either the user tapped the same row twice or tapped another row
if(indexPathToDelete.row != 0){
    NSLog(@"row to delete %d", indexPathToDelete.row);
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPathToDelete] withRowAnimation:UITableViewRowAnimationNone];
}
0 голосов
/ 07 июня 2011

Вот что я делаю, чтобы анимация была чистой.

В дополнение к стратегии, которую предлагает пользователь fluchtpunkt (то есть добавление подпредставления в ячейку, обновлениевысота ячейки через heightForRowAtIndexPath, beginUpdates и endUpdates), я считаю следующие меры полезными для анимации:

  1. Ячейки табличного вида имеют фоновое изображение.В противном случае добавленное подпредставление / панель инструментов отображается через ячейку непосредственно перед тем, как табличное представление анимирует изменение высоты.
  2. Ячейка таблицы находится «позади» представления, которое является ячейкой под ней, в противном случае снова отобразится подпредставление / панель инструментов.слишком раноЯ использую [tableview sendSubviewToBack: cell];и это заботится об этом.

Это чисто для меня, но не совсем как Tweetbot .Интересно, что анимация Tweetbot, кажется, тянет панель инструментов вниз, поскольку нижняя часть ячейки анимируется вниз.Похоже, что должна происходить какая-то дополнительная анимация, или моя теория заговора такова, что она фактически добавляет подпредставление в верхнюю часть ячейки под выбранной ячейкой, а затем выполняет удлинение и анимацию для ячейки ниже.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...