flutter 绘制的基本使用

本文介绍了Flutter使用CustomPainter进行图形绘制,包括drawLine、drawRect、drawCircle、drawArc等方法。通过示例展示了如何创建表格、填充形状、绘制点和圆弧,帮助理解绘画API的基本用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇文章中,简单介绍了使用CustomPainter实现一个简单的画板demo,其中只是对于drawLine画线做了应用,这篇文章,再去学习一下painting中的其他方法。

这里提一下,自定义的CustomPainter需要放在CustomPaint中才能展示,赋值给painter属性,CustomPainter也还有一个child

const CustomPaint({
    Key key,
    this.painter,
    this.foregroundPainter,
    this.size = Size.zero,
    this.isComplex = false,
    this.willChange = false,
    Widget child,
  })

先看第一个例子,画一个表格,作为我们后续学习的背景,这里还试了一下加一个child之后的效果,就是下面右侧那个效果图

Widget build(BuildContext context) {
    return Container(
      child: Center(
          
        child: CustomPaint(
          painter: GirdPainter(10),
          size: Size(300, 300),
          child: new Text('dataaaaaaaaaaaaaa'),
        ),
      ),
    );
  }

可以看到child和我们绘制的东西是重叠的

                                          

画表格的代码如下,就比较简单了,还是drawLine

class GirdPainter extends CustomPainter {
  int count;
  GirdPainter(this.count);
  @override
  void paint(Canvas canvas, Size size) {
    double w = size.width / count;
    double h = size.height / count;
    Paint _paint = new Paint()
    ..color = Colors.yellow[100]
    ..style = PaintingStyle.stroke
    ..strokeWidth = 1.0;
    // TODO: implement paint
    for (var i = 0; i <= count; i++) {
      double dx = w * i;
      double dy = h * i;
      //画横线
      canvas.drawLine(Offset(0, dy), Offset(size.width, dy), _paint);

      canvas.drawLine(Offset(dx, 0), Offset(dx, size.height), _paint);
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return false;
  }
  
}

顺便说一下style属性,是个枚举,只有两个值,fill是用来填充的,stroke是用来画线的,需要制定一下线的宽度(strokeWidth)

enum PaintingStyle {
  
  fill,

  
  stroke,
}

接下来试一下fill的效果,画一个矩形

void paint(Canvas canvas, Size size) {
    double w = size.width / count;
    double h = size.height / count;
    Paint _bgPaint = new Paint()
    ..color = Colors.blue
    ..style = PaintingStyle.fill;
    canvas.drawRect(Offset.zero & size, _bgPaint);

  }

这里需要了解一下drawRect(Rect rect, Paint paint)的第一个参数Rect的构建:

// 利用矩形左边的X坐标、矩形顶部的Y坐标、矩形右边的X坐标、矩形底部的Y坐标确定矩形的大小和位置

Rect.fromLTRB(doubleleft, doubletop, doubleright, doublebottom)
// 利用矩形的左边的X轴、顶边的Y轴位置配合设置矩形的长和宽来确定矩形的大小和位置

Rect.fromLTWH(doubleleft, doubletop, doublewidth, doubleheight)
// 利用矩形的中心点和矩形所在圆的半径来确定矩形的大小和位置,此方法确定的是一个正方形

Rect.fromCircle({ Offset center, doubleradius })
// 利用矩形的左上角和右下角的坐标确定矩形的大小和位置
// 需要注意的是两点坐标中,如果X轴相同或者Y轴相同,确定的是一条线,
// 如果两点XY坐标都是同一个数字,确定的是一个点。

Rect.fromPoints(Offset a, Offset b) 

学习到这里突然想起来,还从来没有画过点呢,直接就开始画线,画矩形了,还是得试试点是咋画的?,就在刚才这个蓝色矩形上画几个试试吧

List<Offset> points = [
      Offset(0, 0),
      Offset(30, 50),
      Offset(20, 80),
      Offset(100, 40),
      Offset(150, 90),
      Offset(60, 110),
      Offset(260, 160),
    ];
    var _pointPaint = Paint()
      ..color = Color(0xFFFf0000)
      ..strokeWidth = 5;

    canvas.drawPoints(PointMode.points, points, _pointPaint);

这里PointMode 也是个枚举 ,有三个值,想知道都是啥意思呢?把每个都试试就知道了?

enum PointMode {
 
  points,

  
  lines,


  polygon,
}

看三个枚举分别的效果图,是不是就一目了然了,然后我们继续~

再画个圆,给个圆心和半径

var _circlePaint = new Paint()
    ..color = Colors.red
    ..strokeWidth = 2
    ..style = PaintingStyle.stroke;
    canvas.drawCircle(Offset(100, 100), 50, _circlePaint);

会画圆了再试着画一段圆弧,先看下画圆弧需要的参数

// rect:矩形区域

// startAngle:开始的弧度

// sweepAngle:扫过的弧度,正数顺时针,负数逆时针

// useCenter:是否使用中心点绘制 如果usecenter为真,则弧为
///回到中心,形成一个圆扇形。否则,弧为
///未闭合,形成圆段。

void drawArc(Rect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint) {
    assert(_rectIsValid(rect));
    assert(paint != null);
    _drawArc(rect.left, rect.top, rect.right, rect.bottom, startAngle,
             sweepAngle, useCenter, paint._objects, paint._data);
  }

说了一堆,不如自己画一个看的更明白? 因为弧度要设计到π 所以先

import 'dart:math';
var _circlePaint = new Paint()
    ..color = Colors.red
    ..strokeWidth = 2
    ..style = PaintingStyle.stroke;
    var rect = Rect.fromCircle(center: Offset(100.0, 100.0), radius: 50.0);
    canvas.drawArc(rect, 0, pi/2, false, _circlePaint);

          

 

学习到这里,简单基础的绘制基本上结束了,然后还有贝塞尔曲线的绘制,巴拉巴拉啥的,以后有空再去学习,毕竟数学学得也一般般~

 

<think>我们正在使用Flutter生成和绘制二维码。根据引用[1]和[2],我们可以使用qr_flutter包来实现。以下是步骤: 1. 添加依赖:在pubspec.yaml文件中添加qr_flutter依赖,并执行flutter pub get。 2. 导入包:在Dart文件中导入qr_flutter包。 3. 使用QrImageView组件:该组件提供了生成二维码的功能,并可以设置各种属性。 根据引用[2],我们可以设置二维码的版本、容错级别、大小、颜色、内边距等,还可以在中心嵌入图片。 下面是一个基本示例: ```dart import 'package:flutter/material.dart'; import 'package:qr_flutter/qr_flutter.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('QR Code Example')), body: Center( child: QrImageView( data: 'https://example.com', // 二维码数据 version: QrVersions.auto, // 自动选择版本 size: 200.0, // 大小 foregroundColor: Colors.black, // 前景色(二维码颜色) backgroundColor: Colors.white, // 背景色 // 可选:嵌入中心图片 embeddedImage: AssetImage('assets/logo.png'), embeddedImageStyle: QrEmbeddedImageStyle( size: Size(40, 40), // 嵌入图片的大小 ), ), ), ), ); } } ``` 注意:如果要嵌入中心图片,需要将图片放在项目中(例如assets目录),并在pubspec.yaml中配置assets。 另外,引用[3]提到了使用CustomPaint绘制二维码扫描框,但生成二维码我们使用qr_flutter包即可。绘制扫描框可以自定义,但这不是生成二维码,而是扫描界面的绘制。 引用[4]提到了绘制优化,但这里我们主要关注二维码的生成和显示。 总结:使用qr_flutter包可以方便地生成和绘制二维码,支持自定义样式和嵌入图片。 §§相关问题§§ 1. 如何在Flutter中扫描二维码? 2. 如何自定义二维码的样式(如形状、颜色渐变等)? 3. 二维码生成时如何处理长文本(自动选择版本)?</think>在 Flutter 中生成和绘制二维码,推荐使用 `qr_flutter` 包,它提供了高度可定制的二维码生成功能。以下是详细实现步骤: ### 步骤 1:添加依赖 在 `pubspec.yaml` 中添加依赖: ```yaml dependencies: qr_flutter: ^4.0.0 flutter_svg: ^2.0.5 # 可选,用于导出SVG格式 ``` 执行 `flutter pub get` ### 步骤 2:基础二维码生成 ```dart import 'package:flutter/material.dart'; import 'package:qr_flutter/qr_flutter.dart'; class QRGenerator extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Center( child: QrImageView( data: 'https://example.com', // 二维码内容 size: 200, // 尺寸 backgroundColor: Colors.white, foregroundColor: Colors.black, ), ), ); } } ``` ### 步骤 3:高级定制功能 ```dart QrImageView( data: 'Hello Flutter!', version: QrVersions.auto, // 自动计算版本 errorCorrectionLevel: QrErrorCorrectLevel.H, // 高容错率 size: 250, padding: EdgeInsets.all(20), gapless: false, // 关闭防间隙 embeddedImage: AssetImage('assets/logo.png'), // 中心图标 embeddedImageStyle: QrEmbeddedImageStyle( size: Size(40, 40), color: Colors.blue, ), errorStateBuilder: (cxt, err) => Text('生成失败!'), ), ``` ### 关键参数说明 | **参数** | **类型** | **说明** | |------------------------|-----------------------|----------------------------------------| | `data` | `String` | 编码内容 (必需) | | `version` | `int`/`QrVersions` | 二维码版本 (1-40) | | `errorCorrectionLevel` | `int` | 容错级别 (L:7%/M:15%/Q:25%/H:30%) [^2] | | `embeddedImage` | `ImageProvider` | 中心覆盖的图片 | | `foregroundColor` | `Color` | 二维码颜色 (默认黑色) | | `backgroundColor` | `Color` | 背景色 (默认透明) | | `gapless` | `bool` | 防间隙渲染 (默认true) [^2] | ### 性能优化建议 1. **复杂内容优化**:长文本自动选择更高版本(设置 `version: QrVersions.auto`) 2. **渲染优化**:开启 `gapless: true` 避免像素间隙 [^2] 3. **错误处理**:使用 `errorStateBuilder` 处理生成异常 4. **图片加载**:设置 `embeddedImageEmitsError: false` 忽略图标加载失败 [^2] ### 导出为图片 ```dart final qrCode = QrPainter( data: 'Exportable QR', version: QrVersions.auto, ); final image = await qrCode.toImage(300); // 导出为ui.Image final byteData = await image.toByteData(format: ImageByteFormat.png); ``` > **注意**:如需绘制扫描框界面,可结合 `CustomPaint` 实现 [^3][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值