Сбой анимации смещения контента
У меня есть анимация, которая запускается при срабатывании распознавателя жестов (двойное нажатие):
[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];