it-swarm.com.ru

Анимация нарисованного пользователем UITableViewCell при входе в режим редактирования

Фон

Прежде всего, большое спасибо atebits за их очень информативное сообщение в блоге Быстрая прокрутка в Tweetie с UITableView . В этом посте подробно объясняется, как разработчики смогли выжать как можно большую производительность прокрутки из UITableViews в Tweetie .

Цели

Начиная с исходного кода, связанного с сообщением в блоге ( оригинал ) ( мое репозиторий github ):

  1. Разрешите UITableView, используя эти пользовательские ячейки, переключаться в режим редактирования, предоставляя пользовательский интерфейс для удаления элемента из таблицы. ( github commit )

  2. Отодвиньте текст ячейки в сторону, поскольку элемент управления удалением перемещается слева. Это завершено, хотя текст переходит вперед и назад без анимации. ( github commit )

  3. Примените анимацию к движению текста в цели 2 выше для более удобного взаимодействия с пользователем. Это тот шаг, на котором я застрял.

Вопрос

Как лучше всего внедрить эту анимацию для достижения цели 3? Было бы хорошо, если бы это можно было сделать таким образом, чтобы не допустить логики моего последнего коммита , потому что мне бы хотелось, чтобы опция перемещала только конфликтующую часть представления, в то время как любые неконфликтующие части (такие как как текст с выравниванием по правому краю) оставайтесь на том же месте или перемещайте на другое количество пикселей. Если вышеупомянутое невозможно, то отмена моего последнего коммита и замена его опцией, которая сдвигает весь вид вправо, также будет работоспособным решением.

Я ценю любую помощь, которую может предоставить каждый, от быстрых указателей и идей до фрагментов кода или коммитов github. Конечно, вы можете подписать мое репо , если хотите. Я буду продолжать заниматься этим вопросом, чтобы убедиться, что любое успешное решение предназначено для github и полностью задокументировано здесь. Большое спасибо за ваше время!

Обновленные мысли

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

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

49
Adam Alexander

Благодаря ответу Craig , который указал мне верное направление, у меня есть решение для этого. Я вернул свой commit , который переместил текстовую позицию на основе режима редактирования и заменил ее на новое решение , которое при каждом вызове layoutSubviews задает правильное положение всего содержимого, что приводит к автоматическому анимация при переключении в режим редактирования:

- (void)layoutSubviews
{
    CGRect b = [self bounds];
    b.size.height -= 1; // leave room for the separator line
    b.size.width += 30; // allow extra width to slide for editing
    b.Origin.x -= (self.editing) ? 0 : 30; // start 30px left unless editing
    [contentView setFrame:b];
    [super layoutSubviews];
}

Делая это таким образом, я смог удалить setFrame: override, найденный в ABTableViewCell.m, потому что его прежняя логика плюс мои дополнения теперь находятся в layoutSubviews. 

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

Еще раз спасибо Крейгу и всем, кто изучал это.

GitHub коммит для этого решения: ( link )

24
Adam Alexander

Как вы перемещаете текст в настоящее время? Или, более конкретно, в каком методе UITableViewCell вы выполняете перемещение?

По моему опыту, переопределение метода layoutSubviews и установка фрейма здесь будут автоматически обернуты в анимацию.

Например:

- (void)layoutSubviews {
    if (self.editing) {
        [titleLabel setFrame:CGRectMake(62, 6, 170, 24)];
    }
    else {
        [titleLabel setFrame:CGRectMake(30, 6, 200, 24)];
    }
    [super layoutSubviews];
}
10
Craig Otis

Для полного контроля над редактированием в пользовательской ячейке вы должны переопределить метод willTransitionToState в своем подклассе UITableViewCell и проверить маску состояния

- (void)willTransitionToState:(UITableViewCellStateMask)state
{
    NSString *logStr = @"Invoked";
    if ((state & UITableViewCellStateShowingEditControlMask)
        != 0) {
        // you need to move the controls in left
        logStr = [NSString stringWithFormat:@"%@
                  %@",logStr,@"UITableViewCellStateShowingEditControlMask"];
    }
    if ((state & UITableViewCellStateShowingDeleteConfirmationMask)
        != 0) {
        // you need to hide the controls for the delete button
        logStr = [NSString stringWithFormat:@"%@
                  %@",logStr,@"UITableViewCellStateShowingDeleteConfirmationMask"];
    }
    NSLog(@"%@",logStr);
    [super willTransitionToState:state];
}

также вы можете переопределить layoutSubviews

- (void)layoutSubviews {
    // default place for label
    CGRect alarmTimeRect = CGRectMake(37, 7, 75, 30);
    if (self.editing && !self.showingDeleteConfirmation) {
        // move rect in left
        alarmTimeRect = CGRectMake(77, 7, 75, 30);
    }
    [alarmTimeLabel setFrame:alarmTimeRect];
    [super layoutSubviews];
}
9
UIBuilder

Для обработки смахивания также: (self.editing &&! Self.showingDeleteConfirmation)

8
ben

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

В пользовательской ячейке (наследовать от UITableViewCell) просто перегрузите setEditing:

- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
    [super setEditing:editing animated:animated];

    if (animated) {
        [UIView beginAnimations:@"setEditingAnimation" context:nil];
        [UIView setAnimationDuration:0.3];
    }

    if (editing) {
        /* do your offset and resize here */
    } else {
        /* return to the original here*/
    }

    if (animated)
        [UIView commitAnimations];
}

Я не проверяю, совпадает ли значение редактирования, но это просто идея, как я это сделал. 

3
Sauleil

На самом деле существует четыре редактируемых состояния.

UITableViewCellStateDefaultMask = 0

UITableViewCellStateShowingEditControlMask = 1 << 0 = 0b01 = 1 путем установки tableView.edit = YES

UITableViewCellStateShowingDeleteConfirmationMask = 1 << 1 = 0b10 = 2, проводя, чтобы удалить

UITableViewCellStateShowingEditControlMask и UITableViewCellStateShowingDeleteConfirmationMask = (1 << 1) & (1 << 0) = 0b11 = 3, установив tableView.edit = YES и нажав кнопку «Стоп»

Что меня смутило, так это то, что когда состояние 3 переходит в состояние 1, не вызывается селектор, который не использует self.showingDeleteConfirmation для изменения макета в iOS7 . Следовательно, чтобы прояснить состояние между состоянием 2 и состоянием 3, Я добавил переменную экземпляра для ее реализации. Это прекрасно работает для меня.

-(void)willTransitionToState:(UITableViewCellStateMask)state{
    [super willTransitionToState:state];

    //Custom delete button from
    //http://stackoverflow.com/questions/19159476/uitableviewcelldeleteconfirmationcontrol-issue
    if((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableViewCellStateShowingDeleteConfirmationMask){
        [self recurseAndReplaceSubViewIfDeleteConfirmationControl:self.subviews];
        [self performSelector:@selector(recurseAndReplaceSubViewIfDeleteConfirmationControl:) withObject:self.subviews afterDelay:0];
    }

    _swipeDelete = NO;

    if(state==2){
        //Swipe to delete confirm
        _swipeDelete = YES;
    }

    if(state==3){
        //Edit state to delete confirm
    }
}

- (void)layoutSubviews{

    [super layoutSubviews];

    self.contentView.frame = CGRectMake(10, 5.0, 300, self.frame.size.height - 10);

    if(self.editing){
        self.contentView.frame = CGRectMake(40, 5.0, 270, self.frame.size.height - 10);
    }

    if(_swipeDelete){
        self.contentView.frame = CGRectMake(10, 5.0, 300, self.frame.size.height - 10);
    }
}
0
Henry