美文网首页SwiftUI
SwiftUI 实现 Segment Tab

SwiftUI 实现 Segment Tab

作者: Bepawbikvy | 来源:发表于2021-07-22 11:27 被阅读0次

    最近忙得前言都不想喵两句了...希望此demo对你有帮助~


    效果图:


    Segment Tab 效果图.gif

    核心实现原理:
    AppBar(index: $index, offset: $offset)控制按钮逻辑;GeometryReader包裹你按钮对应的所有视图,将灵活的首选大小返回到其父布局,offset控制偏移量。

    实现代码如下:

    
    import SwiftUI
    
    struct ContentView: View {
        var body: some View {
            Home()
        }
    }
    
    struct Home: View {
        @State var index = 0
        @State var offset: CGFloat = 0
        var width = UIScreen.main.bounds.width
        @State var offsetMoved: CGFloat = 0
        
        var body: some View {
            VStack(spacing: 0) {
                
                AppBar(index: $index, offset: $offset)
                
                GeometryReader{g in
                    HStack(spacing: 0) {
                        Scape()
                            .frame(width: g.frame(in : .global).width)
                        Code()
                            .frame(width: g.frame(in : .global).width)
                        Cat()
                            .frame(width: g.frame(in : .global).width)
                    }
                    .offset(x: self.offset + self.offsetMoved)
    
                    .highPriorityGesture(DragGesture()
                    .onEnded({ value in
                            if value.translation.width > 150 { // minimum drag...
                                print("right")
                                self.changeView(left: false)
                            } else if value.translation.width < -150 {
                                print("left")
                                self.changeView(left: true)
                            }
                            self.offsetMoved = 0 // 重置微调
                        })
                        .onChanged({ value in
                            self.offsetMoved = value.translation.width // 微调
                        }))
                }
            }
            .animation(.default)
            .edgesIgnoringSafeArea(.all)
        }
        
        func changeView(left: Bool) {
            // tab
            if left {
                
                if self.index != 2 {
                    self.index += 1
                }
            } else {
                if self.index != 0 {
                    self.index -= 1
                }
            }
            
            // view
            if self.index == 0 {
                self.offset = 0
            }
            else if self.index == 1 {
                self.offset = -self.width
            }
            else {
                self.offset = -self.width*2
            }
            // change the width based on the size of the tabs...
        }
    }
    
    struct AppBar: View {
        @Binding var index: Int
        @Binding var offset: CGFloat
        
        let imageWH: CGFloat = 25
        
        var width = UIScreen.main.bounds.width
        
        var body: some View {
            
            VStack(alignment: .leading, content: {
                
                Text("Segment Tab")
                    .font(.title)
                    .foregroundColor(.white)
                    .padding(.leading)
                    .padding(.bottom)
                
                HStack {
                    
                    Button(action: {
                        self.index = 0
                        self.offset = 0
                    }) {
                        VStack(spacing: 8){
                            HStack(spacing: 12) {
                                Image(systemName: "leaf")
                                    .resizable()
                                    .foregroundColor(self.index == 0 ? .white : Color.white.opacity(0.7))
                                    .frame(width: imageWH, height: imageWH)
                                Text("Scape")
                                    .foregroundColor(self.index == 0 ? .white : Color.white.opacity(0.7))
                            }
                            
                            Capsule()
                                .foregroundColor(self.index == 0 ? Color.white : Color.clear)
                                .frame(width: 32, height: 4)
                            Spacer().frame(maxWidth: .infinity, maxHeight: 0)
                        }
                    }
                    
                    Button(action: {
                        self.index = 1
                        self.offset = -self.width
                    }) {
                        VStack(spacing: 8){
                            HStack(spacing: 12) {
                                Image(systemName: "laptopcomputer")
                                    .resizable()
                                    .foregroundColor(self.index == 1 ? .white : Color.white.opacity(0.7))
                                    .frame(width: imageWH+8, height: imageWH)
                                Text("Code")
                                    .foregroundColor(self.index == 1 ? .white : Color.white.opacity(0.7))
                            }
                            
                            Capsule()
                                .foregroundColor(self.index == 1 ? Color.white : Color.clear)
                                .frame(width: 32, height: 4)
                            Spacer().frame(maxWidth: .infinity, maxHeight: 0)
                        }
                    }
                    
                    Button(action: {
                        self.index = 2
                        self.offset = -self.width*2
                    }) {
                        VStack(spacing: 8){
                            HStack(spacing: 12) {
                                Image("Cat_Footprint")
    //                                .resizable()
                                    .foregroundColor(self.index == 2 ? Color.white : Color.white.opacity(0.7))
                                    .frame(width: imageWH, height: imageWH)
                                    
                                Text("Cat")
                                    .foregroundColor(self.index == 2 ? .white : Color.white.opacity(0.7))
                                    
                            }
                            
                            Capsule()
                                .foregroundColor(self.index == 2 ? Color.white : Color.clear)
                                .frame(width: 32, height: 4)
                            Spacer().frame(maxWidth: .infinity, maxHeight: 0)
                        }
                    }
                }
            })
            .padding(.top, (UIApplication.shared.windows.first?.safeAreaInsets.top)! + 15)
            .padding(.horizontal)
            .padding(.bottom, 10)
            .background(Color(.systemBlue))
        }
    }
    
    struct Cat: View {
        var body: some View {
            
            ScrollView(.vertical, showsIndicators: false) {
                VStack(spacing: 0) {
                    ForEach(1...8, id: \.self) {i in
                        
                        HStack(spacing: 0) {
                            Spacer().frame(width: 16)
                            Image("cat_\(i)")
                                .resizable()
                                .aspectRatio(contentMode: .fit)
                                .frame(height: 200)
                                .cornerRadius(15)
                                .padding(.top)
                                .padding(.horizontal)
                            Spacer().frame(width: 16)
                        }
                    }
                }
            }.padding(.bottom, 18)
        }
    }
    
    struct Code: View {
        var body: some View {
            GeometryReader{_ in
                ScrollView(.vertical, showsIndicators: false) {
                    VStack(spacing: 0) {
                        
                        ForEach(1...4, id: \.self) {i in
                            HStack(spacing: 0) {
                                Spacer().frame(width: 16)
                                Image("code_\(i)")
                                    .resizable()
                                    .aspectRatio(contentMode: .fit)
                                    .frame(height: 200)
                                    .cornerRadius(15)
                                    .padding(.top)
                                    .padding(.horizontal)
                                Spacer().frame(width: 16)
                            }
                        }
                        
                    }
                }.padding(.bottom, 18)
            }
            .background(Color.white)
        }
    }
    
    struct Scape: View {
        var body: some View {
            
            GeometryReader{_ in
                
                ScrollView(.vertical, showsIndicators: false) {
                    VStack(spacing: 0) {
                        
                        ForEach(1...5, id: \.self) {i in
                            HStack(spacing: 0) {
                                Spacer().frame(width: 16)
                                Image("scape_\(i)")
                                    .resizable()
                                    .aspectRatio(contentMode: .fill)
                                    .frame(height: 200)
                                    .cornerRadius(15)
                                    .padding(.top)
                                    .padding(.horizontal)
                                Spacer().frame(width: 16)
                            }
                        }
                        
                    }
                }.padding(.bottom, 18)
            }
            .background(Color.white)
        }
    }
    

    相关文章

      网友评论

        本文标题:SwiftUI 实现 Segment Tab

        本文链接:https://www.haomeiwen.com/subject/uauemltx.html