Flutter 手写板 签名

代码如下:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:ui' as UI;

class HandWrittenBoard extends StatefulWidget {
  ///手写笔颜色
  final Color? color;

  ///手写笔宽度
  final double? width;

  ///手写笔控制器
  final HandWrittenBoardController boardController;

  const HandWrittenBoard(
      {Key? key, this.color, this.width, required this.boardController})
      : super(key: key);

  @override
  _HandWrittenBoardState createState() => _HandWrittenBoardState();
}

class HandWrittenBoardController extends ChangeNotifier {
  late BuildContext _context;
  late List<Offset?> points = [];

  void bindContext(BuildContext context) {
    _context = context;
  }

  void refPoints(List<Offset?> newValue) {
    if (points != newValue) {
      points = newValue;
      notifyListeners();
    }
  }

  Future<UI.Image>? get uiImage {
    UI.PictureRecorder recorder = UI.PictureRecorder();
    Canvas canvas = Canvas(recorder);
    HandWrittenBoardPainter painter = HandWrittenBoardPainter(points);
    Size size = _context.size!;
    painter.paint(canvas, size);
    return recorder
        .endRecording()
        .toImage(size.width.floor(), size.height.floor());
  }

  void clearBoard() {
    points.clear();
    notifyListeners();
  }
}

class _HandWrittenBoardState extends State<HandWrittenBoard> {
  late ValueNotifier<List<Offset?>> _offsets = ValueNotifier([]);

  @override
  void initState() {
    super.initState();
    widget.boardController.bindContext(context);
  }

  void _onUpdate(DragUpdateDetails details) {
    RenderBox? _object = context.findRenderObject() as RenderBox;
    Offset _locationPoints = _object.globalToLocal(details.globalPosition);
    _offsets.value = new List.from(_offsets.value)..add(_locationPoints);
    _refPoints();
  }

  void _onEnd(DragEndDetails details) {
    _offsets.value.add(null);
    _refPoints();
  }

  void _refPoints() {
    widget.boardController.refPoints(_offsets.value);
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onPanUpdate: _onUpdate,
      onPanEnd: _onEnd,
      child: ValueListenableBuilder(
        valueListenable: _offsets,
        builder: (BuildContext context, List<Offset?> value, Widget? child) {
          return CustomPaint(
            painter: HandWrittenBoardPainter(value,
                color: widget.color, width: widget.width),
            size: Size.infinite,
          );
        },
      ),
    );
  }
}

class HandWrittenBoardPainter extends CustomPainter {
  HandWrittenBoardPainter(this.points, {this.color, this.width});

  final List<Offset?> points;

  final Color? color;

  final double? width;

  @override
  void paint(Canvas canvas, Size size) {
    var paint = Paint()
      ..color = color ?? Colors.black
      ..strokeCap = StrokeCap.square
      ..strokeWidth = width ?? 5.0;
    for (int i = 0; i < points.length - 1; i++) {
      if (points[i] != null && points[i + 1] != null) {
        canvas.drawLine(points[i]!, points[i + 1]!, paint);
      }
    }
  }

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

boardController 提供监听 以及获取图片 清除手写版方法
去玩吧

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值