Flutter實(shí)現(xiàn)支付寶集五福手畫福字功能
需求
包含需求的具體有:
界面隨著用戶手指的滑動(dòng)顯示走過軌跡,也就是對(duì)應(yīng)的筆畫。
點(diǎn)擊清空按鈕可以清除所有的筆畫。
點(diǎn)擊撤銷按鈕可以清除上一步畫過的筆畫。
保存所寫的文字樣式到相冊(cè)。
實(shí)現(xiàn)思路
顯示筆畫軌跡
使用Listener組件對(duì)用戶手指落下、滑動(dòng)和收起的動(dòng)作進(jìn)行監(jiān)聽,在onPointerDown,onPointerMove,onPointerUp3個(gè)監(jiān)聽方法中返回的PointerMoveEvent對(duì)象包含了手指所在的位置坐標(biāo)偏移量localPosition,用戶每次滑動(dòng)時(shí)都會(huì)記錄下軌跡經(jīng)過的坐標(biāo)點(diǎn),這些坐標(biāo)點(diǎn)連接起來就是一條線。其次,再配合使用CustomPainter進(jìn)行畫布自繪,將所有劃過的點(diǎn)的連接成線使用畫筆繪制在界面上即可。
搜集坐標(biāo)點(diǎn):
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);
}
}
}
}
}撤銷與清空

看到上面的代碼有的人可能會(huì)比較疑惑,繪制時(shí)為什么這么復(fù)雜,還出現(xiàn)了雙重循環(huán)。這就和撤銷功能有關(guān)了,先假設(shè)不需要撤銷功能,其實(shí)我們就可以直接把所有筆畫的點(diǎn)連接到一起進(jìn)行繪制就可以了,但是一旦引入了撤銷功能,就要記錄每一筆筆畫,福字筆畫是13畫,那么理論上是需要記錄13個(gè)筆畫的,才能保證每次撤銷時(shí)都能正常退回上一次畫過的筆跡,所以第一反應(yīng)就是使用集合將每一次筆畫記錄下來。而上面也說了每一個(gè)筆畫其實(shí)也是多個(gè)坐標(biāo)點(diǎn)的集合,所以所有筆畫就是一個(gè)坐標(biāo)點(diǎn)集合的集合,即:
/// 所有筆畫劃線集合 List<List<Offset>> _lines = [];
另外,也不難想到,我們可以輕易通過手指按下和手指手指的方法回調(diào)來區(qū)分筆畫開始和結(jié)束。在兩個(gè)方法中進(jìn)行筆畫的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 = [];
},而前面說的雙重遍歷這時(shí)也比較好理解了:
- 第一層循環(huán)是遍歷所有的筆畫,遍歷次數(shù)就是福字的筆畫數(shù)。
- 第二層循環(huán)是每一個(gè)筆畫包括的好多個(gè)坐標(biāo)點(diǎn),遍歷出來使用
drawLine方法繪制到界面上形成一條線。
這樣在進(jìn)行撤銷操作時(shí),調(diào)用list的removeLast方法移除最后一項(xiàng)再刷新界面就能實(shí)現(xiàn)退回一筆的效果了,清空就是清空筆畫集合。
保存到相冊(cè)
保存相冊(cè)主要是引入了兩個(gè)插件庫:permission_handler和image_gallery_saver,一個(gè)用來獲取存儲(chǔ)權(quán)限,一個(gè)用來保存到相冊(cè)。 使用RepaintBoundary組件將畫布包裹起來,并指定key,在點(diǎn)擊保存時(shí)按順序調(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實(shí)現(xiàn)支付寶集五福手畫福字功能的文章就介紹到這了,更多相關(guān)Flutter畫福字內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)短信驗(yàn)證碼自動(dòng)填寫
這篇文章主要為大家詳細(xì)介紹了Android短信驗(yàn)證碼自動(dòng)填寫功能的實(shí)現(xiàn)過程,感興趣的小伙伴們可以參考一下2016-08-08
flutter實(shí)現(xiàn)掃碼槍獲取數(shù)據(jù)源禁止系統(tǒng)鍵盤彈窗示例詳解
這篇文章主要為大家介紹了flutter實(shí)現(xiàn)掃碼槍獲取數(shù)據(jù)源禁止系統(tǒng)鍵盤彈窗示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
揭秘雙十一手機(jī)淘寶圖標(biāo)如何被動(dòng)態(tài)更換
這篇文章主要介紹了每到雙十一十二的時(shí)候Android手機(jī)動(dòng)態(tài)更換手機(jī)圖標(biāo)的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08
Android自定義View實(shí)現(xiàn)帶音效和震動(dòng)的SeekBar
這篇文章主要為大家詳細(xì)介紹了Android如何自定義View實(shí)一個(gè)帶音效和震動(dòng)的SeekBar,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03
Android快速實(shí)現(xiàn)斷點(diǎn)續(xù)傳的方法
這篇文章主要為大家詳細(xì)介紹了Android快速實(shí)現(xiàn)斷點(diǎn)續(xù)傳的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07
Android ListView中動(dòng)態(tài)添加RaidoButton的實(shí)例詳解
這篇文章主要介紹了Android ListView中動(dòng)態(tài)添加RaidoButton的實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-08-08
兩分鐘讓你徹底明白Android Activity生命周期的詳解(圖文介紹)
本篇文章是對(duì)Android的生命周期進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
Android監(jiān)聽滑動(dòng)控件實(shí)現(xiàn)狀態(tài)欄顏色切換
這篇文章給大家分享一個(gè)平時(shí)在滑動(dòng)頁面經(jīng)常遇到的效果:滑動(dòng)過程動(dòng)態(tài)修改狀態(tài)欄顏色,文中有詳細(xì)的示例代碼,對(duì)我們的學(xué)習(xí)或工作有一定的幫助,感興趣的小伙伴自己動(dòng)手試試吧2023-08-08

