[Flutter] ContainerとDecoratedBoxのBoxDecoration.borderの違いについて
FlutterでContainer.decoration
とDecoratedBox.decoration
のBoxDecoration.border
に微妙な違いがあったので、紹介しておきます。
BoxDecoration.borderについて
BoxDecoration.border
は、子Widgetに枠線を表示させます。以下のように書くと、枠線が表示されます。
Container(
decoration: BoxDecoration(
border: Border.all(),
),
child: const Text('枠線が表示されます'),
),
枠線はContainer.decoration
、またはDecoratedBox.decoration
にBoxDecoration.border
を指定することで表示できます。
Linterからの指摘
実は、先程のコードだとLinterから指摘を受けます。それがこちらです。
Container
の中身が子以外にdecoration
のみの場合、DecoratedBox
を使用することが推奨されます。Container
はconstコンストラクタを持たないため、むやみに使うとパフォーマンス的によろしくないのです。そのため、constコンストラクタを持つDecoratedBox
が推奨されるのですね。
// 引数が子以外にdecorationのみの場合はLinterによって指摘される
Container(
decoration: BoxDecoration(
border: Border.all(),
),
child: const Text('枠線が表示されます'),
),
// Linterでこちらを推奨される
DecoratedBox(
decoration: BoxDecoration(
border: Border.all(),
),
child: const Text('枠線が表示されます'),
),
描画の違いについて
私はLinterに従い、もともとContainer
にしていた箇所をDecoratedBox
に置き換えていました。しかし置き換えてアプリをビルドしてみると、描画に微妙な違いがあったのです。
それがこちら↓
※分かりやすいよう枠線を太くしています。
Container
では子Widgetの外側に枠線が入るのに対し、DecoratedBox
では子Widgetの内側に枠線が入ります。コードは以下の通りです。
return Column(
children: [
Container(
decoration: BoxDecoration(
border: Border.all(
width: 10,
),
),
child: const Text(
'枠線が表示されます',
style: TextStyle(fontSize: 50),
),
),
const SizedBox(height: 20),
DecoratedBox(
decoration: BoxDecoration(
border: Border.all(
width: 10,
),
),
child: const Text(
'枠線が表示されます',
style: TextStyle(fontSize: 50),
),
),
],
),
解決策
「Container
はなるべく使いたくない!」「Linterの通りにしたい!」という人は、DecoratedBox
の子にPadding
を置きましょう。Border
の幅と同じ値をPadding
で設定すれば、Container
を使った時と同じ見た目になります。
書き換えたコードはこちらです
const _borderWidth = 10.0;
return Column(
children: [
Container(
decoration: BoxDecoration(
border: Border.all(
width: 10,
),
),
child: const Text(
'枠線が表示されます',
style: TextStyle(fontSize: 50),
),
),
const SizedBox(height: 20),
DecoratedBox(
decoration: BoxDecoration(
border: Border.all(
width: _borderWidth,
),
),
// Paddingを挟み、Borderと同じ値を入れる
child: const Padding(
padding: EdgeInsets.all(_borderWidth),
child: Text(
'枠線が表示されます',
style: TextStyle(fontSize: 50),
),
),
),
],
),
以上になります。
Linterで推奨するなら、DecoratedBox
だけで同じ描画をしろ!って話ですよね。
最後までご覧いただき、ありがとうございました。
Flutter勉強中の身です。何か間違いがありましたらコメントいただけると幸いです。
Discussion
コメント失礼します!
少し補足させていただきます!
解決策として
_borderWidth
をPadding
に渡すという方法を取られている点についてです!この方法は、
EdgeInsets.all
では対応可能ですが、.symmetric
や.only
などの対応が難しいです!なので、
Container
に余白が生まれる理由と同じアプローチをとることで、これらを解決する方法を提案します!Decoration.padding
Container で padding が適応されている理由
Decoration
からPadding を取得している箇所