flutter 画板签字

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

class SignatureWidget extends StatefulWidget {
  final SignatureWidgetControl? signatureControl;

  ///画笔的颜色
  final Color color;

  /// 线条的宽
  final double strokeWidth;

  /// 生成图片的边距
  final double padding;

  const SignatureWidget(
      {Key? key,
      required this.signatureControl,
      this.color = Colors.black,
      this.strokeWidth = 2,
      this.padding = 10})
      : super(key: key);

  @override
  State<SignatureWidget> createState() => _SignatureWidgetState();
}

class SignatureWidgetControl {
  Function()? _reset;
  Future<Uint8List?> Function()? _onSave;
  Function()? _previousStep;

  /// 重置画布
  void reset() {
    _reset?.call();
  }

  /// 保存画布到图片
  Future<Uint8List?> onSave() {
    return _onSave?.call() ?? Future.value(null);
  }

  ///上一步
  void previousStep() {
    _previousStep?.call();
  }
}

class _SignatureWidgetState extends State<SignatureWidget> {
  List<Path?> paths = [];
  Path? _currentPath;
  Offset? _previousPosition;
  Uint8List? image;
  Paint p = Paint();

  @override
  void initState() {
    super.initState();

    p
      ..color = widget.color
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.stroke
      ..strokeWidth = widget.strokeWidth
      ..isAntiAlias = true;

    widget.signatureControl?._reset = () {
      setState(() {
        paths.clear();
      });
    };

    widget.signatureControl?._previousStep = () {
      setState(() {
        paths.removeAt(paths.length - 1);
      });
    };

    widget.signatureControl?._onSave = () => _save();
  }

  Future<Uint8List?> _save() async {
    Rect? maxBound;
    for (var value in paths) {
      var bound = value?.getBounds();
      if (maxBound == null) {
        maxBound = bound;
      } else {
        maxBound = bound?.expandToInclude(maxBound);
      }
    }

    if (maxBound == null) {
      return null;
    }

    var recorder = ui.PictureRecorder();
    var canvas = Canvas(recorder);
    for (var path in paths) {
      if (path != null) {
        var shiftPath = path.shift(Offset(
            widget.padding - maxBound.left, widget.padding - maxBound.top));
        canvas.drawPath(shiftPath, p);
      }
    }
    var endRecording = recorder.endRecording();

    var image = await endRecording.toImage(
        (maxBound.size.width + widget.padding * 2).toInt(),
        (maxBound.size.height + widget.padding * 2).toInt());
    var byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    return byteData?.buffer.asUint8List();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onPanDown: (e) {
        _currentPath = Path()..moveTo(e.localPosition.dx, e.localPosition.dy);
        _previousPosition = e.localPosition;
        paths.add(_currentPath);
      },
      onPanUpdate: (e) {
        if (_previousPosition == null) {
          _currentPath?.lineTo(e.localPosition.dx, e.localPosition.dy);
        } else {
          _currentPath?.quadraticBezierTo(
              _previousPosition!.dx,
              _previousPosition!.dy,
              (_previousPosition!.dx + e.localPosition.dx) / 2,
              (_previousPosition!.dy + e.localPosition.dy) / 2);
        }

        _previousPosition = e.localPosition;

        setState(() {});
      },
      onPanEnd: (e) {
        _previousPosition = null;
        setState(() {});
      },
      child: CustomPaint(
        painter: SignaturePainter(paths: paths, sPaint: p),
        size: Size.infinite,
        child: Container(
          color: Colors.transparent,
        ),
      ),
    );
  }
}

class SignatureAllWidget extends StatefulWidget {
  const SignatureAllWidget({Key? key}) : super(key: key);

  @override
  State<SignatureAllWidget> createState() => _SignatureAllWidgetState();
}

class _SignatureAllWidgetState extends State<SignatureAllWidget> {
  SignatureWidgetControl? signatureWidgetControl;

  @override
  void initState() {
    super.initState();
    signatureWidgetControl = SignatureWidgetControl();
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        SignatureWidget(
          signatureControl: signatureWidgetControl,
          padding: 20,
          strokeWidth: 20,
          color: Colors.blue,
        ),
        SignatureDealWidget(signatureWidgetControl: signatureWidgetControl)
      ],
    );
  }
}

class SignatureDealWidget extends StatefulWidget {
  final SignatureWidgetControl? signatureWidgetControl;

  const SignatureDealWidget({Key? key, required this.signatureWidgetControl})
      : super(key: key);

  @override
  State<SignatureDealWidget> createState() => _SignatureDealWidgetState();
}

class _SignatureDealWidgetState extends State<SignatureDealWidget> {
  Uint8List? image;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Align(
          alignment: Alignment.bottomCenter,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.end,
            children: [
              ElevatedButton(
                  onPressed: () {
                    var futureSave = widget.signatureWidgetControl?.onSave();
                    futureSave?.then((value) => {
                          setState(() {
                            image = value;
                          })
                        });
                  },
                  child: const Text("保存")),
              ElevatedButton(
                  onPressed: () {
                    widget.signatureWidgetControl?.reset();
                  },
                  child: const Text("清除")),
              ElevatedButton(
                  onPressed: () {
                    widget.signatureWidgetControl?.previousStep();
                  },
                  child: const Text("上一步")),
            ],
          ),
        ),
        Align(
          alignment: Alignment.topLeft,
          child: image == null
              ? const SizedBox()
              : Align(
                  alignment: Alignment.topLeft,
                  child: SizedBox(
                    width: 100,
                    height: 200,
                    child: Container(
                      decoration:
                          BoxDecoration(border: Border.all(color: Colors.blue)),
                      child: Image.memory(image!),
                    ),
                  ),
                ),
        )
      ],
    );
  }
}

class SignaturePainter extends CustomPainter {
  List<Path?> paths;
  Paint sPaint;

  SignaturePainter({required this.paths, required this.sPaint});

  @override
  void paint(Canvas canvas, Size size) {
    for (var value in paths) {
      _drawLine(canvas, value);
    }
  }

  void _drawLine(Canvas canvas, Path? path) {
    if (path == null) return;
    canvas.drawPath(path, sPaint);
  }

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

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter 可以通过调用原生代码来实现调用签字版的功能。具体实现步骤如下: 1. 首先在 Flutter 中编写调用签字版的 Dart 代码。 2. 接着,创建一个 Flutter 插件,用于与原生代码进行通信。 3. 在原生代码中实现调用签字版的功能,并将签字结果返回给 Flutter。 4. 最后,在 Flutter 中处理签字结果并进行相关操作。 代码示例: 在 Flutter 中调用签字版: ```dart import 'package:flutter/services.dart'; import 'package:flutter/material.dart'; import 'dart:async'; class SignaturePad extends StatefulWidget { @override _SignaturePadState createState() => _SignaturePadState(); } class _SignaturePadState extends State<SignaturePad> { static const platform = const MethodChannel('signature_pad'); Future<void> _showSignaturePad() async { try { final bool result = await platform.invokeMethod('showSignaturePad'); if (result) { // 处理签字结果 } } on PlatformException catch (e) { // 处理异常 } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Signature Pad'), ), body: Center( child: RaisedButton( onPressed: _showSignaturePad, child: Text('Open Signature Pad'), ), ), ); } } ``` 创建 Flutter 插件: 1. 在 Flutter 项目的根目录创建一个 `signature_pad` 文件夹,用于存放插件代码。 2. 在 `signature_pad/lib` 目录下创建 `signature_pad.dart` 文件,用于定义插件接口。 ```dart import 'dart:async'; import 'package:flutter/services.dart'; class SignaturePad { static const MethodChannel _channel = const MethodChannel('signature_pad'); static Future<bool> showSignaturePad() async { final bool result = await _channel.invokeMethod('showSignaturePad'); return result; } } ``` 3. 在 `signature_pad/android/src/main/kotlin/com/example/signature_pad/SignaturePadPlugin.kt` 文件中实现 Android 平台的签字功能: ```kotlin class SignaturePadPlugin : FlutterPlugin, MethodCallHandler { private var activity: Activity? = null private var methodChannel: MethodChannel? = null companion object { const val CHANNEL_NAME = "signature_pad" } override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { methodChannel = MethodChannel(binding.binaryMessenger, CHANNEL_NAME) methodChannel?.setMethodCallHandler(this) } override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { methodChannel?.setMethodCallHandler(null) methodChannel = null } override fun onMethodCall(call: MethodCall, result: Result) { if (call.method == "showSignaturePad") { showSignaturePad(result) } else { result.notImplemented() } } private fun showSignaturePad(result: Result) { activity?.runOnUiThread { // 调用签字版界面,等待签字结果 val signatureResult: Boolean = true // 签字结果 result.success(signatureResult) } } } ``` 4. 在 `signature_pad/ios/Classes/SignaturePadPlugin.swift` 文件中实现 iOS 平台的签字功能: ```swift public class SignaturePadPlugin: NSObject, FlutterPlugin { var methodChannel: FlutterMethodChannel? public static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel(name: "signature_pad", binaryMessenger: registrar.messenger()) let instance = SignaturePadPlugin() instance.methodChannel = channel registrar.addMethodCallDelegate(instance, channel: channel) } public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { if call.method == "showSignaturePad" { self.showSignaturePad(result: result) } else { result(FlutterMethodNotImplemented) } } private func showSignaturePad(result: @escaping FlutterResult) { // 调用签字版界面,等待签字结果 let signatureResult = true // 签字结果 result(signatureResult) } } ``` 在 Flutter 中调用插件: ```dart import 'package:flutter/material.dart'; import 'package:signature_pad/signature_pad.dart'; class SignaturePadPage extends StatefulWidget { @override _SignaturePadPageState createState() => _SignaturePadPageState(); } class _SignaturePadPageState extends State<SignaturePadPage> { Future<void> _showSignaturePad() async { bool result = await SignaturePad.showSignaturePad(); if (result) { // 处理签字结果 } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Signature Pad'), ), body: Center( child: RaisedButton( onPressed: _showSignaturePad, child: Text('Open Signature Pad'), ), ), ); } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值