-1

我正在开发一个包含下图所示屏幕的应用程序。具有列表视图的面板是从 Nib 实例化的,但其中带有绘图的浅灰色面板是动态生成的 UIView,它是称为 FrameView 的 UIView 子类的子视图(出于问题的目的)。

角落里的红点是该图的删除按钮。绘图是绘图对象的内容,它与列表中选定的项目具有多对多的关系。当我在列表中选择一个项目时,零个或多个这样的面板,显示该项目的图纸被添加为 FrameView 的子视图。

为了使这些删除按钮可以点击,FrameView 启用了用户交互。当我在列表中选择一个项目时会发生这种情况。FrameView 首次出现时关闭。

左下角是导航键。它有各种与之相关的手势和点击,允许用户在使用主屏幕的不同编辑器之间移动。在主视图中,此按钮具有相对较高的 zPosition。

但是一旦 FrameView 打开了它的用户交互,它就会阻止点击和手势到达导航按钮。

我原以为增加 FrameView 上方导航按钮的 zPosition 可以解决问题,但事实并非如此。即使 FrameView 启用了用户交互,如何让导航按钮接收点击和手势?还是我以错误的方式解决这个问题?

编辑:要提到导航按钮是通过情节提要添加的唯一元素,以防万一

在此处输入图像描述

编辑2:经过一番折腾,我将覆盖hitTest,所以:

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let view = super.hitTest(point, with: event)
        return view == self ? nil : view
    }

这不是来自 SO,虽然这里有一些答案含糊地暗示了这种方法,但它们(在 SO 上很常见)a)与过时的 Swift 版本相关,b)埋在不同的上下文中,c)不是由任何明显的搜索返回。

这个网站必须对过时的、被大力支持的答案做点什么。我认为 Swift 必须是最坏的情况,因为由于 Apple 的强制升级政策,旧版本的用户确实很少。

感谢 Ptit Xav 把你的头伸进我的烂摊子里。

4

1 回答 1

0

“我正在使用 .layer.zPosition 增加 zPosition”

好的,这就是问题所在。

更改.zPosition视图层的 不会更改其在视图层次结构中的顺序。

看看这个布局,在 Storyboard / IB 中添加了两个按钮:

在此处输入图像描述

使用这个基本代码,我们将添加一个启用用户交互的“frameView”子视图,以便它覆盖两个按钮。

我们将使用.layer.zPosition使第一个按钮可见,但我们不能点击它。

我们将使用.bringSubviewToFront()使第二个按钮不仅可见,而且还将更改视图层次结构,以便我们可以点击它。

class HierarchyViewController: UIViewController {
    
    @IBOutlet var firstButton: UIButton!
    @IBOutlet var secondButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let frameView = UIView()
        frameView.backgroundColor = .systemBlue
        frameView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(frameView)
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            frameView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
            frameView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            frameView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            frameView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -20.0),
        ])

        // make sure our added view has user interaction enabled
        frameView.isUserInteractionEnabled = true
        
        // change the zPosition of the first button
        firstButton.layer.zPosition = 999
        
        // change the view Hierarchy for the second button
        view.bringSubviewToFront(secondButton)
    }
    
    @IBAction func firstButtonTap(_ sender: Any) {
        print("First Tapped!")
    }
    
    @IBAction func secondButtonTap(_ sender: Any) {
        print("Second Tapped!")
    }
    
}

这是它在运行时的样子:

在此处输入图像描述

没有视觉上的区别,但是如果我们使用Debug View Hierarchy我们可以清楚地看到第一个按钮在“frameView”后面,而第二个按钮在它前面

在此处输入图像描述

虽然“frameView”禁用了用户交互,但我们可以“点击它”到第一个按钮。但是一旦我们在“frameView”上启用了用户交互,它现在会抓住触摸,我们不能点击第一个按钮。更改视图层次结构.bringSubviewToFront()可解决此问题。(注意,我使用了蓝色背景以便于查看“frameView”......如果它具有清晰的背景,则同样适用)。

于 2021-12-03T14:02:51.600 回答