前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >flutter自定义组件

flutter自定义组件

作者头像
韦东锏
发布2022-04-11 17:52:30
5070
发布2022-04-11 17:52:30
举报
文章被收录于专栏:Android码农Android码农

如何用canvas绘制我们任何想要任意图案的组件,这篇文章用自定义一个五角星组件来说明

CsutomPaint

自定义组件,建议用官方的CustomPaint来实现,先新建一个pantagram的类

代码语言:javascript
复制
class Pentagram extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()..color = Colors.black;
    final rect = Offset.zero & size;
    canvas.drawRect(rect, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

它是继承CustomPainter这个类,有两个方法,shouldRepaint先写死返回false,paint方法就是真实绘制的地方,这里先绘制一个黑色的矩形 然后在页面引用这个类

代码语言:javascript
复制
return Scaffold(              
  appBar: AppBar(             
    title: Text('Demo Page'), 
  ),                           
  body: Center(               
    child: CustomPaint(       
      painter: Pentagram(),   
    ),                         
  ),                           
);                             

运行后,发现页面是空白的,查看了下它的源码,发现是size的问题

代码语言:javascript
复制
const CustomPaint({            
  Key? key,                    
  this.painter,                
  this.foregroundPainter,      
  this.size = Size.zero, //尺寸默认是0       

size默认的尺寸是0,重新设置size后,显示正常了(个人觉得,默认的size用size.infinite更合理,充满父布局)

代码语言:javascript
复制
body: Container(            
  child: CustomPaint(       
    size: Size(150, 150),   
    painter: Pentagram(),   
  ),                         
),                           

使用自定义组件,绘制出了一块黑色的矩形了

绘制path

由于五角星属于特殊的图案,需要手动设置path,为了验证path的可行性,先绘制一个菱形来做验证

代码语言:javascript
复制
void paint(Canvas canvas, Size size) {       
  //把画笔设置成stroke模式                           
  final paint = Paint()                      
    ..color = Colors.black                   
    ..style = PaintingStyle.stroke           
    ..strokeWidth = 2;                       
  var rect = Offset.zero & size;             
  var center = rect.center;                  
  // 连接好菱形的四个顶点                              
  final path = Path();                       
  path.moveTo(center.dx, 0);                 
  path.lineTo(rect.right, center.dy);        
  path.lineTo(center.dx, rect.bottom);       
  path.lineTo(0, center.dy);                 
  path.close(); //最后用close的方式把path封闭起来       
  // 调用canvas绘制path                          
  canvas.drawPath(path, paint);              
}                                            

先把画笔设置成stroke模式,然后path连接好菱形的四个顶点,最后直接绘制即可,效果如下

菱形绘制好了,说明path的方案可行

绘制五角星

既然path方案可行,接来下就是确定五角星的五个顶点,用path连接起来,代码如下

代码语言:javascript
复制
Path getPentagramPath(double radius) {                         
  var initDegreen = 180;                                       
  // 连接五角星的五个顶点                                                
  final path = Path();                                         
  var posOne = getOffsetPosition(initDegreen, radius);         
  path.moveTo(posOne.dx, posOne.dy);                           
  // 360/5,每个是72度                                              
  var posTwo = getOffsetPosition(72 + initDegreen, radius);    
  path.lineTo(posTwo.dx, posTwo.dy);                           
  var posThree = getOffsetPosition(144 + initDegreen, radius); 
  path.lineTo(posThree.dx, posThree.dy);                       
  var posfour = getOffsetPosition(216 + initDegreen, radius);  
  path.lineTo(posfour.dx, posfour.dy);                         
  var posFive = getOffsetPosition(288 + initDegreen, radius);  
  path.lineTo(posFive.dx, posFive.dy);                         
  //最后用close的方式把path封闭起来                                       
  path.close();                                                
  return path;                                                 
}                                                              
                                                               
Offset getOffsetPosition(int degreen, double radius) {         
  //角度转成弧度                                                     
  var radian = degreen * pi / 180;                             
  var dx = sin(radian) * radius;                               
  var dy = cos(radian) * radius;                               
  return Offset(dx + radius, dy + radius);                     
}                                                                           

看下效果图

结果变成五边形了,不是我们要的五角星,需要把path的线条连接方式修改下

代码语言:javascript
复制
var initDegreen = 180;                                      
// 连接五角星的五个顶点,360/5,每个是72度                                  
final path = Path();                                        
var posOne = getOffsetPosition(initDegreen, radius);        
var posTwo = getOffsetPosition(72 + initDegreen, radius);   
var posThree = getOffsetPosition(144 + initDegreen, radius);
var posfour = getOffsetPosition(216 + initDegreen, radius); 
var posFive = getOffsetPosition(288 + initDegreen, radius); 
path.moveTo(posOne.dx, posOne.dy);                          
path.lineTo(posfour.dx, posfour.dy);                        
path.lineTo(posTwo.dx, posTwo.dy);                          
path.lineTo(posFive.dx, posFive.dy);                        
path.lineTo(posThree.dx, posThree.dy);                      
//最后用close的方式把path封闭起来                                      
path.close();                                               

这次终于看到我们需要的效果了

这个五角星,如果要用填充的方式展示,只需要把画笔style设置成fill即可

代码语言:javascript
复制
final paint = Paint()            
  ..color = Colors.black         
  ..style = PaintingStyle.fill;  

效果如下

传参

对于自定义组件,想要一些参数,是可以外部控制的,比如五角星的颜色,可以用外部传进来

代码语言:javascript
复制
class Pentagram extends CustomPainter {
  Pentagram(this.color);
  //画笔的颜色
  final Color color;

先定义好需要外部设置的参数,外部在使用的地方,把颜色设置进来

代码语言:javascript
复制
child: CustomPaint(                  
  size: Size(150, 150),          
  painter: Pentagram(Colors.black),  
),                                    

包括动态调整颜色和其他熟悉,也都可以实现了

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-03-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android码农 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • CsutomPaint
  • 绘制path
  • 绘制五角星
  • 传参
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档