Flutter fabの使い方を説明するために上に吹き出しをつける
言葉で説明しなくてもいいのがマテリアルデザインですが、 こういう依頼が来ることもたまにありますよね。
Bubbleもパッケージがあるのですが、矢印の部分(三角のところ)が自由に移動できなかったので、 自作しました。
import 'package:flutter/material.dart'; class Bubble extends StatelessWidget { Bubble({Key? key, required this.text, required this.textStyle}) : super(key: key); final String text; final TextStyle textStyle; @override Widget build(BuildContext context) { return Container( height: 100, padding: const EdgeInsets.only(left: 32, top: 16, right: 32, bottom: 8), // ここにconstつけるとhot reloadで変わらない decoration: ShapeDecoration( color: Colors.blue, shadows: [ BoxShadow( color: Color(0x80000000), offset: Offset(0, 2), blurRadius: 2, ) ], shape: BubbleBorder(), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( text, style: textStyle, ), ], ), ); } } class BubbleBorder extends ShapeBorder { final bool usePadding; const BubbleBorder({this.usePadding = true}); @override EdgeInsetsGeometry get dimensions => const EdgeInsets.all(0); @override Path getInnerPath(Rect rect, {TextDirection? textDirection}) => Path(); @override Path getOuterPath(Rect rect, {TextDirection? textDirection}) { return Path() // xは少なくなると左、多くなると右 // yは少なくなると上に移動する ..moveTo(rect.bottomCenter.dx + 28, rect.bottomCenter.dy) ..relativeLineTo(45, 16) ..relativeLineTo(6, -16) ..addRRect(RRect.fromRectAndRadius(rect, const Radius.circular(8))) ..close(); } @override void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {} @override ShapeBorder scale(double t) => this; }
上のコードを呼び出すmain
import 'package:flutter/material.dart'; import 'bubble.dart'; void main() { runApp(MaterialApp( home: MySca(), )); } class MySca extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('fabの上に吹き出し'), ), floatingActionButton: Column( crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.only(right: 0), child: Bubble( text: 'こちらを押すと新規登録です', textStyle: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18)), ), Padding( padding: const EdgeInsets.only(top: 16), child: FloatingActionButton( child: Icon(Icons.add), onPressed: () {}, )), ], ), body: SizedBox.shrink()); } }
https://github.com/na8esin/flutter2_practice/tree/main/lib/src/bubble