#ios #swift #uicollectionview #uikit
#iOS #swift #uicollectionview #uikit
Вопрос:
У меня есть UICollectionView
ограничение по краям a UIViewController
. Я хочу обновлять нижнюю вставку UICollectionView
всякий раз, когда отображается клавиатура, чтобы не скрывать элементы внизу UICollectionView
. С этой целью я настроил наблюдателя следующим образом:
override func viewDidLoad() {
super.viewDidLoad()
...
NotificationCenter.default.addObserver(self, selector: #selector(keyboard(onScreen:)), name: UIResponder.keyboardDidShowNotification, object: nil)
}
@objc func keyboard(onScreen notification: Notification?) {
let info = notification?.userInfo
let value = info?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue
guard let keyboardHeight = value?.cgRectValue.size.height else { return }
print("Keyboard height: (keyboardHeight)") // This prints out 371.0
// This does not change anything in the UI
collectionView.contentInset.bottom = keyboardHeight
collectionView.verticalScrollIndicatorInsets.bottom = keyboardHeight
// This updates the UI correctly
collectionView.contentInset.bottom = 371.0
collectionView.verticalScrollIndicatorInsets.bottom = 371.0
}
keyboard
Функция вызывается правильно всякий раз, когда появляется клавиатура, и она выводит правильную высоту, как указано в комментариях к приведенному выше коду.
Проблема в том, что если я установлю contentInset
переменную, полученную с клавиатуры Notification
, в пользовательском интерфейсе ничего не изменится. Если я жестко задам точно такое же значение (371.0), пользовательский интерфейс изменится так, как я этого хочу.
Вещи, которые я пробовал, пока безуспешно:
- Сохранение значения
keyboardHeight
в переменной класса и установкаcontentInset
для него. - Вызов
layoutIfNeeded()
иupdateConstraints()
включениеcollectionView
. - Создание локальной копии
keyboardHeight
aslet heightCopy = CGFloat(keyboardHeight)
и установка для нее вставок.
Я действительно не могу понять, почему поведение будет отличаться, когда я устанавливаю для вставок значение переменной по сравнению с тем, когда я просто жестко кодирую их на то же значение. Кто-нибудь знаком с этим поведением, которое могло бы помочь разобраться в этом?
ОБНОВЛЕНИЕ: в попытке обойти эту проблему я собирался настроить некоторую логику, чтобы решить, на какое жестко заданное значение установить вставку. Проблема в том, что если я оберну вызов collectionView.contentInset.bottom = 371.0
в оператор if, он больше не будет работать, даже если он выполняется. Чтобы уточнить:
collectionView.contentInset.bottom = 371.0 // This updates the UI correctly
В то время как:
if (some statement that is true) {
print("if passed")
collectionView.contentInset.bottom = 371.0
print("insets set")
}
не приводит к каким-либо изменениям в пользовательском интерфейсе, даже если операторы печати отображаются в выходных данных. Я чувствую, что схожу с ума здесь. Любые идеи будут высоко оценены!
ОБНОВЛЕНИЕ 2: если я добавлю вызов для прокрутки до конца UICollectionView
после установки вставки, теперь он работает. Я до сих пор не понимаю, почему на это влияет то, устанавливаете ли вы для вставки жестко заданную константу, или почему важно, переносите ли вы вызов в какое-то условное выражение, но это решило проблему для меня, на случай, если кто-нибудь еще столкнется с этим!
Ответ №1:
Одна вещь, которую вы можете попробовать, это заменить
UIResponder.keyboardDidShowNotification
с
UIResponder.keyboardWillChangeFrameNotification
потому keyboardWillChangeFrameNotification
что это всегда даст вам правильный кадр клавиатуры.
и еще одна вещь, которую следует отметить, вы должны вычесть высоту клавиатуры с помощью SafeArea bottom:
let bottomInset = keyboardHeight - view.safeAreaInsets.bottom
Комментарии:
1. К сожалению, это не решило проблему: (Еще одна вещь, которую я обнаружил, это то, что обертывание
collectionView.contentInset.bottom = 371.0
в if-statement заставляет его не работать. Код «if [оператор, который является истинным] {collectionView.contentInset.bottom = 371.0
} не обновляет пользовательский интерфейс, но удаляет оператор if, и он работает. Аналогично в инструкции switch.