Сбой анимации смещения контента

У меня есть анимация, которая запускается при срабатывании распознавателя жестов (двойное нажатие):

[UIView animateWithDuration:0.3 animations:^{
  _scrollView.contentOffset              = CGPointMake(x, y);
  _scrollViewContentView.frame           = someFrame;
  _scrollViewContentView.layer.transform = 
       CATransform3DMakeScale(1.f/_zoomScale, 1.f/_zoomScale, 1.f);            
}];

Это работает хорошо, за исключением одного случая: если scrollViewWillBeginDecelerating Метод делегата не вызывается перед выполнением анимации (просто с помощью перетаскивания моего прокрутки).

я просто scrollViewDidEndDragging Вызов метода. Я могу подождать 20 секунд, а затем воспроизвести мою анимацию. Это будет играть правильно, за исключением моего contentOffset,

Сами методы делегата ничего не делают, они были добавлены только для того, чтобы увидеть, где может быть проблема.

Понятия не имею почему.

Изменить: вот видео моей проблемы. Фаза 1: прокрутка с замедлением и фаза 2 без. Посмотрите окончательную позицию. Фаза 1 правильная, но не фаза

4 ответа

Пытаться:

[_scrollView setContentOffSet:CGPointMake(x, y) animated:YES];

за пределами блока анимации. Я не верю, что contentOffSet можно анимировать с помощью блока анимации UIView.

Изменить: вместо:

_scrollview.contentOffSet = CGPointMake(x, y);

пытаться:

_scrollview.bounds = CGRectMake(x, y, CGRectGetWidth(scrollview.bounds), CGRectGetHeight(scrollview.bounds));

Я подозреваю, что x в этой строке может вызывать эффект, который вы видите:

_scrollView.contentOffset              = CGPointMake(x, y);

Что это такое? Я думаю, что вы должны попробовать заменить это на CGPointMake(0, y) и посмотреть, не вызывает ли это поле белого каждый раз.

Я рассуждаю так:

1) чтобы создать эффект отскакивания, который не выходит за рамки изображения (не показывает белый фон), вы должны установить _scrollView"s contentSize.width меньше, чем фактический размер изображения.

2) чтобы позволить некоторую прокрутку, вы установили contentSize.width больше ширины _scrollView

3) вы центрировали изображение внутри _scrollView относительно размера его contentSize

4) при анимации вы, вероятно, устанавливаете рамку с предварительно вычисленной координатой x, чтобы расположить изображение в левом размере, потому что без этого CATransform3DMakeScale просто оставить изображение в центре (кстати, зачем использовать CATransform3DMakeScaleкогда можно было просто поменять размер в кадре?)

5) в видео при первом запуске анимации contentOffset.x к максимальному значению (потому что вы перетаскиваете влево, увеличивая таким образом смещение контента, а представление прокрутки возвращается к максимальному смещению контента, которое не выходит за пределы размера контента)

6) в видео при запуске анимации во второй раз, у вас есть contentOffset.x с меньшим значением, потому что вы тянете вправо, уменьшая его

7) когда анимация закончится, у вас останется тот же размер контента для scrollView и, следовательно, тот же объем прокрутки. Если у вас есть contentOffset.x при максимальном значении изображение будет больше слева, если у вас файл contentOffset.x с меньшим значением - изображение будет справа

8) если х в _scrollView.contentOffset = CGPointMake(x, y); относится к фактическому смещению содержимого перед анимацией, тогда имеет смысл, что изображение появляется больше слева в первом случае и больше справа во втором случае.

Если я прав, то вот как это можно решить:

a) Если вы хотите, чтобы изображение всегда отображалось в определенной позиции x, обязательно установите постоянный contentOffset в анимации.

б) настроить код расчета кадра (someFrame) источник в соответствии с contentOffset, к которому вы будете анимировать (похоже, что теперь он работает только с максимальным contentOffset.x).

c) Если после анимации вы не хотите, чтобы содержимое можно было прокручивать, обязательно установите _scrollView.contentSize = _scrollview.bounds.size; в блоке анимации.

Возможно, попробуйте использовать базовую анимацию, а не анимацию UIView. Это не будет иметь значения, если причина, по которой вы столкнетесь с проблемами, заключается в том, что все анимации удаляются со слоя, но если это связано с -[removeAnimationForKey:@"bounds"]это может быть победителем.

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"bounds"];
animation.fromValue = [NSValue valueWithCGRect:_scrollView.layer.bounds];
animation.toValue = [NSValue valueWithCGRect:(CGRect){ .origin = CGPointMake(x,y), .size = scrollView.layer.bounds.size }];
[scrollView.layer addAnimation:animation forKey:@"myCustomScroll"];
scrollView.layer.bounds = (CGRect){ .origin = CGPointMake(x,y), .size = scrollView.layer.bounds.size };

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

Я не уверен, что полностью понимаю вашу проблему (возможно, вы можете попытаться объяснить, чего вы хотите достичь в этой анимации?). В любом случае, возможно, попробуйте это вместо использования setContentOffset:

CGRect *rect = CGRectMake(x, y, 0, 0);
[_scrollView scrollRectToVisible:rect animated:YES];
Другие вопросы по тегам