【发布时间】:2018-12-16 19:11:03
【问题描述】:
我有一个UIPageViewController,其中一页是设置 屏幕。在该屏幕上,有一个 UISwitch 可以打开或关闭设置。
虽然我注意到很多人像我一样点击UISwitch 来切换它,但我观察到一些用户滑动UISwitch 来切换它。
当UIViewController 是UIPageViewController 的一部分时,尝试滑动UISwitch 可能会导致问题,因为滑动开关可以开始滑动UIPageViewController,就好像用户想要更改页面一样。
这种感觉非常破碎和不一致的行为。似乎如果用户触摸开关,但在滑动前短暂犹豫,则触摸由UISwitch 注册,并且它按用户预期工作。但是,如果用户触摸UISwitch 并立即开始滑动,则UIPageViewController 会获得触摸。 UISwitch 接触与否之间似乎有一条非常细的界限(犹豫阈值)。
你会如何解决这个问题?
下面是一个示例,首先通过简单的点击来切换UISwitch,然后展示了尝试滑动UISwitch 导致结果不一致的一些不同方法:
可能的解决方案和问题
我考虑过解决此问题的一种方法是检测 设置 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 上以这种方式检测触摸,但都没有被调用。我还尝试在视图上设置view.isUserInteractionEnabled = true,并在不同的UIViewControllers 上设置true 或false 的不同组合,但似乎仍然无法检测到触摸。
我还考虑过为这个应用放弃整个 UIPageViewController 范式,而将 Settings 屏幕改为模式,因为这样可以解决对这种复杂解决方案的需求,但是是应用程序中UIPageViewController 范式的其他优势,所以我想探索是否可以保留。最终,这似乎比奇怪的解决方法更好,但我还是想发布这个,以防其他人遇到同样的问题或任何人有其他可能的解决方案。
更新:解决方案
我花了很多时间根据提交的答案进行实验,同时也学习了很多关于 iOS 工作原理的知识,所以感谢所有回答的人。
最终,Leon 的回答让我找到了一个与 UIPanGestureRecognizer 一起工作的简单解决方案,这与我根据 Carl 的回答尝试使用 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")
}
}
【问题讨论】:
标签: ios uipageviewcontroller uiswitch