Автозапуск, UIDynamics и анимация

Я новичок в автоматическом макете, и я смущен о том, как анимировать представления.

Я много читаю, и я знаю, что вы должны придерживаться ограничений, редактировать их и обернуть layoutIfNeeded в блок анимации UIView.

Но когда дело доходит до этого, я немного теряюсь. Мне бы хотелось, чтобы кто-нибудь мог объяснить мне, как эта анимация выполняется, например.

Я думаю, что он, вероятно, использует UIPanGestureRecognizer, чтобы изменить constant ведущего пространства на ограничение контейнера, но он, вероятно, использует UIDynamics (для эффекта отскока справа?).

Ответ 1

Хорошо, подобное поведение может быть достигнуто с помощью UIPanGestureRecognizer + [UIView animateWithDuration:animations:]. Да, вы устанавливаете ведущее ограничение пространства и меняете его в соответствии с состоянием UIPanGestureRecognizer. Помните, что вам нужно только установить конечные ограничения (определить конечную позицию ползунка). Промежуточные позиции анимации рассчитаны для вас. Для ползунка у нас есть левое положение по умолчанию и активированное среднее положение.

Для вращения просмотра мы можем использовать свойство transform UIView.

Ограничения автоопределения в IB:

Autolayout constraints in IB

Настройка параметров анимации (UIViewAnimationOptionCurveEaseOut анимационная кривая) может дать ощущение эффекта отскока. UIPanGestureRecognizer code (опустить объявление переменных экземпляра, потому что их имена не требуют пояснений):

- (IBAction)onPan:(UIPanGestureRecognizer*)sender
{
    switch (sender.state) {
        case UIGestureRecognizerStateBegan:
            _startOffset = self.leadingSpace.constant;
            _maxOffset = self.slider.superview.frame.size.width
                - kHorizontalPadding
                - self.slider.frame.size.width;
            break;

        case UIGestureRecognizerStateChanged: {
            CGFloat offset = _startOffset + [sender translationInView:self.slider.superview].x;
            offset = MIN(offset, _maxOffset);

            self.leadingSpace.constant = offset;
            break;
        }

        case UIGestureRecognizerStateEnded: {
            CGFloat offset = _startOffset + [sender translationInView:sender.view.superview].x;
            UIColor *bgColor = [UIColor lightGrayColor];
            CGFloat rotation = 0;

            if (offset < _maxOffset) {
                offset = kHorizontalPadding;
            }
            else {
                offset = (_maxOffset + kHorizontalPadding)/2;
                bgColor = [UIColor redColor];
                rotation = M_PI_2;
            }

            self.leadingSpace.constant = offset;

            [UIView
             animateWithDuration:.5
             delay:0
             options:UIViewAnimationOptionCurveEaseOut
             animations:^{
                 [self.slider layoutIfNeeded];
                 self.slider.backgroundColor = bgColor;
                 self.slider.transform = CGAffineTransformMakeRotation(rotation);
             } completion:nil];

            break;
        }

        default:
            break;
    }
}

Результат анимации с помощью UIViewAnimationOptionCurveLinear (симулятор захвата):

Animation result

Результат анимации с помощью UIViewAnimationOptionCurveEaseOut (симулятор захвата):

Animation result

UIDynamics

С UIDynamics все усложняется. Хорошей отправной точкой является Ray Wenderlich UIKit Dynamics Tutorial.

Для прыгающего слайдера мы можем добавить следующие типы поведения:

  • UIGravityBehavior, который тянет ползунок в исходное положение. Нам нужно изменить свойство angle, чтобы направить силу силы тяжести влево.
  • UICollisionBehavior, который определяет левый и правый края разрешенных движений. translatesReferenceBoundsIntoBoundary свойство будет полезно, если рассматривать родительское представление как границу. Также нам нужно добавить дополнительную границу, чтобы остановить слайдер посередине, используя addBoundaryWithIdentifier:fromPoint:toPoint (или путь безье).
  • UIDynamicItemBehavior изменить свойства elasticy и, возможно, resistance для настройки отказов и ускорения соответственно.
  • Возможно UIPushBehavior в сочетании с распознавателем velocityInView: для указания скорости ползунка, когда пользователь отпускает слайдер
  • Возможно UISnapBehavior в качестве альтернативы UIGravityBehavior