[Flutter]QRのバーコードスキャンをカスタマイズ!CustomQrBorderで背景透明化とボーダー表示を両立する方法
はじめに
FlutterでQRコードスキャナーを実装する際、デザインのカスタマイズで悩むことがありませんか?特に、背景を透明にしつつ、スキャンエリアのボーダーを美しく表示したい場合、標準的な方法では限界があります。
この記事では、qr_code_scanner
パッケージの制約を克服し、カスタムボーダーを実装する方法を詳しく解説します。
問題点:標準的な実装の限界
通常、QRコードスキャナーでオーバーレイを透明にしようとすると、以下のような実装になります:
QrScannerOverlayShape(
cutOutSize: 250,
overlayColor: Colors.transparent,
),
しかし、この方法には大きな問題があります。overlayColor: Colors.transparent
にしてしまうと、ボーダーまで消えてしまい、背景を透明にしつつボーダーを残すことができません。
これでは、ユーザーがスキャンエリアを認識しにくくなってしまいます。
解決策:CustomQrBorderの提案
そこで提案するのが、CustomQrBorderを使用したカスタム実装です。この方法を使うことで、背景を透明にしつつボーダーを残すことができます。
実装方法
実装の核心は、Stackで重ねて呼び出すことです:
return Stack(
children: [
QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
cutOutSize: 250,
overlayColor: Colors.transparent,
),
onPermissionSet: (ctrl, p) => _onPermissionSet(context, ctrl, p),
),
Align(
alignment: Alignment.center,
child: CustomPaint(
painter: CustomQrBorder(
borderColor: AppColors.corporateColorLight,
borderWidth: 10,
borderRadius: 20,
borderLength: 50,
cutOutSize: 250,
),
child: const SizedBox(),
),
)
],
);
この実装により、QRViewの上にCustomPaintを重ねて、カスタムボーダーを描画しています。
CustomQrBorderの詳細解説
クラス構成
CustomQrBorderはCustomPainter
を継承したクラスで、以下のパラメータを持ちます:
class CustomQrBorder extends CustomPainter {
CustomQrBorder({
this.borderColor = Colors.teal, // ボーダーの色
this.borderWidth = 4.0, // ボーダーの太さ
this.borderRadius = 8.0, // 角の丸み
this.borderLength = 30, // L字の長さ
this.cutOutSize = 250, // スキャンエリアのサイズ
});
}
パラメータの詳細
-
borderColor: ボーダーの色を指定。テーマカラーの
AppColors.corporateColorLight
を使用することで、アプリ全体のデザインとの一貫性を保てます - borderWidth: ボーダーの太さ。視認性を考慮して10pxに設定
- borderRadius: 角の丸み。現代的なデザインに合わせて20pxに設定
- borderLength: L字型ボーダーの長さ。50pxでバランスの良い表示
- cutOutSize: スキャンエリアのサイズ。QRViewの設定と合わせる必要があります
描画ロジック
CustomQrBorderの描画処理は以下の手順で行われます:
1. ペイント設定
final borderPaint = Paint()
..color = borderColor
..style = PaintingStyle.stroke
..strokeWidth = borderWidth
..strokeCap = StrokeCap.round; // 角を丸くする
StrokeCap.round
により、線の端を丸くして洗練された見た目にしています。
2. スキャンエリアの計算
final cutOutRect = Rect.fromCenter(
center: Offset(size.width / 2, size.height / 2),
width: cutOutSize,
height: cutOutSize,
);
画面中央を基準に正方形のスキャンエリアを定義します。
3. 4つのL字型ボーダーの描画
各コーナーにL字型のボーダーを描画します:
左上のL字
final topLeftPath = Path()
..moveTo(cutOutRect.left, cutOutRect.top + borderLength)
..lineTo(cutOutRect.left, cutOutRect.top + borderRadius)
..arcToPoint(
Offset(cutOutRect.left + borderRadius, cutOutRect.top),
radius: Radius.circular(borderRadius),
)
..lineTo(cutOutRect.left + borderLength, cutOutRect.top);
右上のL字
final topRightPath = Path()
..moveTo(cutOutRect.right - borderLength, cutOutRect.top)
..lineTo(cutOutRect.right - borderRadius, cutOutRect.top)
..arcToPoint(
Offset(cutOutRect.right, cutOutRect.top + borderRadius),
radius: Radius.circular(borderRadius),
)
..lineTo(cutOutRect.right, cutOutRect.top + borderLength);
左下と右下のL字も同様に、clockwise: false
パラメータを使用して反時計回りのアーチを描画しています。
再描画の最適化
shouldRepaint(covariant CustomQrBorder oldDelegate) {
return oldDelegate.borderColor != borderColor ||
oldDelegate.borderWidth != borderWidth ||
oldDelegate.borderRadius != borderRadius ||
oldDelegate.borderLength != borderLength ||
oldDelegate.cutOutSize != cutOutSize;
}
bool
パラメータが変更された場合のみ再描画することで、パフォーマンスを最適化しています。
実装時のポイント
1. カラーの統一
borderColor: AppColors.corporateColorLight,
アプリのテーマカラーを使用することで、デザインの一貫性を保ちます。
2. サイズの同期
QRViewのcutOutSize
とCustomQrBorderのcutOutSize
を同じ値(250)に設定することが重要です。
3. Stackの順序
QRViewを先に配置し、その上にCustomPaintを重ねることで、カメラ映像の上にボーダーが描画されます。
実装のメリット
- デザインの自由度: 標準のQrScannerOverlayShapeでは不可能な、背景透明化とボーダー表示の両立
- カスタマイズ性: 色、太さ、角の丸み、サイズなど全てカスタマイズ可能
- パフォーマンス: CustomPainterによる効率的な描画
- テーマ対応: AppColorsを使用することで、ダークモード等のテーマ変更に対応
まとめ
CustomQrBorderを使用することで、QRコードスキャナーのデザインを大幅に改善できます。標準的な実装では実現できない、背景透明化とボーダー表示の両立が可能になり、ユーザーエクスペリエンスの向上につながります。
この実装パターンは、他のカスタムオーバーレイにも応用できるため、ぜひ参考にしてみてください。
Discussion