♥️
Flutterで、Flash Cardを作ってみた
スワイプすると動くカード
Flutterで、Flash Cardを自作してみた。スワイプすると横に動くカードですね。実装するには、アニメーションを使う必要があるみたいですね。
ダミーのデータをリストに格納して、ランダムな色のカードに表示するデモアプリを作ってみました。
これが、サンプルコード
import 'package:flutter/material.dart';
import 'dart:math';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Flashcard App',
theme: ThemeData(primarySwatch: Colors.blue),
home: const FlashcardScreen(),
);
}
}
class Flashcard {
final String title;
final String content;
Flashcard({required this.title, required this.content});
}
class FlashcardScreen extends StatefulWidget {
const FlashcardScreen({super.key});
_FlashcardScreenState createState() => _FlashcardScreenState();
}
class _FlashcardScreenState extends State<FlashcardScreen>
with SingleTickerProviderStateMixin {
final List<Flashcard> 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?"),
];
int currentIndex = 0;
late AnimationController _controller;
late Animation<Offset> _animation;
late Animation<double> _rotationAnimation;
Color backgroundColor = _getRandomColor();
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 300), vsync: this);
_animation = Tween<Offset>(begin: Offset.zero, end: const Offset(1.5, 0.0))
.animate(_controller);
_rotationAnimation = Tween<double>(begin: 0, end: 0.1).animate(_controller);
}
void dispose() {
_controller.dispose();
super.dispose();
}
void _nextCard() {
setState(() {
if (currentIndex < flashcards.length - 1) {
currentIndex++;
} else {
currentIndex = 0;
}
backgroundColor = _getRandomColor();
});
}
void _previousCard() {
setState(() {
if (currentIndex > 0) {
currentIndex--;
} else {
currentIndex = flashcards.length - 1;
}
backgroundColor = _getRandomColor();
});
}
static Color _getRandomColor() {
return Color((Random().nextDouble() * 0xFFFFFF).toInt() << 0)
.withOpacity(1.0);
}
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onHorizontalDragUpdate: (details) {
_controller.value += details.primaryDelta! / context.size!.width;
},
onHorizontalDragEnd: (details) {
if (_controller.value > 0.5) {
_controller.forward().then((_) {
_controller.reset();
_previousCard();
});
} else if (_controller.value < -0.5) {
_controller.forward().then((_) {
_controller.reset();
_nextCard();
});
} else {
_controller.reverse();
}
},
child: Center(
child: AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Transform.rotate(
angle: _rotationAnimation.value,
child: SlideTransition(
position: _animation,
child: _buildCard(),
),
);
},
),
),
),
);
}
Widget _buildCard() {
return Container(
width: 300,
height: 200,
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(10),
boxShadow: const [
BoxShadow(
color: Colors.black26,
blurRadius: 5,
offset: Offset(0, 5),
),
],
),
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
flashcards[currentIndex].title,
style: const TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
Text(
flashcards[currentIndex].content,
style: const TextStyle(color: Colors.white, fontSize: 16),
textAlign: TextAlign.center,
),
],
),
),
);
}
}
- フラッシュカードのデータモデル:
Flashcardクラスを使用してフラッシュカードのデータを定義しています。
- カードのスワイプアニメーション:
AnimationController、SlideTransition、Transform.rotateを使用して、カードのスワイプと回転アニメーションを実装しています。
- ランダムな背景色:
カードが切り替わるたびに_getRandomColor()メソッドを使用して新しい背景色を生成します。
- スワイプによるカード切り替え:
GestureDetectorを使用してスワイプジェスチャーを検出し、カードを切り替えます。
- カードのレイアウト:
Containerウィジェットを使用して、カードのデザインと影を実装しています
感想
SwiftUIで同じようなデモアプリを作ってみたのですが、同じiOSでもAndroidと同じ、左から、右へスワイプする動きをしていましたね。動くスピードもぬる〜として遅いような。。。。
リッチなUIにするなら、改良が必要ですね。
Discussion