如何在Flutter中添加签名? [英] How to add Signature in flutter?

查看:219
本文介绍了如何在Flutter中添加签名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在flutter项目中实现了 signature_pad ,并且效果很好.

I have implemented signature_pad in my flutter project and it works fine.

不幸的是,当我将其放置在 SingleChildScrollView 内时,未绘制签名.它滚动而不是签名.

Unfortunately when I place it inside SingleChildScrollView, the signature was not drawn. It scrolled instead of signed.

似乎是 GestureDetector ,但我不知道如何解决它.

It seems like is the GestureDetector but I have no idea how to fix it.

有人可以给我一些线索吗?

Can someone give me some clue on this?

谢谢.

推荐答案

签名类需要修改以响应 VerticalDrag ,我将其重命名为 Signature1

Signature Class need to be modified to respond to VerticalDrag , I renamed it to Signature1

现在签名区域键盘不应该滚动,您可以按其行为检查下面的完整代码.您会发现使用 SingleChildScrollView 不再滚动签名"区域.

now signature area pad should not scroll , you can check the complete code below as it behaves. you will find out that Signature area is no more scrolling with the SingleChildScrollView.

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  var color = Colors.black;
  var strokeWidth = 3.0;
  final _sign = GlobalKey<Signature1State>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body:
           SingleChildScrollView(
             child: Column(
               children: <Widget>[
                 _showCategory(),
                 SizedBox(height: 15),
                 _showCategory(),
                 SizedBox(height: 15),
                 _showCategory(),
                 SizedBox(height: 15),
                 _showCategory(),
                 SizedBox(height: 15),
                 _showCategory(),
                 _showCategory(),
                 SizedBox(height: 15),
                 _showCategory(),
                 SizedBox(height: 15),
                 _showCategory(),
                 SizedBox(height: 15),
                 _showCategory(),
                 SizedBox(height: 15),
                 _showCategory(),
                 _showSignaturePad()
               ],
             ),
           )

      ,
    );
  }

  Widget _showCategory() {
    return TextField(
        onTap: () {
          FocusScope.of(context).requestFocus(FocusNode());
        },
        style: TextStyle(fontSize: 12.0, height: 1.0),
        decoration: InputDecoration(hintText: "TextView"));
  }

  Widget _showSignaturePad() {
    return Container(
      width: double.infinity,
      height: 200,
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Container(
          height: 200,
          //color: Colors.red,
          child: Signature1(
            color: color,
            key: _sign,
            strokeWidth: strokeWidth,
          ),
        ),
      ),
      color: Colors.grey.shade300,
    );
  }
}
class Signature1 extends StatefulWidget {
  final Color color;
  final double strokeWidth;
  final CustomPainter backgroundPainter;
  final Function onSign;

  Signature1({
    this.color = Colors.black,
    this.strokeWidth = 5.0,
    this.backgroundPainter,
    this.onSign,
    Key key,
  }) : super(key: key);

  Signature1State createState() => Signature1State();

  static Signature1State of(BuildContext context) {
    return context.findAncestorStateOfType<Signature1State>();
  }
}

class _SignaturePainter extends CustomPainter {
  Size _lastSize;
  final double strokeWidth;
  final List<Offset> points;
  final Color strokeColor;
  Paint _linePaint;

  _SignaturePainter({@required this.points, @required this.strokeColor, @required this.strokeWidth}) {
    _linePaint = Paint()
      ..color = strokeColor
      ..strokeWidth = strokeWidth
      ..strokeCap = StrokeCap.round;
  }

  @override
  void paint(Canvas canvas, Size size) {
    _lastSize = size;
    for (int i = 0; i < points.length - 1; i++) {
      if (points[i] != null && points[i + 1] != null) canvas.drawLine(points[i], points[i + 1], _linePaint);
    }
  }

  @override
  bool shouldRepaint(_SignaturePainter other) => other.points != points;
}

class Signature1State extends State<Signature1> {
  List<Offset> _points = <Offset>[];
  _SignaturePainter _painter;
  Size _lastSize;

  Signature1State();

  void _onDragStart(DragStartDetails details){
    RenderBox referenceBox = context.findRenderObject();
    Offset localPostion = referenceBox.globalToLocal(details.globalPosition);
    setState(() {
      _points = List.from(_points)
        ..add(localPostion)
        ..add(localPostion);
    });
  }
  void _onDragUpdate (DragUpdateDetails details) {
    RenderBox referenceBox = context.findRenderObject();
    Offset localPosition = referenceBox.globalToLocal(details.globalPosition);

    setState(() {
      _points = List.from(_points)..add(localPosition);
      if (widget.onSign != null) {
        widget.onSign();
      }
    });
  }
  void _onDragEnd (DragEndDetails details) => _points.add(null);

  @override
  Widget build(BuildContext context) {
    WidgetsBinding.instance.addPostFrameCallback((_) => afterFirstLayout(context));
    _painter = _SignaturePainter(points: _points, strokeColor: widget.color, strokeWidth: widget.strokeWidth);
    return ClipRect(
      child: CustomPaint(
        painter: widget.backgroundPainter,
        foregroundPainter: _painter,
        child: GestureDetector(

          onVerticalDragStart: _onDragStart,
          onVerticalDragUpdate: _onDragUpdate,
          onVerticalDragEnd: _onDragEnd,

          onPanStart: _onDragStart,
          onPanUpdate: _onDragUpdate,
          onPanEnd: _onDragEnd
        ),
      ),
    );
  }

  Future<ui.Image> getData() {
    var recorder = ui.PictureRecorder();
    var origin = Offset(0.0, 0.0);
    var paintBounds = Rect.fromPoints(_lastSize.topLeft(origin), _lastSize.bottomRight(origin));
    var canvas = Canvas(recorder, paintBounds);
    if(widget.backgroundPainter != null) {
      widget.backgroundPainter.paint(canvas, _lastSize);
    }
    _painter.paint(canvas, _lastSize);
    var picture = recorder.endRecording();
    return picture.toImage(_lastSize.width.round(), _lastSize.height.round());
  }

  void clear() {
    setState(() {
      _points = [];
    });
  }

  bool get hasPoints => _points.length > 0;

  List<Offset> get points => _points;

  afterFirstLayout(BuildContext context) {
    _lastSize = context.size;
  }
}

这篇关于如何在Flutter中添加签名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆