天天看點

Flutter 42: 圖解頁面截屏與本地儲存小嘗試

      小菜因特别需求想嘗試一下 Flutter 頁面截屏并将圖檔儲存在本地的功能,記錄一下嘗試過程。

RepaintBoundary

      Flutter 提供了支援截屏的 RepaintBoundary,在需要截取部分的外層嵌套,也可以截取某一子 Widget 内容;RepaintBoundary 的結構很簡單,通過 key 來判斷截取的 RenderObject,最終生成一個 RenderRepaintBoundary 對象;

const RepaintBoundary({ Key key, Widget child }) : super(key: key, child: child);

@override
Widget build(BuildContext context) {
  return RepaintBoundary(
      key: globalKey,
      child: Scaffold(
          body: Stack(children: <Widget>[
        Image.asset('img/bg.jpg', width: _w, fit: BoxFit.fill),
        Container(child: CustomPaint(painter: StarCanvas(_w, _h, p, s, st))),
        itemWid(1, 2),
        itemWid(1, 1),
        itemWid(0, 1),
        itemWid(0, 2),
      ])));
}           

ui.Image

      通過 RenderRepaintBoundary 擷取的對象 .toImage() 後轉為 ui.Image 類型位元組流,最終存儲為 png 格式,在轉為常用的 Uint8List 存儲在記憶體中,借助 image.memory() 方式展示在具體位置;而目前隻是擷取到圖檔的流資訊,僅可用于操作,還未存儲在本地;

      toByteData() 生成的資料格式一般分三種:

  1. rawRgba:未解碼的 byte;
  2. rawUnmodified:未解碼且未修改的 byte,如灰階圖;
  3. png 為我們常用的 PNG 圖檔;
Future<Uint8List> _capturePng(globalKey) async {
  RenderRepaintBoundary boundary = globalKey.currentContext.findRenderObject();
  ui.Image image = await boundary.toImage();
  ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
  Uint8List picBytes = byteData.buffer.asUint8List();
  return picBytes;
}           

Directory

      若需要存儲本地,跟 Android/iOS 類似,首先擷取存儲路徑,再進行存儲操作;小菜借助三方插件

path_provider

來擷取圖檔路徑;

      path_provider 提供了 getTemporaryDirectory 臨時路徑 / getApplicationDocumentsDirectory 全局路徑等,可以根據不同的需求存儲不同路徑;

      小菜為了測試友善選擇存放在裝置根目錄下 getExternalStorageDirectory;

Future<String> _capturePath(name) async {
  Directory documentsDirectory = await getExternalStorageDirectory();
  String path = join(documentsDirectory.path, name);
  return path;
}           

writeAsBytes

      檔案的儲存很簡單,直接将 Uint8List 寫入到所在檔案路徑下即可;

File(val).writeAsBytes(unitVal);           

      但此時存儲或自定義檔案路徑,可能會遇到權限問題,小菜為了測試友善在 Android 中添加讀寫權限,并手動在裝置中打開,之後便可正常存儲;

      小菜對檔案存儲還很不熟悉,對于動态申請權限方面也在學習過程中,會在今後的部落格中逐漸整理,如有不對的地方請多多指導!

繼續閱讀