Как отключить подкачку UIPageViewController только для альбомной ориентации? - PullRequest
0 голосов
/ 10 января 2019

У меня есть scroll стиль перехода UIPageViewController, который должен отключать пейджинг только тогда, когда устройство находится в горизонтальной ориентации. Но подкачка должна быть включена в портретной ориентации.

Я сталкивался с подобными вопросами здесь в SO, но не с моей конкретной потребностью. Вот некоторые из них:

Как отключить жест смахивания UIPageViewController?

Отключить прокрутку страниц в UIPageViewController

Отключить / включить прокрутку в UIPageViewController

Ограничить жест панорамирования UIPageViewController (с TransitionStyleScroll) определенной областью

Все вышеперечисленное указывает либо на полное отключение, либо на ограничение жеста панорамирования на определенную область.

Теперь, если я воспользуюсь подходом полного отключения:

  • Мне нужно будет отслеживать изменение ориентации устройства
  • Отключить, если ориентация установлена ​​на ландшафт
  • Снова включить, когда ориентация меняется на книжную

Если я прибегну к ограничению определенной области:

  • Мне нужно будет найти эту определенную область

  • Эта определенная область (описанная в предыдущем пункте) должна быть рассчитана по-разному для портретной и альбомной ориентации

  • Определенная область для портретной ориентации должна быть областью целое UIPageViewController границы

  • Определенная область для альбомной ориентации должна быть очень минимальной (чей кадр может быть 0, 0, 1, 1), где пользователь не сможет выполнить операцию панорамирования. Этот расчет кадра должен быть очень точный, потому что мой UIPageViewController принимает все границы главный экран в альбомной ориентации.

  • Тогда опять может понадобиться отслеживать изменение ориентации устройства для разных расчет определенной области


Есть несколько методик, в которых авторы предлагают:

pvc.dataSource = nil // prevents paging

pvc.dataSource = `a valid dataSource object` // enables paging

Итак, ручное включение + отключение снова. Отслеживание изменения ориентации и включение / отключение.

Это не безопасно для использования в моем конкретном случае, поскольку существует возможность назначения источника данных несколько раз.


Существуют и другие подходы, которые, я думаю, не могут быть изменены в соответствии с вариантом использования.

Есть ли быстрый способ добиться того, что мне нужно?

1 Ответ

0 голосов
/ 13 января 2019

Отвечая на мой собственный вопрос, поскольку я уже достиг того, что мне нужно.

Подклассы UIPageViewController - самый простой способ. Мы должны найти базовый UIScrollView, который используется контроллером просмотра страницы для обработки работы, связанной с жестом панорамирования. Мы добавим еще UIPanGestureRecognizer к этому внутреннему виду прокрутки. Этот распознаватель жестов панорамирования по существу не выполняет никаких действий, но он блокирует внутренний распознаватель жестов панорамирования, который распознается только для альбомной ориентации.

Пример реализации:

class CustomPageViewController: UIPageViewController, UIGestureRecognizerDelegate {

    override func viewDidLoad() {
        if let underlyingScrollView = view.subviews.compactMap({ $0 as? UIScrollView })
                                    .first {

            let pangestureRecognizer = UIPanGestureRecognizer()
            pangestureRecognizer.delegate = self
            underlyingScrollView.addGestureRecognizer(pangestureRecognizer)
            // at this point, the underlying scroll view will have two pan gesture
            // recognizer side by side. We have the control of our added pan gesture
            // recognizer through the delegate. We can conditionally recognize it or not
        }
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, 
         shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) 
         -> Bool {
        // Returning true from here means, page view controller will behave as it is
        // Returning false means, paging will be blocked
        // As I needed to block paging only for landscape orientation, I'm just returning
        // if orientation is in portrait or not
        return UIApplication.shared.statusBarOrientation.isPortrait
    }

}
...