[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.paddingContainer で padding が適応されている理由
DecorationからPadding を取得している箇所