Обновление: Хотя мне все же хотелось бы это решить, я перешел на animateWithDuration:delay:options:animations:completion:
, и он работает намного приятнее. В нем отсутствует тот хороший "отскок" в конце, который предоставляет spring, но по крайней мере он управляемый.
Я пытаюсь создать хороший пользовательский интерфейс, ориентированный на жесты, для iOS, но я сталкиваюсь с некоторыми трудностями, получая значения, чтобы привести к приятному естественному ощущению.
Я использую animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:
, потому что мне нравится оживленная анимация spring. Я инициализирую аргумент velocity
со скоростью, заданной распознавателем жестов в завершенном состоянии. Проблема в том, что, если я буду достаточно быстро капать и отпустить, скорость в тысячах, и мой взгляд заканчивается, пролетая прямо с экрана, а затем отскакивает назад и вперед с такой головокружительной мести.
Я даже корректирую продолжительность анимации относительно расстояния, которое нужно перемещать, поэтому, если требуется только несколько пикселей, анимация займет меньше времени. Это, однако, не решило проблему. Он все еще заканчивается гайками.
То, что я хочу сделать, - это представление должно начинаться с любой скорости, в которую пользователь перетаскивает его, но он должен быстро замедляться при достижении целевой точки и только немного отскакивать в конце (как это происходит, если скорость что-то разумное).
Интересно, правильно ли я использую этот метод или значения. Вот какой код, чтобы показать, что я делаю. Любая помощь будет оценена!
- (void)handlePanGesture:(UIPanGestureRecognizer*)gesture {
CGPoint offset = [gesture translationInView:self.view];
CGPoint velocity = [gesture velocityInView:self.view];
NSLog(@"pan gesture state: %d, offset: %f velocity: %f", gesture.state, offset.x, velocity.x);
static CGFloat initialX = 0;
switch ( gesture.state ) {
case UIGestureRecognizerStateBegan: {
initialX = self.blurView.x;
break; }
case UIGestureRecognizerStateChanged: {
self.blurView.x = initialX + offset.x;
break; }
default:
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateEnded: {
if ( velocity.x > 0 )
[self openMenuWithVelocity:velocity.x];
else
[self closeMenuWithVelocity:velocity.x];
break; }
}
}
- (void)openMenuWithVelocity:(CGFloat)velocity {
if ( velocity < 0 )
velocity = 1.5f;
CGFloat distance = -40 - self.blurView.x;
CGFloat distanceRatio = distance / 260;
NSLog(@"distance: %f ratio: %f", distance, distanceRatio);
[UIView animateWithDuration:(0.9f * distanceRatio) delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:velocity options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.blurView.x = -40;
} completion:^(BOOL finished) {
self.isMenuOpen = YES;
}];
}