Как анимировать UIView с ограничениями в Swift?
в моем примере, у меня есть следующие один вид:
Как вы можете видеть, он состоит из нескольких простых ограничений:
- выровнять горизонтальные и вертикальные центры,
- Высота (установлена на константу)
- ведущие и конечные пробелы (постоянное)
то, что я стремлюсь достичь, - это иметь этот красноватый/розоватый вид "войти" сверху. Традиционно, в ограничении-менее мир, я бы просто изменил кадр внутри UIView.animateWithDuration
, однако я не уверен, как я делаю подобное в мире ограничений.
чтобы повторить мой вопрос, как я могу заставить свой взгляд начать со сцены и оживить вид, летящий сверху?
Я рассмотрел возможность анимации ограничения вертикальных центров (и впоследствии вызова layoutIfNeeded
), но он не достигает желаемого эффекта.
Спасибо за вашу помощь.
5 ответов
что вы можете сделать, это добавить следующий код в ваш viewDidAppear
метод. Сначала вы делаете IBOutlet
свойство ограничения центра y вашего представления, а затем измените его постоянное значение.
self.centerYConstraint.constant = 500.0
self.view.layoutIfNeeded()
UIView.animateWithDuration(Double(0.5), animations: {
self.centerYConstraint.constant = 0
self.view.layoutIfNeeded()
})
то, что вы хотите, на самом деле довольно просто, и я подробно расскажу, как это должно быть сделано, не путаясь с приоритетами или фанки константами. Таким образом, мы можем получить анимацию, которая будет работать на любом размере экрана.
TL; DR - это то, что вам нужно настроить ограничения, а затем вызвать layoutIfNeeded внутри вашего блока анимации для анимации изменений. Для большего см. это так сообщение.
поэтому нам нужны два набора ограничений для скрытия и отображения представления. В viewDidLoad
вид будет скрыт, а затем в viewDidAppear
или там, где мы хотим, чтобы этот вид скользил.
раскадровка / XIB Setup
Итак, первое, что нужно настроить ограничения, которые не будут меняться в IB (или коде, в зависимости от того, что вам удобно). А именно; высота красного вида, а также его ведущее и конечное пространство до контейнера. Таким образом, ваши ограничения могут выглядеть так (Примечание: Я не установил ограничение ширины, но пусть ведущий и конечные пробелы определяют ширину):
теперь вы увидите, что IB предупредит вас, что нет ограничений, настроенных для позиции Y вашего вида (отсюда красные пунктирные линии)
теперь вы можете добавить верхнее пространство в ограничение контейнера и установить его как ограничение-заполнитель (флажок "удалить во время сборки"). Мы делаем это, потому что хотим контролировать, где находится вид программно.
это означает, что это ограничение не будет существовать после загрузки представления, но служит для удаления всех ваших предупреждений, поскольку вы говорите IB, что знаете, как обращаться с этим ограничением при загрузке представления.
Кодирование Времени
теперь нам нужен метод, чтобы скрыть представление, метод, чтобы показать представление. Для этого мы будем хранить ограничение позиционирования Y в представлении, а затем анимировать его. Наши файле ViewController может выглядеть так:
@IBOutlet weak var redView: UIView!
var redViewYPositionConstraint: NSLayoutConstraint?
override func viewDidLoad() {
super.viewDidLoad()
self.hideRedViewAnimated(false)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.showRedViewAnimated(true)
}
прячась
наш метод, чтобы скрыть вид, может просто удалить ограничение позиции, а затем добавить один с красным видом снизу, равным виду контроллера вида сверху:
func hideRedViewAnimated(animated: Bool) {
//remove current constraint
self.removeRedViewYPositionConstraint()
let hideConstraint = NSLayoutConstraint(item: self.redView,
attribute: .Bottom,
relatedBy: .Equal,
toItem: self.view,
attribute: .Top,
multiplier: 1,
constant: 0)
self.redViewYPositionConstraint = hideConstraint
self.view.addConstraint(hideConstraint)
//animate changes
self.performConstraintLayout(animated: animated)
}
показывает
аналогично, наше ограничение show переместит центр представления Y в центр контроллеров Y:
func showRedViewAnimated(animated: Bool) {
//remove current constraint
self.removeRedViewYPositionConstraint()
let centerYConstraint = NSLayoutConstraint(item: self.redView,
attribute: .CenterY,
relatedBy: .Equal,
toItem: self.view,
attribute: .CenterY,
multiplier: 1,
constant: 0)
self.redViewYPositionConstraint = centerYConstraint
self.view.addConstraint(centerYConstraint)
//animate changes
self.performConstraintLayout(animated: animated)
}
Методы
для полноты методов удобства я использовал выглядеть это:
func performConstraintLayout(animated animated: Bool) {
if animated == true {
UIView.animateWithDuration(1,
delay: 0,
usingSpringWithDamping: 0.5,
initialSpringVelocity: 0.6,
options: .BeginFromCurrentState,
animations: { () -> Void in
self.view.layoutIfNeeded()
}, completion: nil)
} else {
self.view.layoutIfNeeded()
}
}
func removeRedViewYPositionConstraint() {
if redViewYPositionConstraint != nil {
self.view.removeConstraint(self.redViewYPositionConstraint!)
self.redViewYPositionConstraint = nil
}
}
вы также можете проверить, виден ли красный вид, используя некоторую математику CGRect:
func isRedViewVisible() -> Bool {
return CGRectContainsPoint(self.view.bounds, self.redView.frame.origin)
}
попробуйте это:
class ViewController: UIViewController {
// red view
@IBOutlet weak var myView: UIView!
// vertical align contraint
@IBOutlet weak var verticalConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
verticalConstraint.constant = (myView.bounds.height + self.view.bounds.height)/2
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.view.layoutIfNeeded()
UIView.animateWithDuration(0.5) {
self.verticalConstraint.constant = 0
self.view.layoutIfNeeded()
}
}
}
будьте осторожны firstItem
и secondItem
порядок в ограничение. Приведенный выше код предполагает, что Superview является firstItem
:
альтернативный способ-определить два ограничения:
- ограничение выравнивания по центру Y (Superview.В. == Вид.CenterY) приоритет = 750
- Ограничение Вертикального Пространства (SuperView.Верхний== Вид.Низу) приоритет = 500
и настройка приоритет чтобы определить, какой контрапункт должен быть принят.
class ViewController: UIViewController {
// vertical align contraint
@IBOutlet weak var centerYConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
centerYConstraint.priority = 250
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.view.layoutIfNeeded()
UIView.animateWithDuration(0.5) {
self.centerYConstraint.priority = 750
self.view.layoutIfNeeded()
}
}
}
для тех, кто ищет простой анимации, подобный запрос:
для анимации скольжения вверх вам нужно использовать [...] этот CGAffineTransformMakeTranslation (x, y).
причина в том, что для слайд-анимации вам нужно сначала переместить вид выключения экрана, а затем вернуть его в исходное положение. Так что ... ваш viewDidLoad просто использовать:
yourView.transform = CGAffineTransformMakeTranslation(0, 500)
это перемещает представление с экрана, в этом случае внизу. Теперь в этот viewDidAppear вы можете показать свой вид с:
UIView.animateWithDuration(0.7, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: [], animations: { self.yourView.transform = CGAffineTransformMakeScale(1, 1) }, completion: nil)
С помощью этих строк вы можете добавить ограничения, которые вы хотите на вашем UIView и разместить его там, где вам нужно в вашем ViewController.
для меня лучший способ для animate Swift 3 & 4
self.constraint.constant = -150
UIView.animate(withDuration: 0.45) { [weak self] in
self?.view.layoutIfNeeded()
}