Ограничение анимации представлений без анимации других представлений

#ios #swift #animation #autolayout #uikit

#iOS #swift #Анимация #автоматическое описание #uikit

Вопрос:

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

У меня есть четыре UITextFields и три с UIButtons использованием автозапуска, которые перемещаются вверх и вниз в зависимости от разных клавиатур-высота, моя проблема в том, что по какой-то причине все представления анимируются, как только загружается ViewController, а это не то, что я хочу, я хочу, чтобы они анимировались только тогда, когда высота клавиатуры равнадругое. Анимация выглядит так, как будто она анимирует все размеры и позиции представления, как только загружается ViewController.

Для управления анимацией у меня есть main constraint ( constraintKeyboardHeight ), к которому привязаны все представления для определения их вертикального положения (см. Изображение ниже).

К вашему сведению — Пожалуйста, обратите внимание, что я автоматически фокусирую одно из текстовых полей в viewDidLoad методе. Я не уверен, имеет ли это какое-то отношение к этому.

Есть идеи? Является ли это нормальным поведением при анимации представлений с ограничениями?

     override func viewDidLoad() {
     super.viewDidLoad()

     oneTextField.becomeFirstResponder()

     NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(UserInputViewController.keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil)
}


func keyboardWillShow(notification: NSNotification) {
      if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {

      keyboardHeight = keyboardSize.height   10

      UIView.animateWithDuration(3.0, animations: {
        self.constraintKeyboardHeight.constant = keyboardHeight
        self.view.layoutIfNeeded()
      })
    }
}
  

введите описание изображения здесь

Ответ №1:

Вызов self.view.layoutIfNeeded вызовет обновление макета для всего, что содержится в представлении. Если это включает в себя вложенные представления, которые вы не хотите анимировать, вам следует добавить все те, которые вы хотите анимировать, в вложенное представление контейнера. Ограничьте вложенное представление контейнера на основе клавиатуры и вызывайте layoutIfNeeded только это вложенное представление.

Я немного смущен

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

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

Редактировать: если вы не хотите анимировать при первой загрузке, вы можете добавить свойство var firstLoad = true к своему контроллеру, а затем изменить вашу клавиатуру, чтобы она отображала функцию следующим образом:

 func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo [UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        keyboardHeight = keyboardSize.height   10
        self.constraintKeyboardHeight.constant = keyboardHeight
        if firstLoad {
            view.layoutIfNeeded()
            firstLoad = false
        } else {
            UIView.animateWithDuration(3.0, animations: {
                self.view.layoutIfNeeded()
            })
        }
    }
}
  

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

Комментарии:

1. @ Connor Neville — Проблема в том, что представления анимируются немедленно, но, по-видимому, это ожидаемое поведение. Если я правильно понимаю, это self.view.layoutIfNeeded обновление всех представлений непосредственно в главном представлении из ViewController, но почему анимация применяется ко всем представлениям, положению и размеру, если я указываю только для анимации одного из ограничений? Я ожидал бы анимировать все представления, но только вверх и вниз, чтобы приспособиться к значению этого ограничения.

2. Анимация происходит немедленно, потому что клавиатура появляется немедленно, что звучит разумно для меня, но если вы не хотите анимацию при первой загрузке, вы можете установить какой-то логический флаг для первой загрузки. И да, это ожидаемое поведение layoutIfNeeded, потому что одно изменение ограничения может и часто изменяет макет всего представления.

3. @ Connor Neville — Теперь имеет смысл. Еще один вопрос: как я могу отслеживать нагрузки? Это может решить мою проблему, поскольку анимация работает так, как я ожидаю, после первой загрузки. Если это слишком сложно, я добавлю представления в одно представление, как предложено в вашем ответе. Но мне любопытно посмотреть, как это делается. Спасибо.

4. Отредактировал это в моем комментарии.

5. Вы потрясающие, большое спасибо!