Flutter實現(xiàn)支付寶集五福手畫福字功能
需求
包含需求的具體有:
界面隨著用戶手指的滑動顯示走過軌跡,也就是對應的筆畫。
點擊清空按鈕可以清除所有的筆畫。
點擊撤銷按鈕可以清除上一步畫過的筆畫。
保存所寫的文字樣式到相冊。
實現(xiàn)思路
顯示筆畫軌跡
使用Listener
組件對用戶手指落下、滑動和收起的動作進行監(jiān)聽,在onPointerDown
,onPointerMove
,onPointerUp
3個監(jiān)聽方法中返回的PointerMoveEvent
對象包含了手指所在的位置坐標偏移量localPosition
,用戶每次滑動時都會記錄下軌跡經(jīng)過的坐標點,這些坐標點連接起來就是一條線。其次,再配合使用CustomPainter
進行畫布自繪,將所有劃過的點的連接成線使用畫筆繪制在界面上即可。
搜集坐標點:
Listener( child: Container( alignment: Alignment.center, color: Colors.transparent, width: double.infinity, height: MediaQuery.of(context).size.height, ), onPointerDown: (PointerDownEvent event) { setState(() { }); }, onPointerMove: (PointerMoveEvent event) { setState(() { }); }, onPointerUp: (PointerUpEvent event) { setState(() { }); }, ),
繪制:
@override void paint(Canvas canvas, Size size) { myPaint.strokeCap = StrokeCap.round; myPaint.strokeWidth = 15.0; if (lines.isEmpty) { canvas.drawPoints(PointMode.polygon, [Offset.zero, Offset.zero], myPaint); } else { for (int k = 0; k < lines.length; k++) { for (int i = 0; i < lines[k].length - 1; i++) { if (lines[k][i] != Offset.zero && lines[k][i + 1] != Offset.zero) { canvas.drawLine(lines[k][i], lines[k][i + 1], myPaint); } } } } }
撤銷與清空
看到上面的代碼有的人可能會比較疑惑,繪制時為什么這么復雜,還出現(xiàn)了雙重循環(huán)。這就和撤銷功能有關(guān)了,先假設不需要撤銷功能,其實我們就可以直接把所有筆畫的點連接到一起進行繪制就可以了,但是一旦引入了撤銷功能,就要記錄每一筆筆畫,福字筆畫是13畫,那么理論上是需要記錄13個筆畫的,才能保證每次撤銷時都能正常退回上一次畫過的筆跡,所以第一反應就是使用集合將每一次筆畫記錄下來。而上面也說了每一個筆畫其實也是多個坐標點的集合,所以所有筆畫就是一個坐標點集合的集合,即:
/// 所有筆畫劃線集合 List<List<Offset>> _lines = [];
另外,也不難想到,我們可以輕易通過手指按下和手指手指的方法回調(diào)來區(qū)分筆畫開始和結(jié)束。在兩個方法中進行筆畫的add和更新。
onPointerDown: (PointerDownEvent event) { setState(() { _event = event; _points.add(_event?.localPosition ?? Offset.zero); _lines.add(_points); }); }, onPointerMove: (PointerMoveEvent event) { setState(() { _event = event; _points.add(_event?.localPosition ?? Offset.zero); _lines.last = _points; }); }, onPointerUp: (PointerUpEvent event) { setState(() { _event = event; _points.add(Offset.zero); _lines.last = _points; }); _points = []; },
而前面說的雙重遍歷這時也比較好理解了:
- 第一層循環(huán)是遍歷所有的筆畫,遍歷次數(shù)就是福字的筆畫數(shù)。
- 第二層循環(huán)是每一個筆畫包括的好多個坐標點,遍歷出來使用
drawLine
方法繪制到界面上形成一條線。
這樣在進行撤銷操作時,調(diào)用list的removeLast方法移除最后一項再刷新界面就能實現(xiàn)退回一筆的效果了,清空就是清空筆畫集合。
保存到相冊
保存相冊主要是引入了兩個插件庫:permission_handler
和image_gallery_saver
,一個用來獲取存儲權(quán)限,一個用來保存到相冊。 使用RepaintBoundary
組件將畫布包裹起來,并指定key,在點擊保存時按順序調(diào)用如下方法先獲取截圖后保存即可:
RenderRepaintBoundary boundary = key.currentContext!.findRenderObject() as RenderRepaintBoundary; var image = await boundary.toImage(pixelRatio: 3.0); ByteData? byteData = await image.toByteData(format: ImageByteFormat.png); _postBytes = byteData?.buffer.asUint8List(); var result = await ImageGallerySaver.saveImage(_postBytes!);
完整代碼與demo下載
到此這篇關(guān)于Flutter實現(xiàn)支付寶集五福手畫福字功能的文章就介紹到這了,更多相關(guān)Flutter畫福字內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android使用CardView作為RecyclerView的Item并實現(xiàn)拖拽和左滑刪除
這篇文章主要介紹了Android使用CardView作為RecyclerView的Item并實現(xiàn)拖拽和左滑刪除,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-11-11android教程之使用popupwindow創(chuàng)建菜單示例
這篇文章主要介紹了android使用popupwindow創(chuàng)建菜單的示例,需要的朋友可以參考下2014-02-02Android studio報錯:The emulator process for AVD (xxx) was kill
這篇文章主要介紹了Android studio報錯:The emulator process for AVD (xxx) was killed,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-12-12