課題
Flutterで三角形のボタンが作りたくなった。
↓こういうの。
canvasで描けばすぐなんだけど、
タップイベント付与とかボタンっぽいアニメーションとか考えるの面倒だったので、
普通のElevatedButtonを何とか三角にできないか頑張った。
意外とハマったし、意外と情報が無かったので一応まとめておきます。
完成品
完璧な三角形はなんか無理でした。
canvasで頑張って描画するしかないかも?
代わりに、ロケット状のボタンならできた。
↓こんな感じ。
見てくれ的には三角形にしたかったけど、
よく考えたら三角形のボタンってタップできる範囲が狭くなって不便なので、
見てくれとユーザビリティを秤にかけたらこの形が最適ですね。
ということで妥協した。
以下ソースです。
//上向きのロケット状ボタン
Container(
margin: EdgeInsets.only(bottom: 10),
width: 50,
height: 40,
child: ElevatedButton(
child: const Text('上'),
style: ElevatedButton.styleFrom(
shape: BeveledRectangleBorder(
borderRadius: BorderRadius.only(
//左上を削る
topLeft: Radius.circular(double.infinity),
//右上を削る
topRight: Radius.circular(double.infinity),
),
),
),
onPressed: () {
//タップした時の処理
}),
),
//下向きのロケット状ボタン
Container(
width: 50,
height: 40,
child: ElevatedButton(
child: const Text('下'),
style: ElevatedButton.styleFrom(
shape: BeveledRectangleBorder(
borderRadius: BorderRadius.only(
//左下を削る
bottomLeft: Radius.circular(double.infinity),
//左下を削る
bottomRight: Radius.circular(double.infinity),
),
),
),
onPressed: () {
//タップした時の処理
}),
),
詳細
-
ElevatedButtonの四角のうち、一部だけ面取りしたい場合は「BorderRadius.only」を使う。
-
BorderRadius.onlyではtopLeft、topRight、bottomLeft、bottomRightの四角に対してそれぞれ面取りサイズを設定できる。
-
面取りサイズの上限は、ボタンのサイズによって自動的に制限がかかるらしい。
なのでdouble.infinity(double型の最大値)を指定しておけば、
自動的に限界まで面取りしてくれてエラーにもならない。
borderRadius: BorderRadius.only(
//左上を削る
topLeft: Radius.circular(double.infinity),
//右上を削る
topRight: Radius.circular(double.infinity),
//左下を削る
bottomRight: Radius.circular(double.infinity),
//右下を削る
bottomRight: Radius.circular(double.infinity),
),
応用編
BorderRadius.onlyの組み合わせ次第で、左向きや右向き、菱形、変な形など割と自由自在に楽しめました。
左右
//左向きは左上、左下を削る
borderRadius: BorderRadius.only(
topLeft: Radius.circular(double.infinity),
bottomLeft: Radius.circular(double.infinity),
),
//右向きは右上、右下を削る
borderRadius: BorderRadius.only(
topRight: Radius.circular(double.infinity),
bottomRight: Radius.circular(double.infinity),
),
菱形
//菱形は全ての角を削る(この場合はBorderRadius.allでOK)
borderRadius: BorderRadius.all(Radius.circular(double.infinity),
何かに使えそうで使えない変な形
//スタイリッシュ!
borderRadius: BorderRadius.only(
topRight: Radius.circular(double.infinity),
bottomLight: Radius.circular(double.infinity),
),