I want to create something like this view:
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.