Отключите прокрутку UIPageViewController, когда касания запускаются на переключателе UIS, содержащемся на одной из страниц - PullRequest
0 голосов
/ 16 декабря 2018

У меня есть UIPageViewController, где одна страница - это экран Настройки .На этом экране есть UISwitch для включения или выключения настройки.

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

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

Это поведение, которое кажется очень испорченным и непоследовательным.Похоже, что если пользователь касается переключателя, но перед скольжением колеблется, касания регистрируются UISwitch, и он работает так, как ожидает пользователь.Но если пользователь касается UISwitch и сразу начинает скользить, UIPageViewController получает вместо этого прикосновения.Кажется, есть очень тонкая грань (порог колебания) между UISwitch, получающими прикосновения или нет.

Как бы вы решили эту проблему?

ВотПример, который начинается с простых нажатий для переключения UISwitch, а затем показывает некоторые из различных способов попробовать скользить UISwitch, которые приводят к противоречивым результатам:

inconsistent-uiswitch-behavior


Возможные решения и проблемы

Один из способов решения этой проблемы, который я рассмотрел, заключается в обнаружении касаний в любом месте Настройки UIViewController, и если касания начинаются где-то в кадре UISwitch, предотвратите скольжение UIPageViewController.

Меня беспокоит то, что простое отключение скольжения для UIPageViewController не приведет кгарантия касания передаются на UISwitch.Это может означать, что пользователь может попытаться сдвинуть UISwitch, а UIPageViewController не будет скользить, но UISwitch также не будет реагировать на прикосновения, из-за чего он все еще будет выглядеть сломанным и непоследовательным.

ДляНачните исследовать это возможное решение. Я попытался обнаружить касания, переопределив метод touchesBegan следующим образом:

override func touchesBegan(_ touches: Set<UITouch>,
                           with event: UIEvent?) {

    print("touchesBegan")

    super.touchesBegan(touches,
                       with: event)
}

Я попытался обнаружить касания таким образом как на UIPageViewController, так и на UIViewControllerопределенной страницы Settings , но ни одна не вызывается.Я также пытался установить view.isUserInteractionEnabled = true на видах и различные комбинации true или false на разных UIViewController с, но все еще не могу обнаружить прикосновения.

I 'Мы также рассмотрели просто отказ от всей парадигмы UIPageViewController для этого приложения и превращение экрана Settings в модальное, поскольку это решило бы необходимость такого сложного решения, но у * есть и другие преимущества.1074 * парадигма в приложении, поэтому я хочу исследовать, возможно ли сохранить.В конечном счете, кажется, что это была бы лучшая идея, чем странные обходные пути, но я все равно хотел опубликовать это на тот случай, если у кого-то возникнут те же проблемы или у кого-то есть другие возможные решения.: РЕШЕНИЕ

Я потратил кучу времени на эксперименты на основе предоставленных ответов, а также много узнал о том, как работает iOS, поэтому спасибо всем, кто ответил.

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

Я закончил подклассами UISwitch и добавил UIPanGestureRecognizer, который ничего не делает.Это заставляет его вести себя именно так, как я хочу: каждый раз, когда пользователь начинает сдвигать переключатель, UIPageViewController не панорамирует.

class NoPanSwitch: UISwitch {

    override init(frame: CGRect) {
        super.init(frame: frame)

        let recognizer = UIPanGestureRecognizer(target: self,
                                                action: nil)
        addGestureRecognizer(recognizer)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Ответы [ 3 ]

0 голосов
/ 18 декабря 2018

Просто попробуйте это и посмотрите, работает ли он так, как вы хотите.

  1. Обнаружение касаний UISwitch, когда UISwitch touchBegan устанавливает делегата иисточник данных от UIPageViewController до `ноль.

  2. Вкл. touchesEnd установить снова установить datasource и delegate для UIPageViewController.

Таким образом, вы сможете взаимодействовать с вашим UISwitch так, как вы хотите.

0 голосов
/ 19 декабря 2018

Контроллер просмотра страниц имеет свойство gestureRecognizers для распознавателей жестов, управляющих взаимодействиями на странице.Я бы попробовал добавить распознаватель панорамирования в UISwitch и добавить его в контроллер страницы.Эффект, который я ожидаю, состоит в том, что распознаватель жестов панорамирования контроллера страницы потребует, чтобы распознаватели жестов в массиве потерпели неудачу, прежде чем распознавать панорамирование страницы, поэтому прокрутка не происходит, когда вы щелкаете переключатель.Если это не сработает, вы можете поменять контроллер страницы на представление прокрутки с представлением стека или коллекции с вашими контроллерами внутри.Тогда у вас будет полный контроль над panGEstureRecognizer в школьном представлении, чтобы добиться описанного выше поведения.

0 голосов
/ 18 декабря 2018

Можете ли вы выделить подклассы используемых вами UIS-переключателей?Это больше похоже на работу для этого класса, переопределяя gestRecognizerShouldBegin (), возвращая NO для распознавателя жестов смахивания, движущегося горизонтально.В документации этого метода упоминается, что UISlider использует этот метод для той же цели;UISwitch, вероятно, должен делать то же самое.

Другой вариант может заключаться в создании пользовательского UIGestureRecognizer, который с помощью делегата или методов UIGestureRecognizerSubclass заставляет любой другой UISwipeGestureRecognizer давать сбой, если он запускается через UISwitch, и для него самому устанавливается с cancellsTouchesInView значение false.(и ничего не делать, когда это "удается").

...