UIScrollView не возвращается в ту же позицию ⇐ IOS
UIScrollView не возвращается в ту же позицию
У меня очень неприятная проблема с деталями, которую я не знаю, как правильно решить с помощью UIScrollView.
У меня есть базовый класс UIViewController со ScrollView и ContentView, настроенными следующим образом:
импортировать UIKit /* Контроллер, используемый там, где контент можно будет прокручивать, как только он выйдет за пределы экрана. например, когда отображается клавиатура. Этот контроллер автоматически будет избегать использования клавиатуры, если это необходимо. Для правильной прокрутки вам необходимо либо создать ограничение между последним дочерним представлением и нижнюю часть contentView или ограничьте высоту contentView с низким/средним приоритетом. При использовании этого в качестве родительского контроллера используйте свойство «contentView» вместо «view». при добавлении контента. */ класс ScrollableContentController: KeyboardAwareViewController { частный класс ScrollView: UIScrollView { удобство init() { self.init(кадр: .init()) TranslationsAutoresizingMaskIntoConstraints = false клавиатураDismissMode = .interactive задержкиContentTouches = ложь } переопределить функцию touchesShouldCancel (в представлении: UIView) -> Bool { true } } позвольте прокрутке: UIScrollView = ScrollView() пусть contentView = UIView() переопределить функцию loadView() { супер.loadView() contentView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(scrollView) ScrollView.addSubview(contentView) NSLayoutConstraint.activate([ ScrollView.frameLayoutGuide.topAnchor.constraint(equalTo: view.topAnchor), ScrollView.frameLayoutGuide.leadingAnchor.constraint(equalTo: view.leadingAnchor), ScrollView.frameLayoutGuide.trailingAnchor.constraint(equalTo: view.trailingAnchor), ScrollView.frameLayoutGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor), ]) NSLayoutConstraint.activate([ contentView.topAnchor.constraint(equalTo: ScrollView.contentLayoutGuide.topAnchor), contentView.leadingAnchor.constraint(equalTo: ScrollView.contentLayoutGuide.leadingAnchor), contentView.trailingAnchor.constraint(equalTo: ScrollView.contentLayoutGuide.trailingAnchor), contentView.bottomAnchor.constraint(equalTo: ScrollView.contentLayoutGuide.bottomAnchor), contentView.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor), ]) ScrollView.delegate = сам } переопределить func KeyboardWillChangeFrame (_ кадр: CGRect) { если isTopViewController { ScrollView.contentInset.bottom = кадр.высота } } } До сих пор я использовал этот класс, ограничивая нижнюю часть моего нижнего представления нижней частью contentView. Это приведет к тому, что прокрутка будет доступна только в том случае, если contentSize превысит размер прокрутки. Однако в последнее время меня начали раздражать просмотры, которые не отскакивают из-за небольшого размера. Например, если вы перемещаетесь по приложению «Системные настройки», вы заметите, что все представления будут отображаться независимо от того, нужно это или нет. Возможно, это обычно делается с помощью UICollectionView или UITableView, но я ненавижу использовать их, когда у меня небольшое и предопределенное количество представлений, поэтому я настаиваю на использовании вместо этого UIScrollView. Я подумал, что, вероятно, смогу имитировать это поведение подпрыгивания, установив для ContentSize значение как минимум на 0,5 пикселя выше моей высоты SafeArea, например:
let height = view.safeAreaLayoutGuide.layoutFrame.size.height.roundUpToNearestHalf() contentView.snp.updateConstraints { сделать в make.height.equalTo(max(section.maxY, высота)).priority(500) } И это прекрасно работает! Ну, почти.. Очень неприятная проблема заключается в том, что когда я прокручиваю вниз и он возвращается обратно вверх, он возвращается в исходное положение, которое на моем телефоне и в моем случае оказывается (0.0, -97.66666666666667). Я получаю эту информацию в методе делегата ScrollViewDidEndDecelering. Однако когда я прокручиваю вверх и он отскакивает обратно вниз, он приземляется на (0.0, -97.33333333333333). Это очень трудно увидеть, но нижняя граница навигационного представления никогда не исчезает полностью, и это действительно раздражает, когда вы ее видите. Эта проблема не существует в приложении «Системные настройки», и вы увидите, что нижняя граница панели навигации полностью исчезнет.
Как решить эту проблему без использования Table или CollectionView? Кроме того, разумно ли вообще, чтобы contentOffset был отрицательным, или я с самого начала все сделал совершенно неправильно?
Я обошел это прямо сейчас, сохранив начальное смещение содержимого в viewLayoutMarginsDidChange, а затем в ScrollViewDidEndDecelerating проверяя, если разница меньше 1, просто установив его в исходное положение, например:
if abs(scrollView.contentOffset.y - InitialContentOffset.y) < 1 { ScrollView.setContentOffset(initialContentOffset, анимированный: true) } Но я надеюсь, что есть лучшее решение — это хак! Кстати, разве начальное смещение содержимого не должно быть равно нулю?
У меня очень неприятная проблема с деталями, которую я не знаю, как правильно решить с помощью UIScrollView.
У меня есть базовый класс UIViewController со ScrollView и ContentView, настроенными следующим образом:
импортировать UIKit /* Контроллер, используемый там, где контент можно будет прокручивать, как только он выйдет за пределы экрана. например, когда отображается клавиатура. Этот контроллер автоматически будет избегать использования клавиатуры, если это необходимо. Для правильной прокрутки вам необходимо либо создать ограничение между последним дочерним представлением и нижнюю часть contentView или ограничьте высоту contentView с низким/средним приоритетом. При использовании этого в качестве родительского контроллера используйте свойство «contentView» вместо «view». при добавлении контента. */ класс ScrollableContentController: KeyboardAwareViewController { частный класс ScrollView: UIScrollView { удобство init() { self.init(кадр: .init()) TranslationsAutoresizingMaskIntoConstraints = false клавиатураDismissMode = .interactive задержкиContentTouches = ложь } переопределить функцию touchesShouldCancel (в представлении: UIView) -> Bool { true } } позвольте прокрутке: UIScrollView = ScrollView() пусть contentView = UIView() переопределить функцию loadView() { супер.loadView() contentView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(scrollView) ScrollView.addSubview(contentView) NSLayoutConstraint.activate([ ScrollView.frameLayoutGuide.topAnchor.constraint(equalTo: view.topAnchor), ScrollView.frameLayoutGuide.leadingAnchor.constraint(equalTo: view.leadingAnchor), ScrollView.frameLayoutGuide.trailingAnchor.constraint(equalTo: view.trailingAnchor), ScrollView.frameLayoutGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor), ]) NSLayoutConstraint.activate([ contentView.topAnchor.constraint(equalTo: ScrollView.contentLayoutGuide.topAnchor), contentView.leadingAnchor.constraint(equalTo: ScrollView.contentLayoutGuide.leadingAnchor), contentView.trailingAnchor.constraint(equalTo: ScrollView.contentLayoutGuide.trailingAnchor), contentView.bottomAnchor.constraint(equalTo: ScrollView.contentLayoutGuide.bottomAnchor), contentView.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor), ]) ScrollView.delegate = сам } переопределить func KeyboardWillChangeFrame (_ кадр: CGRect) { если isTopViewController { ScrollView.contentInset.bottom = кадр.высота } } } До сих пор я использовал этот класс, ограничивая нижнюю часть моего нижнего представления нижней частью contentView. Это приведет к тому, что прокрутка будет доступна только в том случае, если contentSize превысит размер прокрутки. Однако в последнее время меня начали раздражать просмотры, которые не отскакивают из-за небольшого размера. Например, если вы перемещаетесь по приложению «Системные настройки», вы заметите, что все представления будут отображаться независимо от того, нужно это или нет. Возможно, это обычно делается с помощью UICollectionView или UITableView, но я ненавижу использовать их, когда у меня небольшое и предопределенное количество представлений, поэтому я настаиваю на использовании вместо этого UIScrollView. Я подумал, что, вероятно, смогу имитировать это поведение подпрыгивания, установив для ContentSize значение как минимум на 0,5 пикселя выше моей высоты SafeArea, например:
let height = view.safeAreaLayoutGuide.layoutFrame.size.height.roundUpToNearestHalf() contentView.snp.updateConstraints { сделать в make.height.equalTo(max(section.maxY, высота)).priority(500) } И это прекрасно работает! Ну, почти.. Очень неприятная проблема заключается в том, что когда я прокручиваю вниз и он возвращается обратно вверх, он возвращается в исходное положение, которое на моем телефоне и в моем случае оказывается (0.0, -97.66666666666667). Я получаю эту информацию в методе делегата ScrollViewDidEndDecelering. Однако когда я прокручиваю вверх и он отскакивает обратно вниз, он приземляется на (0.0, -97.33333333333333). Это очень трудно увидеть, но нижняя граница навигационного представления никогда не исчезает полностью, и это действительно раздражает, когда вы ее видите. Эта проблема не существует в приложении «Системные настройки», и вы увидите, что нижняя граница панели навигации полностью исчезнет.
Как решить эту проблему без использования Table или CollectionView? Кроме того, разумно ли вообще, чтобы contentOffset был отрицательным, или я с самого начала все сделал совершенно неправильно?
Я обошел это прямо сейчас, сохранив начальное смещение содержимого в viewLayoutMarginsDidChange, а затем в ScrollViewDidEndDecelerating проверяя, если разница меньше 1, просто установив его в исходное положение, например:
if abs(scrollView.contentOffset.y - InitialContentOffset.y) < 1 { ScrollView.setContentOffset(initialContentOffset, анимированный: true) } Но я надеюсь, что есть лучшее решение — это хак! Кстати, разве начальное смещение содержимого не должно быть равно нулю?
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Найдите функциональность выделения слова, используя UIScrollView не по центру
Anonymous » » в форуме IOS - 0 Ответы
- 48 Просмотры
-
Последнее сообщение Anonymous
-