これが Flutter の場合、『キレイに』つけるのが地味に難題。
※一応だがキレイに書ける方法は一番下に載せてるので飛ばしても OK。
自分が思いつく実装方法は以下の 3 つ。
- BoxDecoration で image, border, borderRadius を指定
- BoxDecoration で border を表示、子をさらに ClipRRect で角丸クリップ
- CustomPaint で clip したりして頑張る
1, 2 を以下で試してみる。
1. BoxDecoration で image, border, borderRadius を指定
return Container(
width: 200,
height: 200,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage('https://i.picsum.photos/id/563/200/200.jpg'),
),
border: Border.all(color: Colors.white, width: 3),
borderRadius: BorderRadius.circular(10),
),
);
外側が若干汚い。どうやら 画像の丸角部分が少しはみ出してしまう ようだ。背景色やボーダーの色によってはごまかせるかもしれないが、場合によっては非常に目立ってしまう。
2. BoxDecoration で border を表示、子をさらに ClipRRect で角丸クリップ
return Container(
width: 200,
height: 200,
decoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 3),
borderRadius: BorderRadius.circular(10),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
clipBehavior: Clip.hardEdge,
child: Image.network('https://i.picsum.photos/id/563/200/200.jpg'),
),
);
今度は内側に緑の隙間が出来てしまった。これは border 分 child が小さくなった結果、角丸が合わなくなった ため。
2-2. 上記のコードを foregroundDecoration に変える
foregroundDecoration に設定すれば、その名の通り foreground にボーダーが書かれて、 child が縮まなくなる。
return Container(
width: 200,
height: 200,
foregroundDecoration: BoxDecoration(
やっぱり汚くなる。 1 は結果的にこれと同じことをしているのであろう。
2-3. 若干の padding を入れる(現状一番キレイ)
画像を若干内側に引っ込ませればいいんじゃないの? という発想で padding を加えてみる。
return Container(
width: 200,
height: 200,
foregroundDecoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 3),
borderRadius: BorderRadius.circular(10),
),
// 魔法の padding
padding: const EdgeInsets.all(0.5),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
clipBehavior: Clip.hardEdge,
child: Image.network('https://i.picsum.photos/id/563/200/200.jpg'),
),
);
うまくいった!
うまくいった……けどさ……うーん。
他にきれいなやり方が見つからなかったら後で Issue に投げてみる。
補足: わかりやすいように border width: 3 にしてるけど、↑のやり方は width: 1 でも一応キレイに表示できる。
補足2: ClipRRect の clipBehavior: Clip.hardEdge
は単に処理速度をちょっとでも上げたいという思いで設定している。デフォルトの antialias にしていても、 padding 入れないとやっぱりキレイにはならない。