📐
FlutterでWidgetがMaterial Designガイドラインに沿って配置されているか確認する方法
はじめに
Flutterで開発していると、Material Components ( package:flutter/material.dart
)を使うことが多いかと思います。
Components - Material Design
どうせなら、コンポーネント(以下、ウィジェット)の配置もMaterial Designのガイドライン(ウィジェットを8dp間隔のグリッドに揃える)に沿わせると、見た目綺麗で見やすくなるかと思います。
Spacing methods - Material Design
ですが、Flutter標準のデバッグ機能( Show debug paint
)では、ウィジェットが「8dp間隔のグリッド」(以下、グリッド)に沿っているか確認することはできません。
何かいい方法はないかな?とつぶやいたところ、 monoさんから次のようなアドバイスをいただきました。
か、賢い!ということで、グリッドを描画する汎用Widgetを作ってみました。
なお、作ったウィジェットはパッケージ化してこちらで公開しています。
material_spacing_checker | Flutter Package
この記事では、グリッドを描画するWidgetを作る方法について解説します。
アプローチ
アプローチ的には次の手順を取ります。
- 画面のサイズを取得する
- 画面サイズを元に、グリッドを描画する場合、縦横何本ずつ線を引けば良いか計算する
-
CustomPaint
を使ってグリッドを描画する -
Stack
を使って、グリッド(CustomPaint
)と他Widgetを重ね合わせる
それでは、こちらを実装していきます。
実装方法
まず、画面のサイズは、次のように取得することができます。
final screenSize = MediaQuery.of(context).size;
このscreenSize
を元に、縦横に引くべき線の本数を計算します。
/// 8dpグリッドを描画するCustomPainter
class _GridPaint extends CustomPainter {
_GridPaint({
this.screenSize,
});
final Size screenSize;
void paint(Canvas canvas, Size size) {
final lineSpacing = 8;
// 画面トップは4dp間隔を空けないと、グリッドがずれる
final topMargin = 4;
// +1しておかないと、線の数が足りないことがある
final horizontalLineCount = screenSize.width ~/ lineSpacing + 1;
final paint = Paint()
..color = Colors.red.withOpacity(0.7);
// 水平方向に線を引く
for (var i = 0; i < horizontalLineCount; i++) {
canvas.drawLine(
Offset(
(lineSpacing * i).toDouble(),
0,
),
Offset(
(lineSpacing * i).toDouble(),
screenSize.height,
),
paint,
);
}
// 垂直方向に線を引く
for (var i = 0; i < verticalLineCount; i++) {
canvas.drawLine(
Offset(
0,
(lineSpacing * i).toDouble() + topMargin,
),
Offset(
screenSize.width,
(lineSpacing * i).toDouble() + topMargin,
),
paint,
);
}
}
}
あとは、Stack
を使って重ね合わせれば、他Widget上にグリッドを描画できます。
Widget build(BuildContext context) {
final screenSize = MediaQuery.of(context).size;
return Stack(
children: [
child,// グリッドを重ね合わせたいWidget
CustomPaint(
painter: _GridPaint(
screenSize: screenSize,
),
)
],
);
}
実際に使ってみると、このような感じになります。
Discussion