Thursday, February 1, 2024
HomeiOS Developmentios - Scroll to merchandise with animation concern

ios – Scroll to merchandise with animation concern


In a scrollview with LazyHStack, I am operating into a problem with easily scrolling a tapped merchandise into view. That is the animation Im attempting to attain:

enter image description here

Observe that the merchandise hovered on above easily expands into view with objects shifting on both aspect.

My scrollview merchandise is structured such that it expands with animation on faucet. Nevertheless for a scroll view merchandise that’s partially seen, I am unable to have it develop in addition to scroll fully into view.

My code is as follows:

struct CarouselItem: Identifiable, Equatable {
    non-public(set) var id: UUID = .init()
    var title: String
    var yr: String
    var runtime: String
    var certification: String
    var posterImage: String
    var stillImage: String
}

struct CarousalItemView: View {
    @State var merchandise: CarouselItem
    @Binding var selectedItem: CarouselItem?
    @Namespace non-public var namespace
    non-public var expanded: Bool {
        merchandise.id == selectedItem?.id
    }
    
    var physique: some View {
        VStack(alignment: .main) {
            ZStack {
                Picture(merchandise.posterImage)
                    .resizable()
                    .scaledToFill()
                    .scaleEffect(expanded ?  1.5 : 1, anchor: .topLeading)
                    .body(width: expanded ? 250 : 150, peak: 200)
                    .matchedGeometryEffect(id: "picture", in: namespace, anchor: .topLeading, isSource: true)
                    .opacity(expanded ? 0 : 1)
                    .animation(.easeOut(period: 0.3), worth: expanded)
                
                Picture(merchandise.stillImage)
                    .resizable()
                    .scaledToFill()
                    .body(width: expanded ? 250 : 150, peak: 200)
                    .matchedGeometryEffect(id: "picture", in: namespace, anchor: .topLeading, isSource: false)
                    .opacity(expanded ? 1 : 0)
                    .animation(.easeInOut(period: 0.2).delay(expanded ? 0.1 : 0), worth: expanded)
                    .overlay(alignment: .main) {
                        if expanded {
                            itemDetailsView()
                        }
                    }
            }
            .clipShape(RoundedRectangle(cornerRadius: 10))

            Textual content(merchandise.title)
                .body(peak: 50)
        }
    }
    
    @ViewBuilder func itemDetailsView() -> some View {
        VStack(alignment: .main, spacing: 15) {
            Spacer()
            Textual content(merchandise.title)
                .font(.title2)
            HStack {
                Textual content("CBFC: " + merchandise.certification)
                    .padding(.horizontal, 5)
                    .overlay {
                        Rectangle()
                            .stroke(.white, lineWidth: 1)
                    }
                Textual content(merchandise.runtime)
                Textual content(merchandise.yr)
            }
            .shadow(colour: .grey, radius: 5, y: 5)
            Button {

            } label: {
                Textual content("Trailer")
            }
            .buttonStyle(.borderedProminent)
            .tint(.grey)
            .padding(.backside, 15)
        }
        .padding(.horizontal, 10)
    }
}

struct ContentView: View {
    var objects: [CarouselItem] = [
        .init(title: "Oppenheimer", year: "2023", runtime: "3h 1m", certification: "UA", posterImage: "poster1", stillImage: "still1"),
        .init(title: "Barbie", year: "2023", runtime: "1h 54m", certification: "PG", posterImage: "poster2", stillImage: "still2"),
        .init(title: "The Martian", year: "2015", runtime: "2h 24m", certification: "UA", posterImage: "poster3", stillImage: "still3"),
        .init(title: "The Shawshank Redemption", year: "1994", runtime: "2h 22m", certification: "U", posterImage: "poster4", stillImage: "still4"),
        .init(title: "The Godfather", year: "1972", runtime: "2h 55m", certification: "UA", posterImage: "poster5", stillImage: "still5"),
        .init(title: "The Dark Knight", year: "2008", runtime: "2h 32m", certification: "UA", posterImage: "poster6", stillImage: "still6")
    ]
    @State var selectedItem: CarouselItem?
    var physique: some View {
        VStack {
            HStack {
                Textual content("In style movies")
                    .font(.title2.daring())
                Spacer()
            }
            
            // MARK: Carousal
            ScrollViewReader { proxy in
                ScrollView(.horizontal) {
                    LazyHStack(spacing: 20) {
                        ForEach(objects, id: .id) { merchandise in
                            CarousalItemView(merchandise: merchandise, selectedItem: $selectedItem)
                                .body(width: selectedItem?.id != merchandise.id ? 150 : 250, peak: 250)
                                .clipShape(RoundedRectangle(cornerRadius: 10))
                                .contentShape(Rectangle())
                                .onTapGesture {
                                    DispatchQueue.major.async {
                                        withAnimation {
                                            if selectedItem?.id == merchandise.id {
                                                selectedItem = nil
                                            } else {
                                                selectedItem = merchandise
                                                guard let merchandise = selectedItem else { return }
                                                proxy.scrollTo(merchandise.id, anchor: .heart)
                                            }
                                        }
                                    }
                                }
                        }
                    }
                }
                .body(peak: 250)
                .scrollIndicators(.hidden)
                .clipped()
            }
            Spacer()
        }
        .padding()
        .background {
            Colour(.darkGray).ignoresSafeArea()
        }
        .foregroundStyle(.white)
    }
}

Within the code above, the animation is type of jerky particularly if an merchandise is expanded and is partially seen on the left & proper edges.
Any assistance is appreciated.



Supply hyperlink

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments