场景一
进行一个阅读器项目的开发时,遇到了一个问题,
需要在点击绿色区域时弹出一个菜单,因此在该区域加了一个View,
然而,当在这个区域滑动时,滑动手势被绿色区域拦截,手势无法传递到下面的 UIPageViewController 的 View 上

描述
阅读器上方,摇啊摇,出来一个绿色的菜单
要求可以点,也可以拖动
拖动是下方 UIPageViewController
的事情。
手势被绿色视图挡住了,需要一个透传
思路:
把绿色视图的 hitTest View ,交给正在看的阅读器,那一页
这样拖动绿色视图,也可以滑动
- class GreenView: UIView{
- override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
- var afterThat = next
- while afterThat != nil{
- if let tmp = afterThat as? ViewController{
- if let target = tmp.pagedController.viewControllers?.first{
- return target.view
- }
- }
- else{
- afterThat = afterThat?.next
- }
- }
- return nil
- }
- }
同时要捕捉绿色视图的点击事件,
通过阅读页面的视图控制器,来捕捉
- class ContentCtrl: UIViewController {
- override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
- if let touch = touches.first, greenFrame.contains(touch.location(in: view)){
- NotificationCenter.default.post(name: .hitGreen, object: nil)
- }
- }
- }
场景二
用户在直播室,吃瓜
来了一条重要的消息,必须要用户处理,
用户退出直播室,也要展示,
同时不影响用户给主播送礼物

如上图,用户看到消息,也可以滑动阅读器
( 在消息的区域,滑动无效 )
思路肯定是 window,
脱离控制器,也能展示
实现一,创建新的 window
- class MsgWindow: UIWindow {
- init() {
- let originX: CGFloat = 50
- let width = UIScreen.main.bounds.width - originX * 2
- // 窗口大小固定
- super.init(frame: CGRect(x: originX, y: 100, width: width, height: 150))
- clipsToBounds = true
- layer.cornerRadius = 8
- backgroundColor = UIColor.cyan
- // 提升 zIndex
- windowLevel = UIWindow.Level.statusBar + 100
- isHidden = true
- }
- func show(){
- // 展现的必要配置
- if windowScene == nil, let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene{
- windowScene = scene
- }
- isHidden = false
- }
- }
实现 2,使用老的 window 和 View
- class MsgView: UIView {
- init() {
- let originX: CGFloat = 50
- let width = UIScreen.main.bounds.width - originX * 2
- super.init(frame: CGRect(x: originX, y: 100, width: width, height: 150))
- clipsToBounds = true
- layer.cornerRadius = 8
- backgroundColor = UIColor.cyan
- // 设置 z Index
- layer.zPosition = CGFloat.infinity
- isHidden = true
- }
- func show(){
- // 找到 key window,
- // 把视图,添加上去
- let scenes = UIApplication.shared.connectedScenes
- for sce in scenes{
- if let windowScene = sce as? UIWindowScene, windowScene.activationState == .foregroundActive , let win = windowScene.windows.first{
- isHidden = false
- win.addSubview(self)
- return
- }
- }
- }
- }
场景三
用户在直播室,吃瓜
来了一条重要的消息,必须要用户处理,
用户退出直播室,也要展示,
同时不影响用户给主播送礼物
这条消息,很长
( 在消息的区域,滑动有效 )
思路, 扩展场景 2 的第 2 种实现

一句话,限定了响应范围,
重写了 func point(inside
- class MsgView: UIView {
- let rect : CGRect = {
- let originX: CGFloat = 50
- let width = UIScreen.main.bounds.width - originX * 2
- return CGRect(x: originX, y: 100, width: width, height: 400)
- }()
- let btnRect = CGRect(x: 10, y: 10, width: 50, height: 50)
- init() {
- super.init(frame: rect)
- clipsToBounds = true
- layer.cornerRadius = 8
- backgroundColor = UIColor.clear
- layer.zPosition = CGFloat.infinity
- isHidden = true
- let bg = UIView(frame: CGRect(origin: .zero, size: rect.size))
- bg.backgroundColor = UIColor.cyan
- bg.alpha = 0.5
- addSubview(bg)
- let btn = UIButton(frame: btnRect)
- btn.backgroundColor = UIColor.red
- btn.layer.cornerRadius = 8
- btn.backgroundColor = UIColor.white
- addSubview(btn)
- btn.addTarget(self, action: #selector(hide), for: .touchUpInside)
- }
- @objc func hide(){
- isHidden = true
- }
- override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
- return btnRect.contains(point)
- }
- }
为啥这条消息,不用 scroll View ?
ha ha
同时,解决了场景一
一般情况下
github repo
到此这篇关于iOS阅读器与直播的控件重叠滑动交互详解的文章就介绍到这了,更多相关iOS重叠滑动内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!