【问题标题】:SwiftUI - Double `.clipped()` modifier makes views disappearSwiftUI - 双 `.clipped()` 修饰符使视图消失
【发布时间】:2021-11-20 04:38:10
【问题描述】:

我有一个视图,DotView,它由 3 个绿色圆圈 clipped 和红色边框组成。我正在使用DragGesture 在容器视图中水平滑动它,它有一个蓝色边框,也是clipped

问题是,一旦我滑到某个点,3 个绿色圆圈就会消失。 如何防止它们消失? 有趣的是,如果我删除第一个 clipped 并只剪掉蓝色容器,圆圈不会消失。同样,如果我删除第二个clipped 并仅剪辑DotView,它们也不会消失。

Both views clipped Only blue view clipped Only DotView clipped

The green circles disappear.

The green circles stay.

The green circles stay.

这是我的代码:

/// 3 green circles, constrained to a red border
struct DotView: View {
    var body: some View {
        HStack {
            ForEach(0..<3) { _ in
                Circle()
                    .fill(Color.green)
                    .frame(width: 100, height: 100)
            }
        }
        .frame(width: 250)
        .border(Color.red)
        .clipped() /// 1. make sure the green circles don't overflow
    }
}

/// container for horizontal dragging, with a blue border
struct ContentView: View {
    @State var offset = CGFloat(0)
    var body: some View {
        DotView()
            .padding() /// add a small gap between the red and blue borders
            .offset(x: offset, y: 0)
            .border(Color.blue)
            .clipped() /// 2. make sure `DotView` doesn't overflow the blue border
            .gesture(
                DragGesture(minimumDistance: 0) /// slide `DotView` left and right
                        .onChanged { offset = $0.translation.width }
            )
    }
}

消失效果在ForEach 中非常明显,但在其他视图中也会出现。例如,当您将整个 HStack 替换为 Circle().fill(Color.green).frame(width: 100, height: 100) 时会发生以下情况:

有什么方法可以让我多次使用clipped 而不会产生奇怪的副作用?为什么它们只消失在左侧而不是右侧? 或者,offset 是什么导致了问题?

【问题讨论】:

  • 您的代码对我来说工作正常,xCode 版本 12.5.1 (961.1) 没有任何问题。您可以尝试自己的代码并将.clipped()替换为.clipShape(Rectangle())我认为它可以解决问题。

标签: ios swift swiftui swiftui-foreach


【解决方案1】:

看起来像绘图优化(是的,看起来它起源于offset)。

无论如何,这是一个修复 - 使用绘图组来修复内容(使用 Xcode 13 / iOS 15 测试):

var body: some View {
    DotView()
        .padding()
        .drawingGroup()               // << here !!
        .offset(x: offset, y: 0)
        .border(Color.blue)
        .clipped()
        .gesture(
            DragGesture(minimumDistance: 0) /// slide `DotView` left and right
                .onChanged { offset = $0.translation.width }
        )
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-30
    相关资源
    最近更新 更多