首页 > 解决方案 > 如何使用 SwiftUI 防止一个子视图的剪辑内容阻止底层子视图中的手势?

问题描述

我有一个主视图,其中包含一个 zStack,底部有一个背景图像,上面有一个用户加载的图像,顶部有两个工具栏。工具栏位于视图的垂直顶部和底部。我希望这些工具栏显示为半透明,背景图像在大小和位置上与主视图的背景图像相匹配。如果用户拖动或缩放他们的图像以与工具栏重叠,它应该被它们遮挡。为了实现这一点,我将这些工具栏视图构建为 zStack,并分别将相同的背景图像对齐到顶部或底部,并剪裁内容以匹配工具栏的高度。

我的问题是这些工具栏视图的剪辑内容会阻止底层用户加载图像上的手势。为了帮助可视化问题,我链接了主视图 (MockScoringView) 的调试视图层次结构的屏幕截图。

这是主视图的代码:

GeometryReader { geometry in
            ZStack {

                Rectangle()
                    .foregroundColor(.blue)
                    .frame(width: geometry.size.width, height: geometry.size.height)
                    .offset(x: self.baseOffset.width + self.newOffset.width, y: self.baseOffset.height + self.newOffset.height)
                    .scaleEffect(self.scale)
                    .gesture(DragGesture()
                        .onChanged { value in
                                self.newOffset.width = value.translation.width / self.scale
                                self.newOffset.height = value.translation.height / self.scale
                        }
                        .onEnded { value in
                                self.baseOffset.width += self.newOffset.width
                                self.baseOffset.height += self.newOffset.height
                                self.newOffset = CGSize.zero
                        }
                    )

                VStack(spacing: 0) {
                    MockTopToolbarView()

                    Spacer()

                    MockBottomToolbarView()
                }
            }
        }

顶部工具栏视图的代码,与底部的非常相似:

ZStack {
            Image("Background")
                .resizable()
                .scaledToFill()
                .frame(height: 56, alignment: .top)
                .clipped()

            Rectangle()
                .foregroundColor(.toolbarGray)
                .frame(height: 56)
        }

我想修改工具栏视图背景的内容,这样它们就不会阻止手势到达用户加载的图像。

调试视图层次结构

标签: iosswiftswiftuigesturezstack

解决方案


您可以设置allowsHitTesting(false)背景图像。

或者,由于您不希望用户图像在工具栏后面可见,您也可以将 Rectangle 和工具栏添加到单个 VStack 中。

ZStack {
    Image("Background")
            .resizable()
            .scaledToFill()
    VStack {
        TopToolBar()
        Rectangle()
            .foregroundColor(.blue)
            ...
        BottomToolBar()
    }
}

推荐阅读