📄

Building a Card with Action Feedback in SwiftUI

This article was automatically translated from theJapanese original by AI. It may contain translation errors.

This post was published over 2 years ago. Its content may be outdated.

Introduction

I’ve started learning SwiftUI, so I tried building a card that animates when tapped. I’m keeping this as a record of my learning.

Here’s how it turned out. screen

Building It

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            VStack(spacing: 16) {
                CardView(icon: "star.fill", title: "Title 1", description: "This is a description.")
                CardView(icon: "heart.fill", title: "Title 2", description: "This is a description.")
                CardView(icon: "bolt.fill", title: "Title 3", description: "This is a description.")
            }
            .padding()
            .navigationTitle("Rich")
        }
    }
}

struct CardView: View {
    let icon: String
    let title: String
    let description: String
    
    var body: some View {
        HStack {
            Image(systemName: icon)
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: 50, height: 50)
                .foregroundColor(.blue)
                .padding()
            
            VStack(alignment: .leading) {
                Text(title)
                    .font(.headline)
                    .fontWeight(.bold)
                
                Text(description)
                    .font(.subheadline)
                    .foregroundColor(.gray)
            }
            .padding(.leading, 8)
            
            Spacer()
        }
        .background(Color.white)
        .cornerRadius(10)
        .shadow(color: Color.gray.opacity(0.2), radius: 5, x: 0, y: 5)
        .padding(.horizontal)
        .onTapGesture {
            // Handle the tap on the button
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Once you’ve written this much, it looks like this.

screen2

Adding the Animation

Now that we’ve got this far, let’s add the animation.


struct CardView: View {
    let icon: String
    let title: String
    let description: String
    let height: CGFloat
+   @State private var isPressed = false
    
    var body: some View {
        HStack {
            Image(systemName: icon)
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: 50, height: 50)
                .foregroundColor(.blue)
                .padding()
            
            VStack(alignment: .leading) {
                Text(title)
                    .font(.headline)
                    .fontWeight(.bold)
                
                Text(description)
                    .font(.subheadline)
                    .foregroundColor(.gray)
            }
            .padding(.leading, 8)
            
            Spacer()
        }
        .frame(height: height)
        .background(Color.white)
        .cornerRadius(15)
        .shadow(color: Color.gray.opacity(0.2), radius: 5, x: 0, y: 5)
        .padding(.horizontal)
-        .onTapGesture {
-            // Handle the tap on the button
-        }
+        .scaleEffect(isPressed ? 1.05 : 1.0)
+        .animation(.spring(response: 0.3, dampingFraction: 0.6, blendDuration: 0.2), value: isPressed)
+        .onTapGesture {
+            withAnimation {
+                isPressed.toggle()
+            }
+            DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
+                withAnimation {
+                    isPressed.toggle()
+                }
+            }
+        }
    }
}

Build this, and you should get an animation that plays when you tap the card, like this!

screen

Recent Articles

Network(beta)

Drag to move / Ctrl+wheel to zoom