#ios #objective-c #uiscrollview #uicollectionview #contentoffset
#iOS #objective-c #uiscrollview #uicollectionview #contentoffset
Вопрос:
Я пытаюсь реализовать PullDown To Search
эту функцию в своем приложении. Чтобы реализовать это, я просто изменил бит EGOTableViewPullRefresh, он работает хорошо, за исключением проблемы.
Проблема
Когда пользователь открывает приложение, должен появиться следующий экран. первоначально UICollectionView's
contentoffset
должно быть (0,0)
Если пользователь отключит просмотр коллекции, на этом этапе должен появиться следующий экран contentoffset
UICollectionView
. (0,-60)
Пользователь может выполнять поиск, вводя свой текст на экране выше. Моя проблема возникает на этом экране, как только пользователь нажимает UITextField
, чтобы ввести текст contentoffset
UICollectionView
изменений (0,-60)
(0,-110)
, и пользовательский интерфейс отключается, как показано ниже. экран. Я не уверен, почему происходит это изменение, не могли бы вы помочь мне решить эту проблему?
Комментарии:
1. Покажите нам иерархию представлений? Вы использовали
TPKeyboardAvoidingScrollView
класс из cocoacontrols.com ?2. Значит, нет красивого и простого решения для решения этой проблемы?
Ответ №1:
Возникла та же проблема. Переопределение viewWillAppear:
viewDidLoad:
и другие методы, описанные в документации, не оказали никакого эффекта, TPKeyboardAvoidingScrollView
также не помогли. После борьбы с представлением коллекции более 2 дней я пришел к действительно плохому обходному пути. Идея состоит в том, чтобы заблокировать прокрутку при появлении клавиатуры, чтобы представление вашей коллекции никуда не перемещалось, и разблокировать прокрутку после завершения анимации клавиатуры. Для этого вам следует UICollectionView
добавить в подкласс флаг, блокирующий прокрутку, подписаться на уведомления клавиатуры и правильно установить этот флаг.
Прежде чем вы реализуете это обходное решение, я должен предупредить вас, что это ОЧЕНЬ плохая идея, и вы должны попробовать все остальное, прежде чем делать это. Тем не менее, это работает…
Итак, вот что вы делаете:
-
В viewWillAppear вашего ViewController подпишитесь на уведомления о клавиатуре:
- (void)viewWillAppear:(BOOL)animated { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil]; // you custom code here }
Вы будете обрабатывать уведомления позже
-
Не забудьте отказаться от подписки на уведомления:
- (void)viewWillDisappear:(BOOL)animated { [[NSNotificationCenter defaultCenter] removeObserver:self]; // your custom code }
-
Подкласс UICollectionView и добавить флаг:
@property (nonatomic, getter=isLocked) BOOL locked;
-
Переопределить setContentOffset: в представлении вашей коллекции:
- (void)setContentOffset:(CGPoint)contentOffset { if (contentOffset.y < self.contentOffset.y amp;amp; self.isLocked) // user scrolls up contentOffset.y = self.contentOffset.y; // ignore new Y coordinate, so collection view will not scroll up [super setContentOffset:contentOffset]; }
-
В вашем ViewController создайте методы обработки клавиатуры для блокировки и разблокировки прокрутки:
- (void)keyboardWillShow:(NSNotification *)aNotification { [(LockableCollectionView *)self.collectionView setLocked:YES]; } - (void)keyboardDidShow:(NSNotification *)aNotification { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [(LockableCollectionView *)self.collectionView setLocked:NO]; }); }
Внимание!Вот небольшое разъяснение о dispatch_after
keyboardDidShow:
Если вы разблокируете прокрутку сразу после отображения клавиатуры, блокировка будет проигнорирована, а просмотр коллекции будет прокручиваться вверх. Оберните его, dispatch_after
чтобы запустить этот код через 0,3 секунды, и он работает хорошо. Вероятно, это связано с циклами выполнения и должно быть протестировано на реальных устройствах, а не в симуляторе.
Комментарии:
1. На самом деле это не сработает, если вы снова нажмете на UITextField, когда клавиатура уже на экране.
2. Я думаю, может быть правильнее не переопределять — (void)setContentOffset:(CGPoint)contentOffset и переопределять другой метод: -(void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition анимированный:(BOOL)анимированный
3. FWIW — я обнаружил, что такое поведение возникает, если вы используете код обхода клавиатуры в примере Apple как есть. Мне пришлось изменить его, чтобы учесть смещение табличного представления в момент появления клавиатуры.
Ответ №2:
проблема решена! изменение моего UICollectionViewController с помощью UIViewController и сделать мой UICollectionView подвидом моего ViewController.view.
Комментарии:
1. по какой-то причине UICollectionViewController добавляет scrollview в качестве верхнего представления в иерархии. Это было представление, которое изменялось при появлении клавиатуры.
2. У меня это не работает… Я сталкиваюсь с этой проблемой при использовании UIViewController с UICollectionView.
Ответ №3:
У меня был UITableView внутри UICollectionView, и я получил странную прокрутку. Вдохновленный @AnkH, я переопределил свой UICollectionView и добавил это в конструктор:
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow),
name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidHide),
name: NSNotification.Name.UIKeyboardDidHide, object: nil)
Также переопределите contentOffset и заблокировали все изменения contentOffset, пока клавиатура была видна. Выполнено.
Проблема в том, что UITableView уже запускает правильную настройку contentOffset для себя, но затем родительский UICollectionView добавляет свой собственный contentOffset, что приводит к катастрофическому поведению. Сначала он прокручивался слишком далеко вверх, затем слишком далеко вниз. Теперь он работает безупречно!
Ответ №4:
также не является прекрасным решением для решения этой проблемы
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: UIKeyboardWillShowNotification, object: nil)
func keyboardWillShow() {
let offset = self.collectionView!.contentOffset;
self.collectionView!.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right:0 )
self.collectionView!.contentOffset = offset
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
let offset = self.collectionView!.contentOffset;
self.collectionView!.contentInset = UIEdgeInsets(top: 60, left: 0, bottom: 0, right:0 )
self.collectionView!.contentOffset = offset
}
}
Ответ №5:
Самая простая альтернатива — использовать UIViewController и добавить свой собственный UICollectionView. Количество сумасшедших взломов, необходимых для отключения всего нежелательного поведения клавиатуры, просто безумно.
Комментарии:
1. У меня это не работает… Я сталкиваюсь с этой проблемой при использовании UIViewController с UICollectionView.