Пытаясь оживить ограничение в быстром
У меня есть UITextField, который я хочу увеличить ширину при нажатии. Я установил ограничения и убедился, что ограничение слева имеет более низкий приоритет, чем тот, который я пытаюсь оживить с правой стороны.
Вот код, который я пытаюсь использовать.
// move the input box
UIView.animateWithDuration(10.5, animations: {
self.nameInputConstraint.constant = 8
}, completion: {
(value: Bool) in
println(">>> move const")
})
Это работает, но, похоже, это происходит мгновенно, и, похоже, нет никакого движения. Я попытался установить его на 10 секунд, чтобы убедиться, что у меня ничего не пропало, но я получил те же результаты.
nameInputConstraint - это имя ограничения, которое я управляю перетаскиванием, чтобы подключиться к моему классу из IB.
Спасибо за вашу помощь заранее!
Ответы
Ответ 1
Вам необходимо сначала изменить ограничение, а затем анимировать обновление.
self.nameInputConstraint.constant = 8
Swift 2
UIView.animateWithDuration(0.5) {
self.view.layoutIfNeeded()
}
Swift 3, 4, 5
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
Ответ 2
SWIFT 4.x:
self.mConstraint.constant = 100.0
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
Пример с завершением:
self.mConstraint.constant = 100
UIView.animate(withDuration: 0.3, animations: {
self.view.layoutIfNeeded()
}, completion: {res in
//Do something
})
Ответ 3
Очень важно указать, что view.layoutIfNeeded()
применяется только к view.layoutIfNeeded()
представления.
Поэтому для анимации ограничения представления важно вызвать его в суперпредставлении "просмотр- анимация" следующим образом:
topConstraint.constant = heightShift
UIView.animate(withDuration: 0.3) {
// request layout on the *superview*
self.view.superview?.layoutIfNeeded()
}
Пример для простого макета выглядит следующим образом:
class MyClass {
/// Container view
let container = UIView()
/// View attached to container
let view = UIView()
/// Top constraint to animate
var topConstraint = NSLayoutConstraint()
/// Create the UI hierarchy and constraints
func createUI() {
container.addSubview(view)
// Create the top constraint
topConstraint = view.topAnchor.constraint(equalTo: container.topAnchor, constant: 0)
view.translatesAutoresizingMaskIntoConstraints = false
// Activate constaint(s)
NSLayoutConstraint.activate([
topConstraint,
])
}
/// Update view constraint with animation
func updateConstraint(heightShift: CGFloat) {
topConstraint.constant = heightShift
UIView.animate(withDuration: 0.3) {
// request layout on the *superview*
self.view.superview?.layoutIfNeeded()
}
}
}
Ответ 4
С Swift 5 и iOS 12.3, в соответствии с вашими потребностями, вы можете выбрать один из 3 следующих способов для решения вашей проблемы.
# 1. Использование UIView
animate(withDuration:animations:)
метод класса
animate(withDuration:animations:)
имеет следующее объявление:
Анимируйте изменения в одном или нескольких представлениях, используя указанную продолжительность.
class func animate(withDuration duration: TimeInterval, animations: @escaping () -> Void)
Код Playground ниже показывает возможную реализацию animate(withDuration:animations:)
для анимации изменения константы ограничения Auto Layout.
import UIKit
import PlaygroundSupport
class ViewController: UIViewController {
let textView = UITextView()
lazy var heightConstraint = textView.heightAnchor.constraint(equalToConstant: 50)
override func viewDidLoad() {
view.backgroundColor = .white
view.addSubview(textView)
textView.backgroundColor = .orange
textView.isEditable = false
textView.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
textView.translatesAutoresizingMaskIntoConstraints = false
textView.topAnchor.constraint(equalToSystemSpacingBelow: view.layoutMarginsGuide.topAnchor, multiplier: 1).isActive = true
textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
textView.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor).isActive = true
heightConstraint.isActive = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(doIt(_:)))
textView.addGestureRecognizer(tapGesture)
}
@objc func doIt(_ sender: UITapGestureRecognizer) {
heightConstraint.constant = heightConstraint.constant == 50 ? 150 : 50
UIView.animate(withDuration: 2) {
self.view.layoutIfNeeded()
}
}
}
PlaygroundPage.current.liveView = ViewController()
# 2. Использование UIViewPropertyAnimator
init(duration:curve:animations:)
инициализатор и startAnimation()
init(duration:curve:animations:)
имеет следующее объявление:
Инициализирует аниматор с помощью встроенной временной кривой UIKit.
convenience init(duration: TimeInterval, curve: UIViewAnimationCurve, animations: (() -> Void)? = nil)
Код Playground ниже показывает возможную реализацию init(duration:curve:animations:)
и startAnimation()
для анимации изменения константы ограничения Auto Layout.
import UIKit
import PlaygroundSupport
class ViewController: UIViewController {
let textView = UITextView()
lazy var heightConstraint = textView.heightAnchor.constraint(equalToConstant: 50)
override func viewDidLoad() {
view.backgroundColor = .white
view.addSubview(textView)
textView.backgroundColor = .orange
textView.isEditable = false
textView.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
textView.translatesAutoresizingMaskIntoConstraints = false
textView.topAnchor.constraint(equalToSystemSpacingBelow: view.layoutMarginsGuide.topAnchor, multiplier: 1).isActive = true
textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
textView.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor).isActive = true
heightConstraint.isActive = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(doIt(_:)))
textView.addGestureRecognizer(tapGesture)
}
@objc func doIt(_ sender: UITapGestureRecognizer) {
heightConstraint.constant = heightConstraint.constant == 50 ? 150 : 50
let animator = UIViewPropertyAnimator(duration: 2, curve: .linear, animations: {
self.view.layoutIfNeeded()
})
animator.startAnimation()
}
}
PlaygroundPage.current.liveView = ViewController()
# 3. Использование UIViewPropertyAnimator
runningPropertyAnimator(withDuration:delay:options:animations:completion:)
метод класса
runningPropertyAnimator(withDuration:delay:options:animations:completion:)
имеет следующую декларацию:
Создает и возвращает объект аниматора, который сразу же запускает анимацию.
class func runningPropertyAnimator(withDuration duration: TimeInterval, delay: TimeInterval, options: UIViewAnimationOptions = [], animations: @escaping () -> Void, completion: ((UIViewAnimatingPosition) -> Void)? = nil) -> Self
Код Playground ниже показывает возможную реализацию runningPropertyAnimator(withDuration:delay:options:animations:completion:)
для анимации изменения константы ограничения Auto Layout.
import UIKit
import PlaygroundSupport
class ViewController: UIViewController {
let textView = UITextView()
lazy var heightConstraint = textView.heightAnchor.constraint(equalToConstant: 50)
override func viewDidLoad() {
view.backgroundColor = .white
view.addSubview(textView)
textView.backgroundColor = .orange
textView.isEditable = false
textView.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
textView.translatesAutoresizingMaskIntoConstraints = false
textView.topAnchor.constraint(equalToSystemSpacingBelow: view.layoutMarginsGuide.topAnchor, multiplier: 1).isActive = true
textView.leadingAnchor.constraint(equalTo: view.layoutMarginsGuide.leadingAnchor).isActive = true
textView.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor).isActive = true
heightConstraint.isActive = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(doIt(_:)))
textView.addGestureRecognizer(tapGesture)
}
@objc func doIt(_ sender: UITapGestureRecognizer) {
heightConstraint.constant = heightConstraint.constant == 50 ? 150 : 50
UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 2, delay: 0, options: [], animations: {
self.view.layoutIfNeeded()
})
}
}
PlaygroundPage.current.liveView = ViewController()
Ответ 5
В моем случае я только обновил пользовательский вид.
// DO NOT LIKE THIS
customView.layoutIfNeeded() // Change to view.layoutIfNeeded()
UIView.animate(withDuration: 0.5) {
customViewConstraint.constant = 100.0
customView.layoutIfNeeded() // Change to view.layoutIfNeeded()
}
Ответ 6
Смотреть это
Видео говорит, что вам нужно просто добавить self.view.layoutIfNeeded()
как self.view.layoutIfNeeded()
ниже:
UIView.animate(withDuration: 1.0, animations: {
self.centerX.constant -= 75
self.view.layoutIfNeeded()
}, completion: nil)