Подтвердить что ты не робот

Анимация UIView начинается с начала

Я запускаю этот код...

[UIView animateWithDuration:0.2
                      delay:0.0
                    options:UIViewAnimationOptionCurveEaseOut
                 animations:^{

                     CGAffineTransform settingsTransform = CGAffineTransformMakeTranslation(self.settingsView.frame.size.width, 0);
                     CGAffineTransform speedTransform = CGAffineTransformMakeTranslation(-self.speedView.frame.size.width, 0);

                     self.settingsView.transform = settingsTransform;
                     self.speedView.transform = speedTransform;

                 } completion:nil];

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

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

Когда я вернусь назад, используя этот код...

[UIView animateWithDuration:0.2
                      delay:0.0
                    options:UIViewAnimationOptionCurveEaseOut
                 animations:^{
                     self.settingsView.transform = CGAffineTransformIdentity;
                     self.speedView.transform = CGAffineTransformIdentity;
                 } completion:nil];

Он делает то же самое.

В результате конечное движение составляет половину желаемого преобразования, когда оно сначала скачет половину преобразования в неправильном направлении.

Я действительно не могу понять, почему это происходит?

Любые идеи.

:: EDIT::

Устранение некоторой возможной двусмысленности.

Я не пытаюсь вернуть эти взгляды туда, где они есть. Представления, которые я анимация, похожи на панель управления на краю экрана. Когда пользователь нажимает "идти" на вид, затем выдвигается с пути. Когда пользователь нажимает "стоп", панели возвращаются назад в представление.

По крайней мере, они привыкли. Поскольку включение автоматической компоновки (что мне нужно для других частей приложения), я не могу просто изменить фрейм представлений, поэтому я пошел по пути преобразования.

Этот эффект можно увидеть, вставив представление в контроллер просмотра и кнопку для запуска анимации.

Спасибо

4b9b3361

Ответ 1

ОК, просмотрев видео в WWDC, они заявляют, что одна из первых вещей, которые вы должны делать при использовании AutoLayout, - это удаление любых вызовов для setFrame.

Из-за сложности экрана я полностью удалил Auto-Layout, и теперь я использую расположение фрейма, чтобы переместить вид вокруг экрана.

Спасибо

Ответ 2

У меня была такая же проблема, поэтому вот решение, которое я придумал.

    CGAffineTransform transform = CGAffineTransformMake(1, 0, 0, 1, translation.x, translation.y);
    [UIView animateWithDuration:0.25 animations:^{
        _assetImageView.transform = transform;
        [self.view layoutIfNeeded];
    } completion:^(BOOL finished) {
    }];

Итак, я называю [self.view layoutIfNeeded]; внутри живого блока. Без этого он имеет ту же проблему, что и вы, и сначала перескакивает отрицательный перевод расстояния, а затем анимирует в нужную позицию оттуда. Я вызываю это из контроллера представления, поэтому я - подкласс класса UIViewController. В вашем случае "self.view" может не существовать, но я надеюсь, что вы получите эту идею.

Ответ 3

Ни одно из решений здесь не работало для меня... Моя анимация всегда будет пропускать. (за исключением случаев, когда это было правильно в конце другой анимации, подсказка).

Некоторые сведения:

Представление, которое делало это, имело ряд масштабов и переводилось уже в стек.

Решение:

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

    UIView.animateKeyframesWithDuration(0.4, delay: 0.0, options: [.CalculationModeCubic], animations: { () -> Void in
        //reset start point
        UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 0.01, animations: { () -> Void in
            self.element.transform = initialTransform
        })

        UIView.addKeyframeWithRelativeStartTime(0.01, relativeDuration: 0.99, animations: { () -> Void in
            self.element.transform = finalTransform
        })
    }, completion: nil)

Ответ 4

Я попросил техническую поддержку Apple по этой проблеме и получил этот ответ, так что это ошибка.

В настоящее время iOS 8 демонстрирует известную ошибку в анимациях UIKit, где трансформировать анимацию, получают неправильное значение fromValue (в первую очередь влияя на положение анимированных объектов, заставляя их казаться "прыгать", неожиданно в начале анимации).

[...]

Обходной путь до подачи потенциального исправления заключается в том, чтобы Core Animation API для кодирования анимации.

Ответ 5

У ваших настроекView или speedView уже есть преобразование, применяемое до этой анимации?

Если преобразования для этих представлений не являются преобразованием идентичности (например, CGAffineTransformIdentity, aka no transform), вы не можете получить доступ к своим свойствам .frame.

Свойства фрейма UIViews недействительны, если к ним применено преобразование. Вместо этого используйте "границы".

Ответ 6

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

[UIView animateWithDuration:0.2
                      delay:0.0
                    options:UIViewAnimationOptionCurveEaseOut|UIViewAnimationOptionLayoutSubviews
                 animations:^{
                     self.settingsView.transform = CGAffineTransformIdentity;
                     self.speedView.transform = CGAffineTransformIdentity;
                 } completion:nil];

Вот пример кода, который я использовал для тестирования с помощью простого шаблона контроллера:

myviewcontroller.m:

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.animatedView = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 160, 80)];
    self.animatedView.backgroundColor = [UIColor yellowColor];

    [UIView animateWithDuration:0.2
                          delay:0.0
                        options:UIViewAnimationOptionCurveEaseOut|UIViewAnimationOptionLayoutSubviews
                     animations:^{
                         CGAffineTransform settingsTransform = CGAffineTransformMakeTranslation(self.animatedView.frame.size.width, 0);

                         self.animatedView.transform = settingsTransform;

                     }
                     completion:nil];
    self.buttonToTest = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    self.buttonToTest.frame = CGRectMake(90, 20, 80, 40);
    [self.buttonToTest setTitle:@"Click Me!" forState:UIControlStateNormal];
    [self.buttonToTest addTarget:self action:@selector(buttonClicked) forControlEvents:UIControlEventTouchUpInside];

    // set-up view hierarchy
    [self.view addSubview:self.buttonToTest];
    [self.view addSubview: self.animatedView];

}

- (void) buttonClicked
{
    [UIView animateWithDuration:.2
                          delay:0.0
                        options:UIViewAnimationOptionCurveEaseOut|UIViewAnimationOptionBeginFromCurrentState|UIViewAnimationOptionLayoutSubviews
                     animations:^{
                         self.animatedView.transform = CGAffineTransformIdentity;

                     }
                     completion:nil];
}

Ответ 7

У меня была эта проблема, и я решил ее:

  • Скрытие исходного вида
  • Добавить временное представление, которое копирует вид, который вы хотите оживить
  • Выполните анимацию, которая теперь будет как предполагалось
  • Удалить временное представление и отобразить исходное представление с конечным состоянием

Надеюсь, что это поможет.

Ответ 8

Здесь улучшенная версия Андреаса отвечает Главное различие заключается в том, что вы можете указать только один ключевой кадр и получить меньше кода

UIView.animateKeyframes(withDuration: animationDuration, delay: 0.0, options: [], animations: {
  UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 1.0, animations: {
    animatedView.transform = newTransform
    })
  }, completion: nil)