如何在 SwiftUI 中制作带有自定义视图的可滑动分段控件?

问题描述 投票:0回答:1

我有一个分段控件,有两个分段,如图所示see image here。我想让用户通过向右或向左滑动在两个片段之间切换,并相应地显示相应的视图。我查阅了几篇文章,但没有找到实现此功能的解决方案。

我使用按钮来实现此功能,但我不确定如何启用滑动功能。

  1. 如何在 SwiftUI 中实现左或右 DragGesture() 触发 switch case?
  2. 如何使用 SwiftUI 在视图上检测向上、向下、向左和向右滑动
struct ScheduleView: View {
    // MARK: - Variables
    @State private var playerName: String = ""
    @State private var pastShown: Bool = false
    @State private var presentAlert: Bool = false
    @State private var goToGroupChat: Bool = false
    private var items = ["Upcoming", "Past"]
    
    var body: some View {
        NavigationView {
            ZStack {
                VStack {
                    HStack {
                        VStack(alignment: .leading) {
                            Text("Hello!,")
                                .robotoRegularFont(size: 14)
                                .foregroundColor(Color.custom64B054Color)
                            Text("John Andrew")
                                .robotoRegularFont(size: 14)
                                .foregroundColor(Color.custom333333Color)
                        }
                        Spacer()
                        Image("appIcon_icon")
                            .resizable()
                            .frame(width: 32, height: 32)
                    }
                    .padding(.top, 24)
                    
                    // MARK: - Upcoming and Past Views
                    VStack(spacing: 8) {
                        HStack(alignment: .center, spacing: 0) {
                            Spacer()
                            
                            // MARK: - Button Upcoming
                            ZStack {
                                Button {
                                    print("Upcoming action")
                                    self.pastShown = false
                                } label: {
                                    Text("Upcoming")
                                        .font(.custom(self.pastShown ? "Roboto-Light" : "Roboto-Medium", size: 15))
                                        .foregroundColor(self.pastShown ? .black.opacity(0.7) : .black)
                                }
                            }
                            .frame(width: UIScreen.main.bounds.width / 2 - 18)
                            Spacer()
                            Spacer()
                            
                            // MARK: - Button Past
                            ZStack {
                                Button {
                                    print("Past action")
                                    self.pastShown = true
                                } label: {
                                    Text("Past")
                                        .font(.custom(self.pastShown ? "Roboto-Medium" : "Roboto-Light", size: 15))
                                        .foregroundColor(self.pastShown ? .black : .black.opacity(0.7))
                                }
                            }
                            .frame(width: UIScreen.main.bounds.width / 2 - 18)
                            Spacer()
                        }
                        
                        let upcoming = Capsule()
                            .fill(Color.black.opacity(self.pastShown ? 0.2 : 1))
                            .frame(maxWidth: .infinity, maxHeight: 1.5)
                        let past = Capsule()
                            .fill(Color.black.opacity(self.pastShown ? 1 : 0.2))
                            .frame(maxWidth: .infinity, maxHeight: 1.5)
                        
                        HStack(alignment: .center, spacing: 0) {
                            upcoming
                            past
                        }
                    }
                    .padding(.top, 8)
                    .padding(.horizontal, -18)
                    
                    ScrollView(.vertical, showsIndicators: false) {
                        // MARK: - Past View
                        if self.pastShown {
                            Text("past")
                        } else {
                            // MARK: - Upcoming View
                            LazyVStack(spacing: 20) {
                                MatchInfoCell(playerType: "Doubles", skillRange: "minimum", noOfParticipants: "2/4", date: "Tues, Oct 25", time: "04:00 PM", court: "Tour Greens Houston Serves The Houston Area", isForSchedule: true, lookingButtonAction: {
                                    print("lookingButtonAction")
                                }, gameOnButtonAction: {
                                    print("gameOnButtonAction")
                                }, noGameButtonAction: {
                                    print("noGameButtonAction")
                                }, messageButtonAction: {
                                    print("messageButtonAction")
                                    self.goToGroupChat.toggle()
                                }, addGuestButtonAction: {
                                    print("addGuestButtonAction")
                                    withAnimation {
                                        self.presentAlert.toggle()
                                    }
                                })
                            }
                        }
                    }
                    .padding(.top)
                    .background(Color.clear)
                }
                .padding(.horizontal, 18)
                
                // MARK: - Custom Alert for Add Guest
                if self.presentAlert {
                    VStack {
                        CustomAlertView(alertTitle: "Are you sure you want to add a Guest in this match?", nonFilledButtonTitle: "No", filledButtonTitle: "Yes", nonFilledButtonAction: {
                            withAnimation {
                                self.presentAlert.toggle()
                            }
                        }, filledButtonAction: {
                            withAnimation {
                                self.presentAlert.toggle()
                            }
                        }, presentAlert: $presentAlert)
                    }
                }
                
                // MARK: - Navigate to Group Chat
                NavigationLink("", destination: GroupChatView().navigationBarHidden(true).navigationBarBackButtonHidden(true), isActive: $goToGroupChat)
            }
            .navigationBarHidden(true)
            .navigationBarBackButtonHidden(true)
        }
    }
}

如果有人可以为我提供如何实现这一目标的指导,我将不胜感激!

谢谢您!

swift swiftui uisegmentedcontrol segment swipe-gesture
1个回答
0
投票

因此,为了使其正常工作,我几乎使用了您的所有代码。 重要的部分是手势修改器:

.gesture(
            DragGesture()
                .onChanged({ value in
                    let translationX = value.translation.width
                    let velocity = abs(value.velocity.width)
                    let predictedEnd = value.predictedEndTranslation.width
                    print("Entered \(translationX), velocity \(velocity)")
                    if (translationX > 200 || predictedEnd > 200) && velocity > 500 {
                        withAnimation(.smooth) {
                            self.pastShown = false
                        }
                    } else if (translationX < -200 || predictedEnd > -200) && velocity > 500 {
                        withAnimation(.smooth) {
                            self.pastShown = true
                        }
                    }
                })
        )

根据需要尝试并调整这些值。 您可以将其添加到 ZStack 的末尾,其中嵌入了您的两个视图(即将到来的和过去的)。另外,您需要将此行添加到包含“过去”选项卡的 ScrollView 中:

.frame(maxWidth: .infinity, maxHeight: .infinity)

使它看起来像这样:

ScrollView(.vertical, showsIndicators: false) {
                    // MARK: - Past View
                    if self.pastShown {
                        Text("past")
                    } else {
                        // MARK: - Upcoming View
                        LazyVStack(spacing: 20) {
                           // Your code here
                        }
                    }
                }
                .padding(.top)
                .background(Color.clear)
                .frame(maxWidth: .infinity, maxHeight: .infinity) // <-- The new line

否则,拖动手势只会在屏幕上非常窄的条带上被检测到,从而导致滑动无法正常工作。 让我知道它是否适合您enter image description here

注意:我使用了红色背景,以便您更好地看到可滑动区域。

© www.soinside.com 2019 - 2024. All rights reserved.