swiftui自定义滑动删除

import SwiftUI

//Model and Model Data

struct Item1: Identifiable {
    
    var id = UUID().uuidString // UUID 是一个结构体,表示“通用唯一标识符”
   // uuidString 是 UUID 类型的一个属性,它返回该 UUID 的字符串表示形式。
    var title: String
    var price: String
    var subTitle: String
    var image: String
    var offset: CGFloat = 0
}
import SwiftUI

struct TabBar: View {
    @State var current = "Home"
    
    var body: some View {
       
        ZStack(alignment: Alignment(horizontal: .center, vertical: .bottom)) {
            //Alignment 是一个结构体,允许你定义水平和垂直方向上的对齐方式。
            TabView(selection: $current) {
                
                Home()
                    .tag("Home")
                
                Text("Message")
                    .tag("Message")
                
                Text("Account")
                    .tag("Account")
            }

            HStack(spacing: 0) {
                // TabButton
                
                TabButton(title: "Home", image: "house", selected: $current)
                
                Spacer(minLength:  0)
                
                TabButton(title: "Message", image: "message", selected: $current)
                
                Spacer(minLength:  0)
                
                TabButton(title: "Account", image: "person", selected: $current)
      
            }
            .padding(.vertical, 12)
            .padding(.horizontal)
            .background(.black)
            .clipShape(Capsule())
            .padding(.horizontal, 25)
        }
    }
}

struct TabBar_Previews: PreviewProvider {
    static var previews: some View {
        TabBar()
    }
}
import SwiftUI

struct Home: View {
    @State var size = "Medium"
    @State var currentTab = "All"
    @State var items = [
        Item1(title: "Coco Coffee", price: "$20.00", subTitle: "We have amazing  Lamp wide range", image: "cat1"),
        Item1(title: "Modern Coddee", price: "$60.00", subTitle: "We have amazing coffee", image: "cat1"),
        Item1(title: "Common Coffee", price: "$35.00", subTitle: "Amazing quality width", image: "cat1"),
    ]
    
    @GestureState var isDragging = false
    
    // adding cart items
    @State var cart: [Item1] = []
    
    var body: some View {
        
        VStack {
            
            HStack {
                
                Button {
                    
                }label: {
                    Image(systemName: "line.3.horizontal")
                        .font(.title)
                        .foregroundColor(.black)
                }
                
                Spacer()
                
                Button {
                    
                }label: {
                    Image(systemName: "cart")
                        .font(.title)
                        .foregroundColor(.black)
                }
                .overlay(
                    // Cart Count
                    Text("\(cart.count)")
                        .font(.caption)
                        .foregroundColor(.white)
                        .fontWeight(.heavy)
                        .frame(width: 20, height: 20)
                        .background(.blue)
                        .clipShape(Circle())
                        .offset(x: 25, y: -22)
                    // disbling if no items
                        .opacity(cart.isEmpty ? 0 : 1)
                )
            }
            .padding(.horizontal)
            .padding(.top)
            .padding(.bottom, 10)
            
            ScrollView {
                
                VStack {
                    
                    HStack {
                        
                        VStack(alignment: .leading, spacing: 8) {
                            
                            Text("Welcome to \nMy Home")
                                .font(.largeTitle)
                                .fontWeight(.heavy)
                                .foregroundColor(.black)
                            
                            Text("We have different coffees")
                                .font(.caption)
                                .foregroundColor(.gray)
                                .fontWeight(.bold)
                        }
                        
                        Spacer(minLength: 15)
                        //minLength 是Spacer的一个参数,表示该空白空间的最小高度(或宽度,取决于容器的方向)
                        //minLength: 15 表示Spacer至少会占用15点的空间。如果有更多可用空间,Spacer 会扩展以填满剩余区域。
                        
                        // Menu Button
                        Menu(content: {
                            
                            Button {
                                size = "Small"
                            }label: {
                                
                                Text("Small")
                            }
                            
                            Button {
                                size = "Medium"
                            }label: {
                                
                                Text("Medium")
                            }
                            
                            Button {
                                size = "Large"
                            }label: {
                                
                                Text("Large")
                            }
                        }) {
                            
                            Label(title: {
                                Text(size)
                                    .foregroundColor(.white)
                            }) {
                                
                                Image(systemName: "slider.horizontal.3")
                                    .foregroundColor(.white)
                            }
                            .padding(.vertical, 10)
                            .padding(.horizontal)
                            .background(.black)
                            .clipShape(Capsule())
                        }
                    }
                    .padding()
                    
                    HStack(spacing: 0) {
                        
                        ForEach(tabs, id: \.self) { tab in
                            
                            Button {
                                currentTab = tab
                            }label: {
                                Text(tab)
                                    .fontWeight(.bold)
                                    .foregroundColor(currentTab == tab ? .black : .gray)
                            }
                            
                            if tab != tabs.last {
                                Spacer(minLength: 0)
                            }
                        }
                    }
                    .padding()
                    
                    ForEach(items.indices) { index in
                        
                        //  Card View
                        ZStack {
                            Color.black.cornerRadius(20)
                            
                            Color.blue.cornerRadius(20)
                                .padding(.trailing, 65)
                            
                            // Button
                            HStack {
                                
                                Spacer()
                                
                                Button {
                                    
                                }label: {
                                    
                                    Image(systemName: "heart")
                                        .font(.title)
                                        .foregroundColor(.white)
                                        .frame(width: 65)
                                }
                                
                                Button {
                                    addCart(index: index)
                                }label: {
                                    
                                    Image(systemName: checkCart(index: index) ? "cart.badge.minus": "cart.badge.plus")
                                        .font(.title)
                                        .foregroundColor(.white)
                                        .frame(width: 65)
                                }
                            }
                            
                            CardView(item: items[index])
                            // drag gesture
                                .offset(x: items[index].offset)
                                .gesture(
                                    DragGesture()
                                        .updating($isDragging, body: { (value, state, _) in
                                            // so we can validate for correct drag
                                            state = true
                                            onChanged(value: value, index: index)
                                            
                                        })
                                        .onEnded({ (value) in
                                            onEnded(value: value, index: index)
                                            
                                        })
                                )
                        }
                        .padding(.horizontal)
                        .padding(.top)
                    }
                }
                .padding(.bottom, 100)
            }
        }
        
    }
    
    // checking cart and adding item
    func checkCart(index: Int) -> Bool {
        
        return cart.contains { (item) -> Bool in
            
            return item.id == items[index].id
        }
    }
    
    func addCart(index: Int) {
        
        if checkCart(index: index) {
            
            cart.removeAll { (item) -> Bool in
                return item.id == items[index].id
            }
        }
        else {
            cart.append(items[index])
        }
        
        // closing after added
        withAnimation {
            
            items[index].offset = 0
        }
    }
    
    func onChanged(value: DragGesture.Value, index: Int) {
        
        if value.translation.width < 0 && isDragging {
            
            items[index].offset = value.translation.width
        }
    }
    
    // onEnded is not working properlu
    // may be its bug
    // to avoid this we using update property on Drag Gesture
    func onEnded(value: DragGesture.Value, index: Int) {
        
        withAnimation {
            
            // 65 + 65 = 130
            if -value.translation.width >= 100 {
                
                items[index].offset = -130
            }
            else {
                items[index].offset = 0
            }
        }
    }
    
}


var tabs = ["Tables","Chairs","Lamps","All"]

struct Home_Previews: PreviewProvider {
    static var previews: some View {
        Home()
    }
}
  1. .gesture(DragGesture()...):为卡片添加拖拽手势。DragGesture() 是用于检测拖动手势的类型。

  2. .updating($isDragging, body: { ... }):使用 updating 方法可以更新一个状态变量(这里是 $isDragging)以指示当前是否正在拖动。body: 闭包中的代码会在拖动过程中被调用,这里设置 state = true 表示正在拖动,同时调用 onChanged(value:index) 函数进行处理。

  3. .onEnded({ (value) in ... }):当拖动结束时,使用 onEnded 来处理最终的拖动结果。在闭包中调用 onEnded(value:index) 函数来处理结束后的逻辑。

import SwiftUI

struct CardView: View {
    var item: Item1
    
    var body: some View {
        
        HStack {
            
            Image(item.image)
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: UIScreen.main.bounds.width / 3.2)
            
            VStack(alignment: .leading, spacing: 10) {
                
                Text(item.title)
                    .fontWeight(.heavy)
                    .foregroundColor(.black)
                
                Text(item.subTitle)
                    .font(.caption)
                    .foregroundColor(.gray)
                
                Text(item.price)
                    .fontWeight(.heavy)
                    .foregroundColor(.black)
            }
            Spacer(minLength: 0)
        }
        .padding()
        .background(Color.white)
        .cornerRadius(20)
        .shadow(color: Color.black.opacity(0.08), radius: 5, x: 5, y: 5)
        .shadow(color: Color.black.opacity(0.08), radius: 5, x: -5, y: -5)
    }
}
import SwiftUI

struct TabButton: View {
    var title: String
    var image: String
    
    @Binding var selected: String
    
    var body: some View {
        
        Button {
            withAnimation(.spring()) {
                selected = title
            }
        }label: {
            
            HStack(spacing: 10) {
                
                Image(systemName: image)
                    .resizable()
                    .renderingMode(.template)
                    .frame(width: 25, height: 25)
                    .foregroundColor(.white)
                
                if selected == title {
                    
                    Text(title)
                        .fontWeight(.bold)
                        .foregroundColor(.white)
                }
            }
            .padding(.vertical, 10)
            .padding(.horizontal)
            .background(Color.white.opacity(selected == title ? 0.08 : 0))
            .clipShape(Capsule())
        }
    }
}

         在 SwiftUI 中,.renderingMode(.template) 是用于控制图像(如 SF Symbols 图标)渲染方式的修饰符。这个修饰符主要用于设置图像的填充模式,使其能够适应当前环境的颜色。.renderingMode(): 这是一个视图修饰符,用于指定图像的渲染模式。.template: 当你将渲染模式设置为 .template 时,图像将使用其所处环境的前景色(通常是文本颜色),而不是其原始颜色。

Menu的简单使用:

       //在SwiftUI 中,Menu 是一个用于创建上下文菜单或弹出菜单的视图组件。它允许用户选择多个选项,而不必占用界面太多空间。
            Menu("选择一项") {
                Button("选项 1") {
                    print("选择了选项 1")
                }

                Button("选项 2") {
                    print("选择了选项 2")
                }

                Button("选项 3") {
                    print("选择了选项 3")
                }
            }
            .padding()
            .background(Color.blue.opacity(0.1))
            .cornerRadius(10)
        Menu {
            Button {
                
            }label: {
                Label("Option 1", systemImage: "star")
            }
            Button{
                
            }label: {
                Label("Option 2", systemImage: "gear")
            }
            Button{
                
            } label:{
                Label("Option 3", systemImage: "circle")
            }
        } label: {
            Label("Show Menu", systemImage: "ellipsis.circle")
        }
        Menu("美食") {
            Button {
                
            }label: {
                Text("炸鸡")
            }
            
            Button {
                
            }label: {
                Text("烧烤")
            }
            Menu {
                Button {
                    
                }label: {
                    Text("榴莲披萨")
                }
                
                Button {
                    
                }label: {
                    Text("奥尔良披萨")
                }
            } label: {
                Text("披萨")
            }
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值