Нескучные UITableViews

dbd84f7d7e9573ff86b2626c9592f529.pngЗахотелось мне однажды сделать бесконечно скроллящиеся таблицы нескучными. Решение нашлось сразу — нужно анимировать ячейки при их первом появлении на экране. В итоге реализация оказалось достаточно простой, а полученные эффекты — очень интересными.Внимание! Под катом — тяжелые GIFки.Первым делом — объявим несколько новых свойств в .h-файле нашего контроллера:

@property (strong, nonatomic) NSNumber* cellZoomXScaleFactor; @property (strong, nonatomic) NSNumber* cellZoomYScaleFactor; @property (strong, nonatomic) NSNumber* cellZoomXOffset; @property (strong, nonatomic) NSNumber* cellZoomYOffset; @property (strong, nonatomic) NSNumber* cellZoomInitialAlpha; @property (strong, nonatomic) NSNumber* cellZoomAnimationDuration; Забегая немного вперед, расскажу, за что каждое из них будет отвечать: cellZoomXScaleFactor — масштабирование ячейки в горизонтальной плоскости, cellZoomYScaleFactor — масштабирование ячейки в вертикальной плоскости, cellZoomXOffset — сдвиг ячейки в горизонтальной плоскости, cellZoomYOffset — сдвиг ячейки в вертикальной плоскости, cellZoomInitialAlpha — прозрачность ячейки, cellZoomAnimationDuration — длительность анимации. Теперь займемся подготовкой почвы для экспериментов со значениями введенных свойств. Сначала, используя #define, создадим набор макросов: #define CELL_ZOOM_X_SCALE_FACTOR 0.5 #define CELL_ZOOM_Y_SCALE_FACTOR 0.5 #define CELL_ZOOM_X_OFFSET 0 #define CELL_ZOOM_Y_OFFSET 0 #define CELL_ZOOM_INITIAL_ALPHA 0.7 #define CELL_ZOOM_ANIMATION_DURATION 0.6 В методе -viewDidLoad свяжем макросы с объявленными свойствами: _cellZoomXScaleFactor = [NSNumber numberWithFloat: CELL_ZOOM_X_SCALE_FACTOR]; _cellZoomYScaleFactor = [NSNumber numberWithFloat: CELL_ZOOM_Y_SCALE_FACTOR]; _cellZoomXOffset = [NSNumber numberWithFloat: CELL_ZOOM_X_OFFSET]; _cellZoomYOffset = [NSNumber numberWithFloat: CELL_ZOOM_Y_OFFSET]; _cellZoomInitialAlpha = [NSNumber numberWithFloat: CELL_ZOOM_INITIAL_ALPHA]; _cellZoomAnimationDuration = [NSNumber numberWithFloat: CELL_ZOOM_ANIMATION_DURATION]; И последний штрих перед тем, как перейти непосредственно к программированию поведения ячейки — добавим переменные для хранения номера последних отображенных ячейки и секции таблицы: @implementation HomeViewController { int currentMaxDisplayedCell; int currentMaxDisplayedSection; } И, наконец-то, самое интересное. Поведение ячейки будем задавать в методе -willDisplayCell: -(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section >= currentMaxDisplayedSection && indexPath.row > currentMaxDisplayedCell) { cell.contentView.alpha = self.cellZoomInitialAlpha.floatValue; CGAffineTransform transformScale = CGAffineTransformMakeScale (self.cellZoomXScaleFactor.floatValue, self.cellZoomYScaleFactor.floatValue); CGAffineTransform transformTranslate = CGAffineTransformMakeTranslation (self.cellZoomXOffset.floatValue, self.cellZoomYOffset.floatValue); cell.contentView.transform = CGAffineTransformConcat (transformScale, transformTranslate); [tableView bringSubviewToFront: cell.contentView]; [UIView animateWithDuration: self.cellZoomAnimationDuration.floatValue delay:0 options: UIViewAnimationOptionAllowUserInteraction animations:^{ cell.contentView.alpha = 1; cell.contentView.transform = CGAffineTransformIdentity; } completion: nil]; currentMaxDisplayedCell = indexPath.row; currentMaxDisplayedSection = indexPath.section; } } Разберемся в том, что здесь происходит:1. Анимируются только ранее не показанные ячейки — здесь и приходят на помощь объявленные ранее переменные currentMaxDisplayedSection и currentMaxDisplayedCell.2. Задаем прозрачность ячейки, используя свойство cellZoomInitialAlpha. Если оно изначально будет равным 1, эффект смены прозрачности заметен не будет.3. Задаем значение свойства transform нашей ячейки с использованием функции CGAffineTransformConcat ().4. Выполняем блок анимации, в результате которого ячейка возвращается в свое исходное состояние.5. Задаем переменным currentMaxDisplayedSection и currentMaxDisplayedCell значения текущего ряда и секции.

А теперь можно приступать к экспериментам с разными значениями введенных свойств. Для удобства наборы значений буду описывать по следующему шаблону: (CELL_ZOOM_X_SCALE_FACTOR, CELL_ZOOM_Y_SCALE_FACTOR, CELL_ZOOM_X_OFFSET, CELL_ZOOM_Y_OFFSET, CELL_ZOOM_INITIAL_ALPHA, CELL_ZOOM_ANIMATION_DURATION).

Начнем со стартового набора, который мы уже успели задать (0.5, 0.5, 0, 0, 0.7, 0.6): 3eb929845edc1938a45b296801cf2d47.gif

Попробуем поиграть с прозрачностью (1, 1, 0, 0, 0.0, 0.7): 0e4242d4def1cbf9b6020f4f80f4c88e.gif

Создадим эффект выплывания из-за края экрана (1, 1, -50, 0, 1.0, 0.4): 7f917c1bf94b177d2be9fa99f75b73a6.gif

Реализуем эффект переворачивающихся карточек (1, 0.01, 0, 0, 1.0, 0.4): a262dc751613161bd3577ee69b8125a8.gif

И напоследок немного кошачьего безумия (0.01, 0.01, 100, 100, 1.0, 0.4): e1d5b996acfe678741f3aa2a57e0f708.gif

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

© Habrahabr.ru