Анимация 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::
Устранение некоторой возможной двусмысленности.
Я не пытаюсь вернуть эти взгляды туда, где они есть. Представления, которые я анимация, похожи на панель управления на краю экрана. Когда пользователь нажимает "идти" на вид, затем выдвигается с пути. Когда пользователь нажимает "стоп", панели возвращаются назад в представление.
По крайней мере, они привыкли. Поскольку включение автоматической компоновки (что мне нужно для других частей приложения), я не могу просто изменить фрейм представлений, поэтому я пошел по пути преобразования.
Этот эффект можно увидеть, вставив представление в контроллер просмотра и кнопку для запуска анимации.
Спасибо
Ответы
Ответ 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)