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

Как оживить UIView с ограничениями в Swift?

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

enter image description here

Как вы можете видеть, он состоит из нескольких простых ограничений:

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

То, что я хочу достичь, - это красноватое/розоватое представление "прийти" сверху. Традиционно, в мире с ограниченными условиями, я бы просто изменил фрейм внутри UIView.animateWithDuration, однако я не уверен, как я делаю подобное в мире ограничений.

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

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

Спасибо за вашу помощь.

4b9b3361

Ответ 1

Что вы можете сделать, так это добавить следующий код в свой метод viewDidAppear. Сначала вы создаете свойство IBOutlet вашего ограничения Y центра просмотра и затем изменяете его постоянное значение.

self.centerYConstraint.constant = 500.0
self.view.layoutIfNeeded()

UIView.animateWithDuration(Double(0.5), animations: {
        self.centerYConstraint.constant = 0
        self.view.layoutIfNeeded()
    })

Ответ 2

То, что вы хотите, на самом деле довольно просто, и я подробно расскажу, как это нужно делать, не вникая в приоритеты или фанковые константы. Таким образом, мы можем получить анимацию, которая будет работать на любом размере экрана.

TL; DR - это то, что вам нужно настроить свои ограничения, а затем вызвать layoutIfNeeded внутри вашего блока анимации, чтобы анимировать изменения. Для получения дополнительной информации см. Этот SO-сообщение.

Итак, нам нужны два набора ограничений для скрытия и отображения представления. В viewDidLoad вид будет скрыт, а затем в viewDidAppear или везде, где мы хотим, чтобы этот просмотр скользил.

Установка раскадровки /XIB

Итак, сначала нужно настроить ограничения, которые не будут меняться в IB (или код, в зависимости от того, что вам удобно). А именно, высота красного изображения и его ведущее и конечное пространство для контейнера. Таким образом, ваши ограничения могут выглядеть так ( note: Я не задал ограничение ширины, но пусть начальное и конечное пространства определяют ширину):

Constraints

Теперь вы увидите, что IB предупредит вас, что нет ограничения, настроенного для позиции Y вашего вида (отсюда красные пунктирные линии)

View with warnings

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

enter image description here

Это означает, что это ограничение не будет существовать после загрузки представления, но служит для удаления всех ваших предупреждений, когда вы сообщаете 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)
}

Ответ 3

Попробуйте следующее:

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:

screenshot


Альтернативный способ заключается в определении двух ограничений:

  • Ограничение выравнивания по центру Y (Superview.CenterY == View.CenterY) priority = 750
  • Вертикальное ограничение пространства (SuperView.Top == View.Bottom) priority = 500

screenshot

И настройте приоритет, чтобы определить, какой из них следует принять.

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()
        }
    }

}

Ответ 4

Для тех, кто ищет простую анимацию, такую ​​как запрос, отметьте мой пример в GitHub о том, как анимация UIview в Swift.

Я надеюсь, что это может помочь кому-то, потому что первоначальный запрос посмотрит на третью анимацию (анимация "Слайд вверх" ).

Для слайд-анимации вам необходимо использовать [...] 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.

Ответ 5

Для меня лучший способ для анимации Swift 3 и 4

self.constraint.constant = -150

UIView.animate(withDuration: 0.45) { [weak self] in
    self?.view.layoutIfNeeded()
}