Enumを使ってTapするとemojiを切り替える
Dart3.0のEnum + Switchを使ってみる
時々Xでお見かけするSandroさんというマニアックなロジックを作る人のコードを見て、再現できないかな〜とやってるんですけど、今回もやってみました。
タップすると絵文字の背景に色がつく!
Enumとsealed classどっちがいいのかという議論をしているようです。
In some cases enum are better than sealed classes
✅ Less verbose
✅ Easier to read and use
✅ .values
to get list of enum
💡ダーツチップ💡
場合によっては、enum の方がシールされたクラス🎯
✅よりも優れています。
✅読みやすく使いやすくなりました
✅ enum のリストを取得する .values
Enumがこれで絵文字の切り替えに使います。
enum Emoji {
smile,
rocket,
dart;
String toString() => switch (this) {
Emoji.smile => "😀",
Emoji.rocket => "🚀",
Emoji.dart => "🎯",
};
}
sealed classがこれですね。最近使うの流行ってますけど、Enum
の方が良い場合もあるよと言ってるんだと思います。Kotlinにもsealed class
あって、Enum
みたいな使い方しますね。
sealed class Emoji {}
class Smile extends Emoji {
String toString() => "😀";
}
class Rocket extends Emoji {
String toString() => "🚀";
}
class Dart extends Emoji {
String toString() => "🎯";
}
絵文字を切り替えるボタンのコンポーネントを作成して、これをmapメソッドでWidget側に表示して使います。InkWell
を使ってTapするイベントが起きると、emojiの背景に色が付きます。
class EmojiButton extends StatelessWidget {
const EmojiButton(
{super.key,
required this.selected,
required this.emoji,
required this.onPressed});
final bool selected;
final Emoji emoji;
final void Function(Emoji) onPressed;
Widget build(BuildContext context) {
return Material(
color: selected
? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.surface,
shape: const CircleBorder(),
child: InkWell(
onTap: () => onPressed(emoji),
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(emoji.toString()),
),
),
);
}
}
このように、mapメソッドを使ってView側に生成する。意味間違ってるかもだけど。setState
を使って画面を更新して、emojiの背景に色がつく仕組みになってます。
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: Emoji.values
.map((e) => EmojiButton(
selected: e == selectedEmoji,
emoji: e,
onPressed: (emoji) => setState(() {
selectedEmoji = emoji;
}),
))
.toList(),
),
全体のコードはこちら:
import 'package:flutter/material.dart';
enum Emoji {
smile,
rocket,
dart;
String toString() => switch (this) {
Emoji.smile => "😀",
Emoji.rocket => "🚀",
Emoji.dart => "🎯",
};
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Emoji selectedEmoji = Emoji.smile;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: Emoji.values
.map((e) => EmojiButton(
selected: e == selectedEmoji, // 修正
emoji: e,
onPressed: (emoji) => setState(() {
selectedEmoji = emoji; // 修正
}),
))
.toList(),
),
],
),
),
);
}
}
class EmojiButton extends StatelessWidget {
const EmojiButton(
{super.key,
required this.selected,
required this.emoji,
required this.onPressed});
final bool selected;
final Emoji emoji;
final void Function(Emoji) onPressed;
Widget build(BuildContext context) {
return Material(
color: selected
? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.surface,
shape: const CircleBorder(),
child: InkWell(
onTap: () => onPressed(emoji),
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(emoji.toString()),
),
),
);
}
}
最後に
Sandroさんは、日本語も話せるらしくて以前🌸サクラの話題でトークしたことあります笑
いつもマニアックなロジック書いてるのみて、気になるのがあったら真似して書いてますね。
Xにはコードを書くアイディアが紹介されていることあるから見てみると、わ〜って驚く面白いコードがありますね。再現するのは難しいですが💦
Discussion