无法在另一个UIScrollView内的UIScrollView中检测到点击

彼得

我有一个垂直滚动UIScrollView,横跨整个ViewController,包含此ContentViewUIView),因此我能够检测到scrollViews边界之外的触摸事件:

import UIKit

class ContentView: UIView {
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let reversedSubviews = subviews.reversed()
        let hitSubview = reversedSubviews
            .first(where: { $0.hitTest(convert(point, to: $0), with: event) != nil })
        if hitSubview != nil {
            return hitSubview
        }
        return super.hitTest(point, with: event)
    }
}

这是View hiearchey

UIScrollView (vertical scroll) //Works
|
 -- ContentView(UIView)
    |
    --UIScrollView (horizontal scroll) //Works
       |
       -- UIView
          |
          --UIButton //This does not work
    |
    --UIScrollView (horizontal scroll) //Works
       |
       -- UIView
          |
          --UIButton //This does not work

在其中,ContentView我还有其他几个水平滚动UIScrollViews但是由于,我无法检测到这些scrollViews中的触摸事件ContentView

即使子视图超出范围,我应该如何处理它以检测所有scrollView中的触摸事件?

将其放置ContentView在水平scrollViews中是没有帮助的

唐马格

这是一个非常基本的示例。

遵循您的层次结构:

  Main View
  |
  -- UIScrollView (vertical scroll) - Red
    |
     -- ContentView(UIView) - Medium Blue
        |
        -- UIScrollView (horizontal scroll) - Green
           |
           -- UIView - Light Gray
              |
              -- UIButton - Blue
           |
           -- UIView - Light Gray
              |
              -- UIButton - Blue
        |
        -- UIScrollView (horizontal scroll) - Green
           |
           -- UIView - Light Gray
              |
              -- UIButton - Blue
           |
           -- UIView - Light Gray
              |
              -- UIButton - Blue
        |

这是它的外观-可以点击按钮:

在此处输入图片说明

向下滚动并向右滚动每个水平滚动视图之后:

在此处输入图片说明

示例代码...不需要@IBOutlet@IBAction不需要连接,只需将视图控制器的类分配给MultiScrollViewController

class MultiScrollViewController: UIViewController {
    
    let vertScrollView = UIScrollView()
    
    let contentView = UIView()
    
    let hScrollA = UIScrollView()
    let hScrollB = UIScrollView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        [vertScrollView, contentView, hScrollA, hScrollB].forEach {
            $0.translatesAutoresizingMaskIntoConstraints = false
        }
        
        contentView.addSubview(hScrollA)
        contentView.addSubview(hScrollB)
        
        vertScrollView.addSubview(contentView)
        
        view.addSubview(vertScrollView)
        
        let g = view.safeAreaLayoutGuide
        let svContentG = vertScrollView.contentLayoutGuide
        let svFrameG = vertScrollView.frameLayoutGuide
        
        NSLayoutConstraint.activate([
            
            // vertical scroll view with 20-pts on each side for "padding"
            vertScrollView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
            vertScrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            vertScrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            vertScrollView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -20.0),
            
            // content view Top / Leading / Bottom 12-pts to content layout guide
            contentView.topAnchor.constraint(equalTo: svContentG.topAnchor, constant: 12.0),
            contentView.leadingAnchor.constraint(equalTo: svContentG.leadingAnchor, constant: 12.0),
            contentView.bottomAnchor.constraint(equalTo: svContentG.bottomAnchor, constant: -12.0),
            // content view Trailing to content layout guide
            contentView.trailingAnchor.constraint(equalTo: svContentG.trailingAnchor, constant: 0.0),
            
            // content view Width: scroll frame width minus 24-pts (we don't want horizontal scrolling)
            contentView.widthAnchor.constraint(equalTo: svFrameG.widthAnchor, constant: -24.0),
            
            // horizontal scroll view A Top / Leading / Trailing 8-pts to contentView
            hScrollA.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8.0),
            hScrollA.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8.0),
            hScrollA.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8.0),
            
            // horizontal scroll view B Top 20-pts from Bottom of hScrollA
            hScrollB.topAnchor.constraint(equalTo: hScrollA.bottomAnchor, constant: 20.0),
            
            // horizontal scroll view B Leading / Trailing / Bottom 8-pts to contentView
            hScrollB.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8.0),
            hScrollB.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8.0),
            hScrollB.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8.0),
            
            // so we have some vertical scrolling, make each horizontal scroll view
            //  60% the height of the vertical scroll view frame
            hScrollA.heightAnchor.constraint(equalTo: svFrameG.heightAnchor, multiplier: 0.6),
            hScrollB.heightAnchor.constraint(equalTo: hScrollA.heightAnchor),
            
        ])
        
        // each horizontal scroll view will have
        //  two UIViews, each with a UIButton
        
        let btn1inA = UIButton()
        let btn2inA = UIButton()
        
        let btn1inB = UIButton()
        let btn2inB = UIButton()
        
        let btn1inAView = UIView()
        let btn2inAView = UIView()
        
        let btn1inBView = UIView()
        let btn2inBView = UIView()
        
        let btnViews = [btn1inAView, btn2inAView, btn1inBView, btn2inBView]
        
        let btns = [btn1inA, btn2inA, btn1inB, btn2inB]
        let ttls = ["Button 1 in A", "Button 2 in A", "Button 1 in B", "Button 2 in B"]
        
        for (btn, str) in zip(btns, ttls) {
            btn.setTitle(str, for: [])
            btn.setTitleColor(.white, for: .normal)
            btn.setTitleColor(.gray, for: .highlighted)
            btn.titleLabel?.font = .boldSystemFont(ofSize: 18)
            btn.backgroundColor = .blue
            btn.contentEdgeInsets = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16)
            btn.translatesAutoresizingMaskIntoConstraints = false
            btn.addTarget(self, action: #selector(self.btnTap(_:)), for: .touchUpInside)
        }
        
        for (btn, v) in zip(btns, btnViews) {
            v.backgroundColor = UIColor(white: 0.95, alpha: 1.0)
            v.translatesAutoresizingMaskIntoConstraints = false
            v.addSubview(btn)
            // center each button in a view with 8-pts padding on all 4 sides
            NSLayoutConstraint.activate([
                btn.topAnchor.constraint(equalTo: v.topAnchor, constant: 8.0),
                btn.leadingAnchor.constraint(equalTo: v.leadingAnchor, constant: 8.0),
                btn.trailingAnchor.constraint(equalTo: v.trailingAnchor, constant: -8.0),
                btn.bottomAnchor.constraint(equalTo: v.bottomAnchor, constant: -8.0),
            ])
        }
        
        // add button-holding-views to horizontal scroll views
        hScrollA.addSubview(btn1inAView)
        hScrollA.addSubview(btn2inAView)
        
        hScrollB.addSubview(btn1inBView)
        hScrollB.addSubview(btn2inBView)
        
        let svAContentG = hScrollA.contentLayoutGuide
        let svAFrameG = hScrollA.frameLayoutGuide
        
        let svBContentG = hScrollB.contentLayoutGuide
        let svBFrameG = hScrollB.frameLayoutGuide
        
        NSLayoutConstraint.activate([
            
            // button 1 in hScroll A
            //  top == content top + 20
            btn1inAView.topAnchor.constraint(equalTo: svAContentG.topAnchor, constant: 20.0),
            //  leading == content leading + 20
            btn1inAView.leadingAnchor.constraint(equalTo: svAContentG.leadingAnchor, constant: 20.0),
            
            // button 2 in hScroll A
            //  leading == button 1 leading + 600 (so we get horizontal scrolling
            btn2inAView.leadingAnchor.constraint(equalTo: btn1inAView.trailingAnchor, constant: 600.0),
            
            //  trailing == content trailing - 20
            btn2inAView.trailingAnchor.constraint(equalTo: svAContentG.trailingAnchor, constant: -20.0),
            
            //  bottom to content bottom
            btn2inAView.bottomAnchor.constraint(equalTo: svAContentG.bottomAnchor),
            
            //  bottom 20-pts from hScroll A frame bottom (so it's at lower-right)
            btn2inAView.bottomAnchor.constraint(equalTo: svAFrameG.bottomAnchor, constant: -20.0),
            
            // button 1 in hScroll B
            //  top == content top + 20
            btn1inBView.topAnchor.constraint(equalTo: svBContentG.topAnchor, constant: 20.0),
            
            //  leading == content leading + 20
            btn1inBView.leadingAnchor.constraint(equalTo: svBContentG.leadingAnchor, constant: 20.0),
            
            // button 2 in hScroll A
            //  leading == button 1 leading + 600 (so we get horizontal scrolling
            btn2inBView.leadingAnchor.constraint(equalTo: btn1inBView.trailingAnchor, constant: 600.0),
            
            //  trailing == content trailing - 20
            btn2inBView.trailingAnchor.constraint(equalTo: svBContentG.trailingAnchor, constant: -20.0),
            
            //  bottom to content bottom
            btn2inBView.bottomAnchor.constraint(equalTo: svBContentG.bottomAnchor),
            
            //  bottom 20-pts from hScroll B frame bottom (so it's at lower-right)
            btn2inBView.bottomAnchor.constraint(equalTo: svBFrameG.bottomAnchor, constant: -20.0),
            
        ])
        
        // some background colors so we can see the frames
        view.backgroundColor = .yellow
        vertScrollView.backgroundColor = .red
        
        // medium blue
        contentView.backgroundColor = UIColor(red: 0.0, green: 0.5, blue: 1.0, alpha: 1.0)
        
        hScrollA.backgroundColor = .green
        hScrollB.backgroundColor = .green
        
    }
    
    @objc func btnTap(_ sender: UIButton) -> Void {
        print(sender.currentTitle ?? "No Button Title")
    }
    
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

无法在另一个UIScrollView内的UIScrollView中检测到点击

来自分类Dev

我可以将UIScrollView放在另一个UIScrollView中吗

来自分类Dev

在另一个视图控制器中,检测到LongPressGesture已结束

来自分类Dev

在另一个视图控制器中检测到LongPressGesture已结束

来自分类Dev

是否可以从iOS中的当前应用检测到另一个应用?

来自分类Dev

GMap-无法检测到点击多边形

来自分类Dev

无法在ng-click功能中检测到点击事件

来自分类Dev

UIScrollView contentOffset在另一个视图被推送后更改

来自分类Dev

使UIScrollView在另一个ViewController的按钮单击上滚动

来自分类Dev

使用另一个视图中具有特定索引的图像启动UIScrollView

来自分类Dev

“未检测到另一个显示”但被检测到。如何修复第三台显示器?

来自分类Dev

从另一个df中的字符串中检测一个df中的多个字符串,如果检测到,则返回检测到的字符串

来自分类Dev

是否检测到两个元素中的任意一个之外的点击?

来自分类Dev

在wpf中另一个控件内的某个内部控件上检测Mouseover

来自分类Dev

我可以检测到另一个线程挂起的进程并从中恢复吗?

来自分类Dev

Android,如何检测到该活动是从另一个活动返回的?

来自分类Dev

检测到网络连接时启动另一个活动

来自分类Dev

:hover选择器即使在另一个元素后面也被检测到

来自分类Dev

jQuery从另一个<input>模糊时检测到<input>是焦点

来自分类Dev

另一个电话可以检测到什么电话信号?(不包括BLE)

来自分类Dev

QuickBlox聊天:如何检测到另一个用户已断开连接?

来自分类Dev

当来自另一个<input>的模糊时,jQuery检测到<input>是焦点

来自分类Dev

Capybara::Poltergeist::MouseEventFailed。Poltergeist 检测到另一个元素

来自分类Dev

jQuery未检测到点击链接

来自分类Dev

检测到UIScrollview到达底部

来自分类Dev

如何在已经有jQuery插件监听点击的区域内检测到点击?

来自分类Dev

以编程方式创建UIScrollView作为另一个UIView的子视图的必要步骤是什么?

来自分类Dev

如何点击一个元素并在另一个元素中添加文本

来自分类Dev

无法启动另一个流程中的另一个流程

Related 相关文章

  1. 1

    无法在另一个UIScrollView内的UIScrollView中检测到点击

  2. 2

    我可以将UIScrollView放在另一个UIScrollView中吗

  3. 3

    在另一个视图控制器中,检测到LongPressGesture已结束

  4. 4

    在另一个视图控制器中检测到LongPressGesture已结束

  5. 5

    是否可以从iOS中的当前应用检测到另一个应用?

  6. 6

    GMap-无法检测到点击多边形

  7. 7

    无法在ng-click功能中检测到点击事件

  8. 8

    UIScrollView contentOffset在另一个视图被推送后更改

  9. 9

    使UIScrollView在另一个ViewController的按钮单击上滚动

  10. 10

    使用另一个视图中具有特定索引的图像启动UIScrollView

  11. 11

    “未检测到另一个显示”但被检测到。如何修复第三台显示器?

  12. 12

    从另一个df中的字符串中检测一个df中的多个字符串,如果检测到,则返回检测到的字符串

  13. 13

    是否检测到两个元素中的任意一个之外的点击?

  14. 14

    在wpf中另一个控件内的某个内部控件上检测Mouseover

  15. 15

    我可以检测到另一个线程挂起的进程并从中恢复吗?

  16. 16

    Android,如何检测到该活动是从另一个活动返回的?

  17. 17

    检测到网络连接时启动另一个活动

  18. 18

    :hover选择器即使在另一个元素后面也被检测到

  19. 19

    jQuery从另一个<input>模糊时检测到<input>是焦点

  20. 20

    另一个电话可以检测到什么电话信号?(不包括BLE)

  21. 21

    QuickBlox聊天:如何检测到另一个用户已断开连接?

  22. 22

    当来自另一个<input>的模糊时,jQuery检测到<input>是焦点

  23. 23

    Capybara::Poltergeist::MouseEventFailed。Poltergeist 检测到另一个元素

  24. 24

    jQuery未检测到点击链接

  25. 25

    检测到UIScrollview到达底部

  26. 26

    如何在已经有jQuery插件监听点击的区域内检测到点击?

  27. 27

    以编程方式创建UIScrollView作为另一个UIView的子视图的必要步骤是什么?

  28. 28

    如何点击一个元素并在另一个元素中添加文本

  29. 29

    无法启动另一个流程中的另一个流程

热门标签

归档