Flutter 使用Painter类向容器添加自定义装饰
我知道我可以装饰我的容器,然后为它提供一个边框。 但是我正在尝试使用自定义绘制类用一些自定义边框来包装我的Flutter 使用Painter类向容器添加自定义装饰,flutter,Flutter,我知道我可以装饰我的容器,然后为它提供一个边框。 但是我正在尝试使用自定义绘制类用一些自定义边框来包装我的容器,自定义绘制类应该围绕或向容器提供一个边框,就像一个虚线边框或任何自定义形状边框一样 注意:-请不要建议我使用任何自定义软件包,如虚线边框,我希望答案采用自定义画师的形式,如BoxPainter类等。 到目前为止,我已经写了这个code import'dart:math'; 进口“包装:颤振/材料.省道”; 类CustPaint扩展了无状态小部件{ @凌驾 小部件构建(构建上下文){ 返
容器
,自定义绘制类应该围绕或向容器
提供一个边框
,就像一个虚线
边框
或任何自定义形状边框一样
注意:-请不要建议我使用任何自定义软件包,如虚线边框,我希望答案采用自定义画师的形式,如BoxPainter类等。
到目前为止,我已经写了这个code
import'dart:math';
进口“包装:颤振/材料.省道”;
类CustPaint扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回脚手架(
正文:中(
子:容器(
宽度:300,
身高:300,
装饰:自定义装饰(),
孩子:新图标(Icons.wb_sunny),
)),
);
}
}
阶级装饰延伸了装饰{
@凌驾
BoxPainter createBoxPainter([void Function()onChanged]){
返回BoxDecorationPainter();
}
}
类BoxDecorationPainter扩展了BoxPainter{
@凌驾
虚空绘制(画布、偏移、图像配置){
最终矩形边界=偏移量和配置.size;
_绘画装饰(帆布、镶边);
}
}
void\u drawDecoration(帆布,矩形尺寸){
变量半径=最小值(尺寸.宽度/2,尺寸.高度/2);
var circleRaidus=半径*.012;
var paint=paint()
…color=Colors.teal
..strokeWidth=circleRaidus*.5
…风格=绘画风格笔划
..strokeCap=strokeCap.round;
对于(int i=0;i<60;i++){
偏移量topRight=偏移量(size.left+i*4,size.top);
左下偏移=偏移(size.left,size.top+i*4);
偏置底部右=偏置(size.left+i*4,size.bottom);
向下偏移=偏移(size.right,size.top+i*4);
画布。画圈(右上角,画圈*2,绘画);
画布.画圈(右下角,圆圈*2,油漆);
画布.画圈(右下,画圈*2,绘画);
画布.画圈(左下,画圈*2,绘画);
}
}
我所取得的成就是
但是输出
行
(带小圆圈)都应该连接在一起,并且当遇到角
到角
时,它们之间不应该有间隙
。(意味着它们应该连接起来,像正方形或矩形一样覆盖容器)圆圈之间留出一些空间
一些填充
圆圈
可以
替换为任何图像
提前感谢必须根据盒子的大小调整圆圈的数量:
final nbShapes = [
((bounds.width + gap) / (shapeSize + gap)).floor(),
((bounds.height + gap) / (shapeSize + gap)).floor(),
];
在我的解决方案中,CustomDecorationBox可以配置为:
,形状的大小双形状大小
,两个形状之间的间隙双形状贴图
,用于绘制形状的绘制(支持笔划和填充绘制)绘制形状绘制
,一个绘制形状的函数shapePAINTERPAINTSHAPE
paintCircle()
paintRectangle()
,一家n-gon画家工厂ShapePainter创建NgoNpainter(int n)
完整源代码:
import 'dart:math';
import 'package:flutter/material.dart';
typedef ShapePainter = void Function(Canvas, Rect, Paint);
Random random = Random();
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'CustomDecoration Demo',
home: Scaffold(
body: MyWidget(),
),
),
);
}
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) {
final size = Size(1, .6) * constraints.biggest.width;
print(size);
return GridView.count(
crossAxisCount: 3,
children: List.generate(
120,
(index) => Padding(
padding: EdgeInsets.all(size.width * .01),
child: Container(
decoration: CustomDecoration(
shapeSize: 5.0 + random.nextInt(10),
shapeGap: 2.0 + random.nextInt(3),
shapePaint: Paint()
..color = Color(0x99000000 + random.nextInt(0xffffff))
..strokeWidth = random.nextInt(3).toDouble()
..style = random.nextInt(3) == 2
? PaintingStyle.fill
: PaintingStyle.stroke,
paintShape: random.nextInt(4) == 0
? paintCircle
: createNGonPainter(3 + random.nextInt(5)),
),
child: Center(
child: Text(
index.toString(),
style: TextStyle(fontSize: 24.0),
),
),
),
),
),
);
},
),
);
}
}
class CustomDecoration extends Decoration {
final double shapeSize;
final double shapeGap;
final Paint shapePaint;
final ShapePainter paintShape;
CustomDecoration({
this.shapeSize,
this.shapeGap,
this.shapePaint,
this.paintShape,
}) : super();
@override
BoxPainter createBoxPainter([void Function() onChanged]) {
return BoxDecorationPainter(
shapeSize: shapeSize ?? 10,
shapeGap: shapeGap ?? 4,
shapePaint: shapePaint ?? Paint(),
paintShape: paintShape ?? paintCircle);
}
}
class BoxDecorationPainter extends BoxPainter {
final double shapeSize;
final double shapeGap;
final Paint shapePaint;
final ShapePainter paintShape;
BoxDecorationPainter({
this.shapeSize,
this.shapeGap,
this.shapePaint,
this.paintShape,
}) : super();
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
final Rect bounds = offset & configuration.size;
_drawDecoration(canvas, bounds, shapeSize, shapeGap);
}
void _drawDecoration(
Canvas canvas, Rect bounds, double shapeSize, double gap) {
final nbShapes = [
((bounds.width + gap) / (shapeSize + gap)).floor(),
((bounds.height + gap) / (shapeSize + gap)).floor(),
];
final correctedGaps = [
(bounds.width - nbShapes[0] * shapeSize) / (nbShapes[0] - 1),
(bounds.height - nbShapes[1] * shapeSize) / (nbShapes[1] - 1),
];
final steps = [
correctedGaps[0] + shapeSize,
correctedGaps[1] + shapeSize,
];
for (int i = 0; i < nbShapes[0]; i++) {
paintShape(
canvas,
Rect.fromLTWH(
bounds.left + steps[0] * i,
bounds.top,
shapeSize,
shapeSize,
),
shapePaint,
);
paintShape(
canvas,
Rect.fromLTWH(
bounds.left + steps[0] * i,
bounds.bottom - shapeSize,
shapeSize,
shapeSize,
),
shapePaint,
);
}
for (int i = 1; i < nbShapes[1] - 1; i++) {
paintShape(
canvas,
Rect.fromLTWH(
bounds.left,
bounds.top + steps[1] * i,
shapeSize,
shapeSize,
),
shapePaint,
);
paintShape(
canvas,
Rect.fromLTWH(
bounds.right - shapeSize,
bounds.top + steps[1] * i,
shapeSize,
shapeSize,
),
shapePaint,
);
}
}
}
void paintCircle(Canvas canvas, Rect bounds, Paint paint) {
canvas.drawCircle(
Offset(
bounds.left + bounds.width / 2,
bounds.top + bounds.height / 2,
),
bounds.shortestSide / 2,
paint,
);
}
void paintRectangle(Canvas canvas, Rect bounds, Paint paint) {
canvas.drawRect(bounds, paint);
}
ShapePainter createNGonPainter(int n) => (canvas, bounds, paint) {
Path path = Path();
path.moveTo(
bounds.left + (bounds.width + cos(2 * pi / n) * bounds.width) / 2,
bounds.top + (bounds.height + sin(2 * pi / n) * bounds.height) / 2,
);
for (var k = 2; k <= n; k++) {
path.lineTo(
bounds.left + (bounds.width + cos(2 * k * pi / n) * bounds.width) / 2,
bounds.top +
(bounds.height + sin(2 * k * pi / n) * bounds.height) / 2,
);
}
path.close();
canvas.drawPath(path, paint);
};
import'dart:math';
进口“包装:颤振/材料.省道”;
typedef ShapePainter=无效函数(画布、矩形、绘制);
随机=随机();
void main(){
runApp(
材料聚丙烯(
debugShowCheckedModeBanner:false,
标题:“定制装饰演示”,
家:脚手架(
正文:MyWidget(),
),
),
);
}
类MyWidget扩展了无状态Widget{
@凌驾
小部件构建(构建上下文){
返回脚手架(
正文:布局生成器(
生成器:(上下文、约束){
最终尺寸=尺寸(1.6)*约束。最大。宽度;
印刷品(尺寸);
返回GridView.count(
交叉轴计数:3,
子项:List.generate(
120,
(索引)=>填充(
填充:所有边缘设置(尺寸.宽度*.01),
子:容器(
装饰:定制装饰(
形状大小:5.0+随机。下一个(10),
shapeGap:2.0+随机。nextInt(3),
shapePaint:Paint()
…color=color(0x99000000+random.nextInt(0xffffff))
..strokeWidth=random.nextInt(3).toDouble()
…样式=随机。下一个(3)==2
?油漆方式。填充
:PaintingStyle.stroke,
paintShape:random.nextInt(4)=0
?画圈
:createNGonPainter(3+random.nextInt(5)),
),
儿童:中心(
子:文本(
index.toString(),
样式:TextStyle(fontSize:24.0),
),
),
),
),
),
);
},
),
);
}
}
阶级装饰延伸了装饰{
最终的双形化;
最后的双形图;
最终油漆成型漆;
最终形状中间油漆形状;
定制装饰({
这是shapeSize,
这是shapeGap,
这是shapePaint,
这是我的画形,
}):super();
@凌驾
BoxPainter createBoxPainter([void Function()onChanged]){
返回框装饰油漆工(
形状尺寸:形状尺寸±10,
shapeGap:shapeGap?4,
shapePaint:shapePaint??Paint(),
paintShape:paintShape??paintCircle);
}
}
箱形装饰类
import 'dart:math';
import 'package:flutter/material.dart';
typedef ShapePainter = void Function(Canvas, Rect, Paint);
Random random = Random();
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'CustomDecoration Demo',
home: Scaffold(
body: MyWidget(),
),
),
);
}
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) {
final size = Size(1, .6) * constraints.biggest.width;
print(size);
return GridView.count(
crossAxisCount: 3,
children: List.generate(
120,
(index) => Padding(
padding: EdgeInsets.all(size.width * .01),
child: Container(
decoration: CustomDecoration(
shapeSize: 5.0 + random.nextInt(10),
shapeGap: 2.0 + random.nextInt(3),
shapePaint: Paint()
..color = Color(0x99000000 + random.nextInt(0xffffff))
..strokeWidth = random.nextInt(3).toDouble()
..style = random.nextInt(3) == 2
? PaintingStyle.fill
: PaintingStyle.stroke,
paintShape: random.nextInt(4) == 0
? paintCircle
: createNGonPainter(3 + random.nextInt(5)),
),
child: Center(
child: Text(
index.toString(),
style: TextStyle(fontSize: 24.0),
),
),
),
),
),
);
},
),
);
}
}
class CustomDecoration extends Decoration {
final double shapeSize;
final double shapeGap;
final Paint shapePaint;
final ShapePainter paintShape;
CustomDecoration({
this.shapeSize,
this.shapeGap,
this.shapePaint,
this.paintShape,
}) : super();
@override
BoxPainter createBoxPainter([void Function() onChanged]) {
return BoxDecorationPainter(
shapeSize: shapeSize ?? 10,
shapeGap: shapeGap ?? 4,
shapePaint: shapePaint ?? Paint(),
paintShape: paintShape ?? paintCircle);
}
}
class BoxDecorationPainter extends BoxPainter {
final double shapeSize;
final double shapeGap;
final Paint shapePaint;
final ShapePainter paintShape;
BoxDecorationPainter({
this.shapeSize,
this.shapeGap,
this.shapePaint,
this.paintShape,
}) : super();
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
final Rect bounds = offset & configuration.size;
_drawDecoration(canvas, bounds, shapeSize, shapeGap);
}
void _drawDecoration(
Canvas canvas, Rect bounds, double shapeSize, double gap) {
final nbShapes = [
((bounds.width + gap) / (shapeSize + gap)).floor(),
((bounds.height + gap) / (shapeSize + gap)).floor(),
];
final correctedGaps = [
(bounds.width - nbShapes[0] * shapeSize) / (nbShapes[0] - 1),
(bounds.height - nbShapes[1] * shapeSize) / (nbShapes[1] - 1),
];
final steps = [
correctedGaps[0] + shapeSize,
correctedGaps[1] + shapeSize,
];
for (int i = 0; i < nbShapes[0]; i++) {
paintShape(
canvas,
Rect.fromLTWH(
bounds.left + steps[0] * i,
bounds.top,
shapeSize,
shapeSize,
),
shapePaint,
);
paintShape(
canvas,
Rect.fromLTWH(
bounds.left + steps[0] * i,
bounds.bottom - shapeSize,
shapeSize,
shapeSize,
),
shapePaint,
);
}
for (int i = 1; i < nbShapes[1] - 1; i++) {
paintShape(
canvas,
Rect.fromLTWH(
bounds.left,
bounds.top + steps[1] * i,
shapeSize,
shapeSize,
),
shapePaint,
);
paintShape(
canvas,
Rect.fromLTWH(
bounds.right - shapeSize,
bounds.top + steps[1] * i,
shapeSize,
shapeSize,
),
shapePaint,
);
}
}
}
void paintCircle(Canvas canvas, Rect bounds, Paint paint) {
canvas.drawCircle(
Offset(
bounds.left + bounds.width / 2,
bounds.top + bounds.height / 2,
),
bounds.shortestSide / 2,
paint,
);
}
void paintRectangle(Canvas canvas, Rect bounds, Paint paint) {
canvas.drawRect(bounds, paint);
}
ShapePainter createNGonPainter(int n) => (canvas, bounds, paint) {
Path path = Path();
path.moveTo(
bounds.left + (bounds.width + cos(2 * pi / n) * bounds.width) / 2,
bounds.top + (bounds.height + sin(2 * pi / n) * bounds.height) / 2,
);
for (var k = 2; k <= n; k++) {
path.lineTo(
bounds.left + (bounds.width + cos(2 * k * pi / n) * bounds.width) / 2,
bounds.top +
(bounds.height + sin(2 * k * pi / n) * bounds.height) / 2,
);
}
path.close();
canvas.drawPath(path, paint);
};