使用手势后删除视图和移动内容

Posted

技术标签:

【中文标题】使用手势后删除视图和移动内容【英文标题】:Deleting Views and Shifting Content After Using Gesture 【发布时间】:2021-05-23 09:32:12 【问题描述】:

我有一个 VStack,通过 DragGesture()、.rotationEffect() 和 .offset(),可以在屏幕外移动和旋转。 VStack 下面是另一个 VStack。 VStack移出屏幕后,如何删除上面的VStack并将下面的VStack向上移动到上面的VStack原来的位置?

这是一个最小的、可重现的例子:

import SwiftUI

struct Test: View 
    @State var offset = CGSize.zero
    var colWidth: CGFloat
    var body: some View 
        VStack 
            VStack 
                Text("A")
            
            .frame(width: colWidth)
            .border(Color.black, width: 1)
            .rotationEffect(.degrees(Double(offset.width / 5)))
            .offset(x: offset.width * 5, y: 0)
            .gesture(DragGesture()
                        .onChanged  gesture in
                            self.offset = gesture.translation
                        
                        .onEnded  _ in
                            if abs(self.offset.width) > 100 
                             else 
                                self.offset = .zero
                            
                        
            )
            VStack 
                Text("B")
            .frame(width: colWidth)
            .border(Color.black)
        
    


struct Test_Previews: PreviewProvider 
    static var previews: some View 
        Test(colWidth: 414)
    

在这种情况下,当 A 移出视野时,我应该如何删除 A 并将 B 移动到 A 的位置?

提前致谢!

【问题讨论】:

【参考方案1】:

首先,我会使用ForEach,因此如果您想添加更多字母(例如“C”),则无需更改代码。

它还使删除变得非常容易。只需rows.remove(at: index),下方的VStacks 就会上移。

struct ContentView: View 
    @State var offset = CGSize.zero
    var colWidth: CGFloat = 414
    
    @State var rows = ["A", "B", "C"]
    
    var body: some View 
        
        VStack 
            ForEach(rows.indices, id: \.self)  index in
                VStack 
                    Text(rows[index]) /// get the current letter
                
                .frame(width: colWidth)
                .border(Color.black, width: 1)
                .rotationEffect(.degrees(index != 0 ? 0 : Double(offset.width / 5))) /// only rotate if row is on top (index 0)
                .offset(x: index != 0 ? 0 : offset.width * 5, y: 0) /// only offset if row is on top (index 0)
                .gesture(DragGesture()
                            
                            .onChanged  gesture in
                                self.offset = gesture.translation
                            
                            .onEnded  _ in
                                if abs(self.offset.width) > 100 
                                    rows.remove(at: index)
                                
                                self.offset = .zero
                            
                )
                
            
        
    

结果:


编辑:允许在任意行上滑动以删除

struct ContentView: View 
    @State var gestureIndex: Int?
    @State var offset = CGSize.zero
    var colWidth: CGFloat = 414

    @State var rows = ["A", "B", "C"]

    var body: some View 

        VStack 
            ForEach(rows.indices, id: \.self)  index in
                VStack 
                    Text(rows[index])
                
                .frame(width: colWidth)
                .border(Color.black, width: 1)
                .rotationEffect(.degrees(gestureIndex == index ? Double(offset.width / 5) : 0)) /// only apply rotation if row is dragged row
                .offset(x: gestureIndex == index ? offset.width * 5 : 0, y: 0) /// only apply offset if row is dragged row
                .gesture(DragGesture()
                            .onChanged  gesture in
                                print("change: \(index)")
                                self.gestureIndex = index
                                self.offset = gesture.translation
                            
                            .onEnded  _ in
                                if abs(self.offset.width) > 100 
                                    rows.remove(at: index)
                                
                                self.gestureIndex = nil
                                self.offset = .zero
                            
                )

            
        
    

【讨论】:

非常感谢您的回答 - 这对我帮助很大。如果我想刷 C,我必须刷 A 和 B 才能到达 C。有什么方法可以直接刷 C 或任何其他 VStack?

以上是关于使用手势后删除视图和移动内容的主要内容,如果未能解决你的问题,请参考以下文章

动画后的iOS旋转手势

表格视图延迟(即使在删除手势识别器后)

移除 UIButton 的手势

在 iOS Swift 中使用键盘平移手势处理文本输入视图移动

不要在特定位置使用长按手势移动表格视图单元格

UIScrollview 子视图在缩放后无法识别平移手势