Home > Back-end >  How to create spinning wheel like view with cards
How to create spinning wheel like view with cards

Time:10-24

I want to create something like this view: enter image description here

I want the view to let the blue border cycle trough the cards and stop at a random integer value and highlight the current card that has the border by making it a little bigger. I'm new to animating with swift and don't know where to start.

This is my current code for the view:

struct Card: Identifiable, Hashable {
    
    func hash(into hasher: inout Hasher) {
            hasher.combine(id)
            hasher.combine(name)
        }
    
    let id: String = UUID().uuidString
    var cardBackGroundColor: Color
    var image: Image
    var name: String
}

struct PriceRollView: View {
    @State var cards = [Card(cardBackGroundColor: ColorConstants.turquoise, image: Image("vacation"), name: "Hawaii vacation"),
                        Card(cardBackGroundColor: ColorConstants.lightPink, image: Image("suit"), name: "Tailored suit"), Card(cardBackGroundColor: ColorConstants.lightYellow, image: Image("shoes"), name: "Sneaker"), Card(cardBackGroundColor: ColorConstants.darkPink, image: Image("watch"), name: "Classic Chronometer"), Card(cardBackGroundColor: ColorConstants.purple, image: Image("car"), name: "Sports car"), Card(cardBackGroundColor: ColorConstants.turquoise, image: Image("airplane"), name: "Private jet flight"), Card(cardBackGroundColor: ColorConstants.darkPink, image: Image("smartWatch"), name: "Smart watch"), Card(cardBackGroundColor: ColorConstants.lightYellow, image: Image("coliseum"), name: "Italy vacation")]
    let columns = [
        GridItem(.flexible()),
        GridItem(.flexible()),
        GridItem(.flexible())
    ]
    var body: some View {
        VStack {
            Text("Rolling for your price...").foregroundColor(ColorConstants.darkBlue)
            LazyVGrid(columns: columns, spacing: 12) {
                    ForEach(cards, id: \.self) { card in
                        VStack(alignment: .center) {
                            card.image
                                .resizable()
                                .scaledToFit()
                            Text(card.name)
                                .foregroundColor(ColorConstants.darkBlue)
                                .lineLimit(1)
                                .minimumScaleFactor(0.5)
                        }
                        .padding(12)
                        .frame(width: (ScreenConstants.width - 48) / 3, height: (ScreenConstants.width - 48) / 3)
                        .background(card.cardBackGroundColor)
                        .cornerRadius(4)
                    }
                }.padding(.leading, 12)
                    .padding(.trailing, 12)
                    .padding(.top, ScreenConstants.hasNotch ? 12 : 20)
            Spacer()
        }.statusBar(hidden: true)
    }
}

CodePudding user response:

You can do so using a Timer:

struct TestView: View {
    @State var index = 0
    let timer = Timer.publish(every: 0.5, on: .main, in: .common).autoconnect()
    var body: some View {
        LazyVGrid(columns: [.init(), .init(), .init()]) {
            ForEach(0..<10) { index in
                Text("Hiii\(index)")
                    .background(index == self.index ? Color.blue: .red)
                    .cornerRadius(4)
            }
        }.onReceive(timer) { _ in
            withAnimation(.default) {
                if index == 9 {
                    index = 0
                }else {
                    index  = 1
                }
            }
        }
    }
}

In the onReceive closure, you set the next item to be highlighted a State variable, and in the ForEach you check if the value matches the current one & modify the content as you want.

  • Related