SwiftUIで、FlashCardを作ってみた
Swaipeすると横にスライドするUI
SwiftUIで、スワイプすると、横にスライドするUIを作りたかった。YouTubeで検索すると、動画色々出てくるが自分の作りたいものと違った😅
こんな感じのものを作ってみた!
アニメーションの機能も必要なようだ...
流石にわからなかったので、AIに試しにサンプルを作らせてみた。
イメージと違うな。カードを横にスワイプスるとカードが斜めに動いて、切り替わるようにしてほしい。アニメーションが必要なのか?
ご指摘ありがとうございます。確かに、よりダイナミックなアニメーションを加えることで、ユーザー体験を向上させることができますね。カードを横にスワイプすると斜めに動いて切り替わるアニメーションを実装しましょう。
はい、このような動きを実現するにはアニメーションが必要です。SwiftUIのwithAnimationとgestureを組み合わせて、より洗練された動きを作り出すことができます。
では、先ほどのコードを修正して、要望に沿ったアニメーションを追加しましょう。
import SwiftUI
struct Flashcard: Identifiable {
let id = UUID()
let title: String
let content: String
}
struct ContentView: View {
@State private var flashcards = [
Flashcard(title: "コーヒーショップの場所", content: "Where is the coffee shop after exiting the station?"),
Flashcard(title: "レストランの予約", content: "I'd like to make a reservation for dinner."),
Flashcard(title: "電車の乗り方", content: "How do I take the train to the city center?"),
Flashcard(title: "観光スポットの推薦", content: "Can you recommend some popular tourist attractions?"),
Flashcard(title: "ホテルのチェックイン時間", content: "What time is check-in at the hotel?")
]
@State private var currentIndex = 0
@State private var offset: CGSize = .zero
@State private var backgroundColor = Color.random
var body: some View {
VStack {
Spacer()
ZStack {
ForEach(0..<flashcards.count) { index in
if index == currentIndex {
flashcardView(for: index)
.offset(offset)
.rotationEffect(.degrees(Double(offset.width / 5)))
.gesture(
DragGesture()
.onChanged { gesture in
offset = gesture.translation
}
.onEnded { gesture in
withAnimation(.spring()) {
if abs(gesture.translation.width) > 100 {
offset = CGSize(width: gesture.translation.width > 0 ? 1000 : -1000, height: 0)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
changeCard(gesture.translation.width > 0 ? -1 : 1)
}
} else {
offset = .zero
}
}
}
)
}
}
}
Spacer()
}
}
func flashcardView(for index: Int) -> some View {
VStack {
Text(flashcards[index].title)
.font(.headline)
.padding()
Text(flashcards[index].content)
.font(.body)
.padding()
}
.frame(width: 300, height: 200)
.background(backgroundColor)
.cornerRadius(10)
.shadow(radius: 5)
}
func changeCard(_ direction: Int) {
currentIndex = (currentIndex + direction + flashcards.count) % flashcards.count
offset = .zero
backgroundColor = Color.random
}
}
extension Color {
static var random: Color {
return Color(
red: .random(in: 0...1),
green: .random(in: 0...1),
blue: .random(in: 0...1)
)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
このコードでの主な変更点と新機能は以下の通りです:
- カードのスワイプアニメーション:
offsetとrotationEffectを使用して、カードがスワイプ中に移動し回転するようにしました。
スワイプが一定距離を超えると、カードが画面外に飛び出すアニメーションを追加しました。
- カード切り替えのロジック:
スワイプが終了したときに、スワイプの距離に基づいてカードを切り替えるか元の位置に戻すかを決定します。
カードが切り替わる際に、新しいカードが表示されるまでの短い遅延を追加しました。
- 背景色の変更:
カードが切り替わるたびに新しいランダムな背景色を設定します。
- ZStackの使用:
現在のカードのみを表示するようにZStackを使用しています。これにより、スワイプ中に次のカードが見えることを防いでいます。
このアプリケーションでは、カードを横にスワイプすると、カードが斜めに動いて切り替わります。スワイプの距離が十分でない場合は、カードが元の位置に戻ります。
また、カードが切り替わるたびに背景色がランダムに変更されるので、視覚的な変化も楽しめます。
このコードをSwiftUIプロジェクトに組み込んで実行すると、要望に沿ったダイナミックなフラッシュカードアプリケーションが動作するはずです。何か追加の機能や修正点があればお知らせください。
感想
もっと美しいUIを作っている人はいるが、動きがあるカードがあれば、十分だったので、今回はこんな感じにした。くるくる回りながら、スライドとかもありそう?
みていても疲れないものにしたいですね。
アニメーションがあるリッチなアプリケーションができる。
Discussion