London Escorts sunderland escorts 1v1.lol unblocked yohoho 76 https://www.symbaloo.com/mix/yohoho?lang=EN yohoho https://www.symbaloo.com/mix/agariounblockedpvp https://yohoho-io.app/ https://www.symbaloo.com/mix/agariounblockedschool1?lang=EN
2 C
New York
Friday, January 31, 2025

ios – Keep away from “jumpy” animation when swipe between completely different pages in TabView


I’ve the next TabView

TabView(choice: $currentTab) {
    ForEach(0...(quizViewModel.quizzes.rely), id: .self) {
        if $0 < quizViewModel.quizzes.rely {
            quizSide(index: $0)
                .tag($0)
        } else {
            resultSide()
                .tag($0)
        }
    }
}
.tabViewStyle(.web page(indexDisplayMode: .by no means))
.indexViewStyle(.web page(backgroundDisplayMode: .all the time))

After I swipe from quizSide to a different quizSide, the animation is clean.

Clean animation

enter image description here

Nevertheless, once I swipe from quizSize to the final web page resultSide, or from final web page resultSide to quizSide, the animation is jumpy.


Jumpy animation

enter image description here

I believed the animation needs to be clean, as I’ve already utilized id and tag contained in the TabView.

Do you will have any concept why is is so? How I can keep away from such? This is the whole code snippet.

struct QuizView: View {
    @Atmosphere(.colorScheme) personal var colorScheme

    @Atmosphere(.dismiss) var dismiss
    
    @ObservedObject var quizViewModel: QuizViewModel
    
    @State personal var currentTab = 0
    
    @State personal var isSheetPresented = false
    
    personal let successBackgroundColor = Shade(hex: "388E3C")
    
    var physique: some View {
        NavigationView {
            VStack {
                if quizViewModel.quizzes.isEmpty {
                    VStack(spacing: 0) {
                        Textual content("quizzes_loading...")
                            .foregroundColor(.secondary)
                            .font(.title)
                        
                        LottieView(animation: .named("chat"))
                            .looping()
                            .body(width: 200, peak: 56)
                    }.padding(.horizontal, 16)
                } else {
                    
                    Spacer()
                    
                    TabView(choice: $currentTab) {
                        ForEach(0...(quizViewModel.quizzes.rely), id: .self) {
                            if $0 < quizViewModel.quizzes.rely {
                                quizSide(index: $0)
                                    .tag($0)
                            } else {
                                resultSide()
                                    .tag($0)
                            }
                        }
                    }
                    .tabViewStyle(.web page(indexDisplayMode: .by no means))
                    .indexViewStyle(.web page(backgroundDisplayMode: .all the time))
                    

                    // Navigation Buttons
                    HStack {
                        Button(motion: {
                            withAnimation {
                                currentTab = max(0, currentTab - 1)
                            }
                        }) {
                            Picture(systemName: "chevron.left.circle.fill")
                                .font(.system(dimension: 44))
                                .foregroundStyle(.white, .blue)
                        }
                        .opacity(currentTab > 0 ? 1 : 0.3)
                        
                        Spacer()
                        
                        if currentTab < quizViewModel.quizzes.rely {
                            Textual content(verbatim: "(currentTab+1) / (quizViewModel.quizzes.rely)")
                                .multilineTextAlignment(.middle)
                                .lineLimit(1)
                                .minimumScaleFactor(0.5)
                                .foregroundColor(.secondary)
                                .font(.physique)
                            
                            Spacer()
                        }
                        
                        Button(motion: {
                            withAnimation {
                                currentTab = min(quizViewModel.quizzes.rely, currentTab + 1)
                            }
                        }) {
                            Picture(systemName: "chevron.proper.circle.fill")
                                .font(.system(dimension: 44))
                                .foregroundStyle(.white, .blue)
                        }
                        .opacity(currentTab < quizViewModel.quizzes.rely ? 1 : 0.3)
                    }
                    .padding(.horizontal, 16)
                    .padding(.backside, 16)
                }
            }
            .navigationBarTitle("quiz", displayMode: .inline)
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button(motion: { dismiss() }) {
                        Picture(systemName: "xmark")
                            .imageScale(.medium)        // This matches UIKit's "medium" image scale
                            .foregroundColor(.main)  // This matches UIKit's "Label" colour
                    }
                }
            }
        }
        .navigationViewStyle(StackNavigationViewStyle()) // Power single-column navigation (iPad)
    }
}

extension QuizView {
    personal func resultSide() -> some View {
        VStack {
            Textual content(verbatim: "🥳")
                .foregroundColor(.main)
                .font(.largeTitle)
        }
        .body(maxWidth: .infinity, maxHeight: .infinity) // Ensures VStack fills the entire display
        .background(.pink) // Background now covers the whole display
    }
    
    personal func quizSide(index: Int) -> some View {
        VStack {
            let choice = quizViewModel.picks[index]
            
            let userMadeSelection = choice >= 0
            
            let quiz = quizViewModel.quizzes[index]
            
            if userMadeSelection {
                if let clarification = quiz.selections[selection].clarification, !clarification.isTrimmedEmpty {
                    
                    let right = choice == quiz.reply
                    
                    let backgroundColor: Shade = (right ? successBackgroundColor : Shade(UIColor.systemRed))
                        .opacity(colorScheme == .darkish ? 0.4 : 0.2)
                    
                    let content material =
                        Textual content(clarification)
                            .foregroundColor(.main)
                            .font(.physique)
                            .padding(.vertical, 8)
                            .padding(.horizontal, 16)
                            .body(maxWidth: .infinity, alignment: .main)
                            .quizCard(backgroundColor: backgroundColor, cornerRadius: 8)
                    
                    let textual content = Textual content("tap_for_explanation")
                        .foregroundColor(.blue) // Blue colour like a hyperlink
                        .underline() // Provides an underline
                        .font(.physique)
                        .onTapGesture {
                            isSheetPresented = true // Present the underside sheet
                        }
                    
                    ViewThatFits(in: .vertical) {
                        content material
                        textual content
                    }
                    .padding(.prime, 0)
                    .padding(.backside, 16)
                    .sheet(isPresented: $isSheetPresented) {
                        NavigationView {
                            content material
                            .toolbar {
                                ToolbarItem(placement: .navigationBarTrailing) {
                                    Button(motion: {
                                        isSheetPresented = false
                                    }) {
                                        Picture(systemName: "xmark")
                                            .imageScale(.medium) // Matches UIKit's "medium" image scale
                                            .foregroundColor(.main) // Matches UIKit's "Label" colour
                                    }
                                }
                            }
                        }
                        .presentationDetents([.medium])
                    }
                }
            }
            
            VStack {
                HStack(alignment: .prime) {
                    Textual content(verbatim: "(index + 1). ")
                        .foregroundColor(.main)
                        .font(.title3)
                        .fontWeight(.daring)
                    Textual content(verbatim: "(quiz.query)")
                        .foregroundColor(.main)
                        .minimumScaleFactor(0.5)
                        .font(.title3)
                        .fontWeight(.medium)
                        .lineLimit(3)
                        .multilineTextAlignment(.main)
                }
                .body(maxWidth: .infinity, alignment: .main)
                .padding(.backside, 8)

                
                ForEach(Array(quiz.selections.enumerated()), id: .offset) { buttonIndex, selection in
                    Button(motion: {
                        quizViewModel.picks[index] = buttonIndex
                    }) {
                        let right = buttonIndex == quiz.reply
                        let chosen = choice == buttonIndex
                        
                        let foregroundColor: Shade = right ? Shade("successTextColor") : Shade(UIColor.systemRed)
                        
                        HStack(alignment: .middle) {
                            Textual content(selection.textual content)
                                .foregroundColor(.main)
                                .minimumScaleFactor(0.5)
                                .font(.title3)
                                .lineLimit(2)
                                .multilineTextAlignment(.main)
                            
                            Spacer()
                            
                            let systemName = right ? "checkmark.circle.fill" : "xmark.circle.fill"
                            let opacity = right ? (userMadeSelection ? 1.0 : 0.0) : (chosen ? 1.0 : 0.0)
                            
                            Picture(systemName: systemName)
                                .font(.system(dimension: 22))
                                .foregroundStyle(.white, foregroundColor)
                                .opacity(opacity)
                        }
                        .padding(.vertical, 8)
                        .padding(.horizontal, 16)
                        .body(maxWidth: .infinity, minHeight: 56, alignment: .main)
                        .background(Shade.grey.opacity(0.2))
                        .cornerRadius(8)
                        .overlay(
                            chosen ?
                            RoundedRectangle(cornerRadius: 8)
                                .stroke(foregroundColor, lineWidth: 2)
                            : nil
                        )
                    }
                }
            }
            .padding(.vertical, 24)
            .padding(.horizontal, 16)
            .quizCard()
            .padding(.backside, 16)
            // https://stackoverflow.com/questions/56507497/views-compressed-by-other-views-in-swiftui-vstack-and-list
            .fixedSize(horizontal: false, vertical: true)
        }
        .body(maxHeight: .infinity, alignment: .backside)
    }
}

Related Articles

Social Media Auto Publish Powered By : XYZScripts.com