💡
【Flutter】光っているボタンを作成した
はじめに
こちらのサイトで見つけた、以下の画像のような光っているようにみえるボタンをFlutterで作ってみました。
環境
flutter --version
Flutter 3.10.3 • channel stable • https://github.com/flutter/flutter.git
Framework • revision f92f44110e (3 months ago) • 2023-06-01 18:17:33 -0500
Engine • revision 2a3401c9bb
Tools • Dart 3.0.3 • DevTools 2.23.1
実装
光っているように見えるだけのボタン
まずは、光っているように見えるだけのボタンを作成しました。
import 'package:flutter/material.dart';
class CircleShineButton extends StatelessWidget {
const CircleShineButton({
Key? key,
required this.onTap,
this.icon = Icons.add,
this.size = 60,
this.color = Colors.white,
this.backgroundColor = Colors.black,
}) : super(key: key);
final Function onTap;
final IconData icon;
final double size;
final Color color;
final Color backgroundColor;
Widget build(BuildContext context) {
final blurRadius = useState(8.0);
return InkWell(
onTap: () {
onTap;
},
child: Material(
shape: CircleBorder(
side: BorderSide(
color: color,
),
),
color: Colors.transparent,
child: Container(
width: size,
height: size,
decoration: ShapeDecoration(
shadows: [
BoxShadow(
color: color,
offset: const Offset(0, 0),
blurRadius: 10,
),
BoxShadow(
color: backgroundColor,
offset: const Offset(0, 0),
blurRadius: 10,
),
],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(size / 2),
),
),
),
child: Icon(
icon,
color: color,
size: size / 2,
shadows: [
BoxShadow(
color: color,
offset: const Offset(0, 0),
blurRadius: 10,
),
],
),
),
),
);
}
}
Material
の子要素のContainer
の影を二つ重ねることで、真ん中がくり抜かれたように描画できています。
shadows: [
BoxShadow(
color: color,
offset: const Offset(0, 0),
blurRadius: 10,
),
BoxShadow(
color: backgroundColor,
offset: const Offset(0, 0),
blurRadius: 10,
),
],
また、Material
を追加しているのは、円を線で描画したかったためです。
child: Material(
shape: CircleBorder(
side: BorderSide(
color: color,
),
),
...
タップ時に光が広がるようにする。
blurRadius
の値を変数にして、ボタンダウン時に値を増やすことにする。
-
useState
を使いたいのでHookWidgetに変更しています。
- class CircleShineButton extends StatelessWidget {
+ class CircleShineButton extends HookWidget {//変更
+ final blurRadius = useState(8.0);//追加
- アイコンの方も
blurRadius.value
に変更します。
- blurRadius: 10,
+ blurRadius: blurRadius.value,
最後に、InkWell
のプロパティのonTapDown
を追加して、onTap
時に値を戻すようにする。
onTap: () {
+ blurRadius.value = 8.0;//追加
onTap;
},
+ onTapDown: (details) {
+ blurRadius.value = 10.0;
+ },//追加
これで完成。
コード全体
circle_shine_button.dart
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
class CircleShineButton extends HookWidget {
const CircleShineButton({
Key? key,
required this.onTap,
this.icon = Icons.add,
this.size = 60,
this.color = Colors.white,
this.backgroundColor = Colors.black,
}) : super(key: key);
final Function onTap;
final IconData icon;
final double size;
final Color color;
final Color backgroundColor;
Widget build(BuildContext context) {
final blurRadius = useState(8.0);
return InkWell(
onTap: () {
blurRadius.value = 8.0;
onTap;
},
onTapDown: (details) {
blurRadius.value = 10.0;
},
child: Material(
shape: CircleBorder(
side: BorderSide(
color: color,
),
),
color: Colors.transparent,
child: Container(
width: size,
height: size,
decoration: ShapeDecoration(
shadows: [
BoxShadow(
color: color,
offset: const Offset(0, 0),
blurRadius: blurRadius.value,
),
BoxShadow(
color: backgroundColor,
offset: const Offset(0, 0),
blurRadius: 10,
),
],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(size / 2),
),
),
),
child: Icon(
icon,
color: color,
size: size / 2,
shadows: [
BoxShadow(
color: color,
offset: const Offset(0, 0),
blurRadius: blurRadius.value,
),
],
),
),
),
);
}
}
最後に
今回作ったボタンを使うことで、UIが少しリッチになると思います。ぜひご参考ください。
ここまでご覧いただきありがとうございました。
Discussion