首页 > 解决方案 > 使用用户手势更改其值时高度卡顿

问题描述

我正在尝试构建一个底部表单 UI,就像 Apple Maps 应用程序中的 UI 一样。通常,这是通过将底部工作表视图放置在电话的可见区域之外来实现的。但是,因为我也在使用标签栏,所以这样做并不理想,因为它会破坏标签栏的透明度。

相反,我要做的是在用户的拖动事件中更改底部工作表内容的高度。这是一个简化的示例:

struct AnimationView2: View {
    
    @State private var translation: CGFloat = 0
    
    var body: some View {
        
        VStack {
            
            Spacer()
            RoundedRectangle(cornerRadius: 10)
                .fill(Color.green)
                .frame(height: self.height())
                .padding()
                .gesture(self.gesture())
        }
        
    }
    
    private func height() -> CGFloat {
        return 100 + abs(self.translation)
    }
    
    private func gesture() -> some Gesture {
        DragGesture()
            .onChanged { action in
                self.translation = action.translation.height
            }
    }
}

但是,前面的例子有两个问题:

这是我正在谈论的一个例子。也许 GIF 不是显示动画如何卡顿的最佳选择,但我认为它或多或少是可见的:

问题的GIF

有趣的是,使用完全相同的代码,但使用 offset 属性做运动动画似乎完美无缺:

struct AnimationView2: View {
    
    @State private var translation: CGFloat = 0
    
    var body: some View {
        
        VStack {
            
            Spacer()
            RoundedRectangle(cornerRadius: 10)
                .fill(Color.green)
                .frame(height: 100)
                .padding()
                .offset(y: self.translation)
                .gesture(self.gesture())
        }
        
    }
    
    private func gesture() -> some Gesture {
        DragGesture()
            .onChanged { action in
                self.translation = action.translation.height
            }
    }
}

知道为什么会这样吗?

标签: swiftswiftui

解决方案


这是一个如何实现这一目标的示例。我.clipped()在父视图上使用,以限制内部内容的大小,使其不会低于TabView.

最小示例代码:

struct ContentView: View {
    
    @State private var selection: Int = 1
    
    var body: some View {
        TabView(selection: $selection) {
            AnimationView2()
                .tabItem {
                    Label("1", systemImage: "1.circle")
                }
                .tag(1)
            
            Text("Other view")
                .tabItem {
                    Label("2", systemImage: "2.circle")
                }
                .tag(2)
        }
    }
}



struct AnimationView2: View {
    
    @State private var offset: CGFloat = 0
    
    private var height: CGFloat {
        offset + 100 // Indicator you grab?
    }
    private var dragGesture: some Gesture {
        DragGesture()
            .onChanged { drag in
                offset = -drag.translation.height
            }
            .onEnded { drag in
                offset = 0
            }
    }
    
    var body: some View {
        GeometryReader { geo in
            RoundedRectangle(cornerRadius: 10)
                .fill(Color.green)
                .frame(height: UIScreen.main.bounds.height)
                .offset(y: geo.size.height - height)
                .gesture(dragGesture)
                .animation(.easeOut)
        }
        .clipped()
    }
}

结果:

显示抽屉工作的 GIF


推荐阅读