Flutter 實(shí)現(xiàn)手寫(xiě)簽名效果

如何使用Flutter實(shí)現(xiàn)手寫(xiě)簽名的效果

思路

  • 需要監(jiān)聽(tīng)用戶(hù)觸摸的起始點(diǎn)和結(jié)束點(diǎn),并記錄途經(jīng)點(diǎn),這里我使用了StreamController
  • 將途經(jīng)點(diǎn)從起始位置到結(jié)束位置繪制出來(lái),這里用到CustomPainter

繪制流程

  1. 獲取觸摸點(diǎn)作為畫(huà)筆的起始點(diǎn)
  2. 手機(jī)途經(jīng)點(diǎn)
  3. 繪制途徑路線(xiàn)
  4. 結(jié)束觸摸點(diǎn)重置畫(huà)筆

具體實(shí)現(xiàn)

需要一個(gè)Listener用來(lái)監(jiān)聽(tīng)用戶(hù)行為,并將這些行為的點(diǎn)添加到StreamController中, 兩個(gè)變量

final List _points = []; //承載對(duì)應(yīng)的點(diǎn)
final StreamController _controller = StreamController(); //數(shù)據(jù)通信

Widget _buildWriteWidget() {
  return Stack(
    children: [
      Listener( //用來(lái)監(jiān)聽(tīng)用戶(hù)的觸摸行為
        child: Container(
          color: Colors.transparent,
        ),
        onPointerDown: (PointerDownEvent event) {
          _points.add(event.localPosition);
          _controller.sink.add([_points]);  //起始點(diǎn)的記錄
        },
        onPointerMove: (PointerMoveEvent event) {
          _points.add(event.localPosition);
          _controller.sink.add([_points]);  //添加途經(jīng)點(diǎn)
        },
        onPointerUp: (PointerUpEvent event) {
          _points.add(Offset.zero); //結(jié)束的標(biāo)記
        },
      ),
      StreamBuilder(
          stream: _controller.stream,
          builder: (BuildContext context, AsyncSnapshot snapshot) {
            return snapshot.hasData
                ? CustomPaint(painter: LinePainter(snapshot.data))  //關(guān)聯(lián)數(shù)據(jù)到Painter
                : const SizedBox();
          }),
      Positioned(
          bottom: 50,
          right: 50,
          child: FloatingActionButton(
            onPressed: () {
              _clear();
            },
            child: const Icon(Icons.cleaning_services),
          ))
    ],
  );
}

清除StreamController的內(nèi)容,重置數(shù)據(jù)

void _clear() {
  _points.clear();
  _controller.add(null);
}

dispose時(shí)釋放StreamController

@override
void dispose() {
  _controller.close();
  super.dispose();
}

畫(huà)筆Painter

class LinePainter extends CustomPainter {
  final List<List<Offset>> lines;
  final Color paintColor = Colors.black;
  final Paint _paint = Paint();

  LinePainter(this.lines);

  @override
  void paint(Canvas canvas, Size size) {
    _paint.strokeCap = StrokeCap.round;
    _paint.strokeWidth = 5.0;
    if (lines.isEmpty) {
      canvas.drawPoints(PointMode.polygon, [Offset.zero, Offset.zero], _paint);
    } else {
      for (int i = 0; i < lines.length; i++) {
        for (int j = 0; j < lines[i].length - 1; j++) {
          if (lines[i][j] != Offset.zero && lines[i][j + 1] != Offset.zero) {
            canvas.drawLine(lines[i][j], lines[i][j + 1], _paint);  //繪制相應(yīng)的點(diǎn)
          }
        }
      }
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

最后

如果想要成為架構(gòu)師或想突破20~30K薪資范疇,那就不要局限在編碼,業(yè)務(wù),要會(huì)選型、擴(kuò)展,提升編程思維。此外,良好的職業(yè)規(guī)劃也很重要,學(xué)習(xí)的習(xí)慣很重要,但是最重要的還是要能持之以恒,任何不能堅(jiān)持落實(shí)的計(jì)劃都是空談。

如果你沒(méi)有方向,這里給大家分享一套由阿里高級(jí)架構(gòu)師編寫(xiě)的《Android八大模塊進(jìn)階筆記》,幫大家將雜亂、零散、碎片化的知識(shí)進(jìn)行體系化的整理,讓大家系統(tǒng)而高效地掌握Android開(kāi)發(fā)的各個(gè)知識(shí)點(diǎn)。

更多Android可以查看我的個(gè)人介紹?。。?/p>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容