搜尋套件、儲存庫與 APP 分類

套件詳情v3.0.0

screenshot

Flutter 截圖套件(執行時)。將任何 Widget 當作影像擷取。

AndroidiOSWebmacOSWindowsLinux
近 30 天下載
61.7萬
喜歡數
1560
Pub 分數
140

安裝套件

flutter pub add screenshot

套件介紹

根據套件公開資料產生的選型評估,僅供參考。

截圖套件可於執行階段跨多個平台擷取任何Flutter元件為影像。它讓開發者能在應用程式執行期間以程式方式拍攝元件的螢幕截圖,對於除錯、測試或分享視覺內容非常實用。此套件支援Android、iOS、Web、macOS、Windows與Linux,具有高度彈性。它與Flutter的渲染流程無縫整合,並提供簡單的API,可從元件樹產生影像。適合需要動態影像生成或視覺回饋的應用程式。

適用情境

  • 除錯 UI 問題
  • 產生可分享的影像
  • 自動化測試
  • 視覺文件
  • 應用教程
  • 預覽功能

主要特色

  • 執行時期元件截圖捕捉
  • 跨平台支援
  • 簡單的 API 結合
  • 高品質圖像輸出
  • 支援所有主要平台
  • 無外部依賴

適合對象

  • 需要動態截圖的開發者
  • 測試與品質保證團隊
  • 具有視覺共享功能的應用程式
  • 教育類或教學類應用
  • UI 原型設計工具
  • 除錯複雜版面

使用建議

  • 大型小部件上的性能影響
  • 高解析度圖像的記憶體使用情況
  • 在移動平台需要適當的權限
  • 不適用於即時影片捕捉
  • 僅限靜態小工具快照
  • 可能需要平台特定的設定

原始 README

以下為關聯原始碼儲存庫的 README 原文快照,最新內容請造訪原始碼儲存庫。

screenshot

A simple package to capture widgets as Images. Now you can also capture the widgets that are not rendered on the screen!

This package wraps your widgets inside RenderRepaintBoundary

Source

screenshot

  Capture a widget:

screenshot

 Capture an invisible widget (a widget which is not part of the widget tree):

screenshot

Getting Started

This handy package can be used to capture any Widget including full screen screenshots & individual widgets like Text().

  1. Create Instance of Screenshot Controller
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  Uint8List _imageFile;

  //Create an instance of ScreenshotController
  ScreenshotController screenshotController = ScreenshotController(); 

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }
  ...
}
  1. Wrap the widget that you want to capture inside Screenshot Widget. Assign the controller to screenshotController that you have created earlier
Screenshot(
    controller: screenshotController,
    child: Text("This text will be captured as image"),
),
  1. Take the screenshot by calling capture method. This will return a Uint8List
screenshotController.capture().then((Uint8List image) {
    //Capture Done
    setState(() {
        _imageFile = image;
    });
}).catchError((onError) {
    print(onError);
});

Capturing Widgets that are not in the widget tree

You can capture invisible widgets by calling captureFromWidget and passing a widget tree to the function

screenshotController
      .captureFromWidget(Container(
          padding: const EdgeInsets.all(30.0),
          decoration: BoxDecoration(
            border:
                Border.all(color: Colors.blueAccent, width: 5.0),
            color: Colors.redAccent,
          ),
          child: Text("This is an invisible widget")))
      .then((capturedImage) {
    // Handle captured image
  });


Capturing a List Widget

You can capture a long Invisible widgets by using captureFromLongWidget function.

var randomItemCount = Random().nextInt(100);

///
/// Step 1: Create Long widget using Column.
///

var myLongWidget = Builder(builder: (context) {
  return Container(
      padding: const EdgeInsets.all(30.0),
      decoration: BoxDecoration(
        border:
            Border.all(color: Colors.blueAccent, width: 5.0),
        color: Colors.redAccent,
      ),
      ///
      /// Note: Do not use Scrolling widget, instead place your children in Column. 
      ///  
      /// Do not use widgets like 'Expanded','Flexible',or 'Spacer'
      ///
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          for (int i = 0; i < randomItemCount; i++)
            Text("Tile Index $i"),
        ],
      ));
});

///
/// Step 2: 
///    Use `captureFromLongWidget` function for taking screenshot.
///
screenshotController
      .captureFromLongWidget(
          InheritedTheme.captureAll(
            context, 
            Material(
              child: myLongWidget,
            ),
          ),
          delay: Duration(milliseconds: 100),
          context: context,


          ///
          /// Additionally you can define constraint for your image.
          ///
          /// constraints: BoxConstraints(
          ///   maxHeight: 1000,
          ///   maxWidth: 1000,
          /// )
      )
      .then((capturedImage) {
    // Handle captured image
  });


Saving images to Specific Location

For this you can use captureAndSave method by passing directory location. By default, the captured image will be saved to Application Directory. Custom paths can be set using path parameter. Refer path_provider

Note

Method captureAndSave is not supported for web.

final directory = (await getApplicationDocumentsDirectory ()).path; //from path_provide package
String fileName = DateTime.now().microsecondsSinceEpoch;
path = '$directory';

screenshotController.captureAndSave(
    path //set path where screenshot will be saved
    fileName:fileName 
);

Saving images to Gallery

If you want to save captured image to Gallery, Please use https://github.com/hui-z/image_gallery_saver Example app uses the same to save screenshots to gallery.


Sharing Captured Images

await _screenshotController.capture(delay: const Duration(milliseconds: 10)).then((Uint8List image) async {
      if (image != null) {
        final directory = await getApplicationDocumentsDirectory();
        final imagePath = await File('${directory.path}/image.png').create();
        await imagePath.writeAsBytes(image);

        /// Share Plugin
        await Share.shareFiles([imagePath.path]);
      }
    });

Note:

Captured image may look pixelated. You can overcome this issue by setting value for pixelRatio

The pixelRatio describes the scale between the logical pixels and the size of the output image. It is independent of the window.devicePixelRatio for the device, so specifying 1.0 (the default) will give you a 1:1 mapping between logical pixels and the output pixels in the image.

double pixelRatio = MediaQuery.of(context).devicePixelRatio;

screenshotController.capture(
    pixelRatio: pixelRatio //1.5
)

Sometimes rastergraphics like images may not be captured by the plugin with default configurations. The issue is discussed here.

...screenshot is taken before the GPU thread is done rasterizing the frame 
so the screenshot of the previous frame is taken, which is wrong.

The solution is to add a small delay before capturing.

screenshotController.capture(delay: Duration(milliseconds: 10))

Known Issues

  • Platform Views are not supported. (Example: Google Maps, Camera etc)issue

所屬分類

原始碼儲存庫

使用此套件的專案