UIScrollview setContentOffset с нелинейной анимацией?
Я пытаюсь воспроизвести гладкую анимацию scrollview с включенным пейджингом, когда вы действительно переходите к следующей странице. Кажется, это UIViewAnimationCurveEaseInOut
, но мне нужно иметь кнопку "следующая страница" и программно прокручивать прокрутку.
Вот мой код:
-(void) scrollToPage:(int)page
{
UIScrollView *scrollView = contentView;
CGPoint offset = CGPointMake(scrollView.bounds.size.width * page, scrollView.contentOffset.y);
[scrollView setContentOffset:offset animated: YES];
[self pageControlUpdate];
}
-(void) scrollToNextPage
{
[self scrollToPage:(pageControl.currentPage + 1)];
}
Я не могу воспроизвести гладкость UIViewAnimationCurveEaseInOut
,
либо с setContentOffset
, либо с помощью scrollRectToVisible
...
он переходит на следующую страницу с уродливой линейной анимацией
Я даже пытался анимировать его вручную:
[UIView animateWithDuration:.5 delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
scrollView.contentOffset = offset;
} completion:^(BOOL finished) { } ];
Где я ошибаюсь?
Ответы
Ответ 1
Каждый раз, когда вы создаете свои собственные анимации, вам нужно передать НЕТ в качестве параметра animated:
:
- (void)scrollToPage:(int)page
{
UIScrollView *scrollView = contentView;
CGPoint offset = CGPointMake(scrollView.bounds.size.width * page,
scrollView.contentOffset.y);
[UIView animateWithDuration:.5
delay:0
options:UIViewAnimationCurveEaseInOut
animations:^{
[scrollView setContentOffset:offset animated:NO];
} completion:nil];
[self pageControlUpdate];
}
Ответ 2
Используя общедоступные API, я не считаю, что в настоящее время это возможно. Предполагая, что вам не нужно взаимодействие с пользователем во время анимации, вам лучше будет анимировать позицию ваших подтекстов UIScrollView
(т.е. Содержимого прокрутки), а затем настроить contentOffset
без анимации на завершение. Вы можете сделать это так:
- (void) scrollToPage:(int)page {
UIScrollView *scrollView = contentView;
scrollView.userInteractionEnabled = NO;
CGPoint offset = CGPointMake(scrollView.bounds.size.width * page, scrollView.contentOffset.y);
CGFloat delta = offset.x - scrollView.contentOffset.x;
__block int animationCount = 0;
for (UIView *view in scrollView.subviews) {
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
animationCount++;
CGRect frame = view.frame;
frame.origin.x -= delta;
view.frame = frame;
} completion:^(BOOL finished) {
animationCount--;
if (animationCount == 0) {
scrollView.contentOffset = offset;
for (UIView *view in scrollView.subviews) {
CGRect frame = view.frame;
frame.origin.x += delta;
view.frame = frame;
}
scrollView.userInteractionEnabled = YES;
}
}];
}
}
Я могу подтвердить, что это работает, как и ожидалось, я сам тестировал его.
Ответ 3
[UIView animateWithDuration:(Animation_Duration)
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[scroll setContentOffset:CGPointMake(PointX, PointY) animated:NO];
}
completion:^(BOOL finished){}];`
Ответ 4
Этот класс полностью спас мне жизнь:
MOScroll на GitHub.com
Он имеет
- (void)setContentOffset:(CGPoint)contentOffset
withTimingFunction:(CAMediaTimingFunction *)timingFunction
duration:(CFTimeInterval)duration;
Также как частный API, но со всеми общедоступными методами и математикой.