※本記事は下記のZenn本にまとめました。
目標
カスタマイズ描画基本はCustomPaintの継承して描画しますが、今回はShapeBorderを継承してdecorationのshapeで装飾したいと思います。
ShapeBorder継承
5つの抽象メソッドがあります。
import 'package:flutter/material.dart';
class TicketBorder extends ShapeBorder{
@override
// TODO: implement dimensions
EdgeInsetsGeometry get dimensions => throw UnimplementedError();
@override
Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
// TODO: implement getInnerPath
throw UnimplementedError();
}
@override
Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
// TODO: implement getOuterPath
throw UnimplementedError();
}
@override
void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {
// TODO: implement paint
}
@override
ShapeBorder scale(double t) {
// TODO: implement scale
throw UnimplementedError();
}
}
枠線を描く
pain関数のパラメーターにcanvasとrect持っているため、装飾対象のcanvas操作やrect情報を取得できます。それを利用してチケットの白い枠線を作りたいと思います。
@override
void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {
var paint = Paint()
..color = Colors.white
..strokeWidth = 2.0
..style = PaintingStyle.stroke;
var w = rect.width;
var h = rect.height;
canvas.drawRect(Rect.fromPoints(const Offset(40, 25), Offset(w - 40, h - 25)), paint);
}
borderの枠を設けないと、エラーになるから、矩形を作っておきます。
@override
Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
Path path = Path();
// 矩形枠
path.addRect(rect);
return path;
}
穴を切り取る
// 左上
path.lineTo(40, 0);
path.arcToPoint(
const Offset(0, 40),
radius: const Radius.circular(40),
);
path.fillType = PathFillType.evenOdd;
ギザギザを作る
double radius = 4;
int holeCount = (h - 80) ~/ (radius * 2);
for (int i = 0; i < holeCount; i++) {
if (i % 2 == 0) {
path.addArc(
Rect.fromCircle(center: Offset(0, 44 + i * radius * 2), radius: radius),
pi / 2,
pi,
);
} else {
path.addArc(
Rect.fromCircle(center: Offset(0, 44 + i * radius * 2), radius: radius),
-pi / 2,
pi,
);
}
}
雑ですが、これでチケットの模様を作りました。
ソースは下記のGithubをご参考ください。