flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
162.17k stars 26.65k forks source link

In Android, capturing WebView content works fine, but on iOS, it captures a blank screen. Is there a solution for this? #147507

Open junga970 opened 2 weeks ago

junga970 commented 2 weeks ago

Steps to reproduce

  1. Display a graph using the echarts library.
  2. The graph rendering is complete.
  3. Press the capture button to capture the graph.

Expected results

The capture includes the graph. (The results obtained on Android.)

IMG_0122

Actual results

The capture is successful, but the graph appears as a white screen. (The results obtained on iOS.)

IMG_0104

Code sample

Code sample 1. Add the following to your Podfile file: ```TEXT post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) target.build_configurations.each do |config| # You can remove unused permissions here # for more information: https://github.com/BaseflowIT/flutter-permission-handler/blob/master/permission_handler/ios/Classes/PermissionHandlerEnums.h # e.g. when you don't need camera permission, just add 'PERMISSION_CAMERA=0' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)', ## dart: PermissionGroup.photos 'PERMISSION_PHOTOS=1', ] end end end ``` 2. Add the following to your Info.plist. ``` NSPhotoLibraryUsageDescription photos ``` 3. pubspec.yaml ``` dependencies: flutter: sdk: flutter permission_handler: ^11.1.0 flutter_echarts: ^2.5.0 image_gallery_saver: ^2.0.3 ``` 4. main.dart ```dart import 'dart:typed_data'; import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_echarts/flutter_echarts.dart'; import 'package:image_gallery_saver/image_gallery_saver.dart'; import 'package:permission_handler/permission_handler.dart'; void main() => runApp(MyApp()); class MyApp extends StatefulWidget { const MyApp({super.key}); @override State createState() => _MyAppState(); } class _MyAppState extends State { final GlobalKey globalKey = GlobalKey(); Future captureGraph() async { try { // Requesting access to the photo library. await Permission.photos.request(); RenderRepaintBoundary boundary = globalKey.currentContext!.findRenderObject() as RenderRepaintBoundary; ui.Image image = await boundary.toImage(pixelRatio: 3.0); ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png); Uint8List pngBytes = byteData!.buffer.asUint8List(); // Save screenshot to photo library. final result = await ImageGallerySaver.saveImage(Uint8List.fromList(pngBytes)); print("Image saved to gallery: $result"); return true; } catch (e) { print("Error capturing screen: $e"); return false; } } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('ECharts capture example')), body: RepaintBoundary( key: globalKey, child: Center( child: Column( children: [ SizedBox( width: 300, height: 250, child: Echarts( captureAllGestures: true, key: ValueKey(DateTime.now()), onLoad: (p0) { print('로딩 완료'); }, option: ''' { title: { text: 'AA', subtext: 'BB', left: 'center' }, tooltip: {}, backgroundColor: '#fff', xAxis: { type: 'category', boundaryGap: false, data: [0.0, 0.3, 0.6, 0.9, 1.0] }, yAxis: { type: 'category', boundaryGap: false, data: ['0', '10', '20', '30', '40', '50'] }, series: [ { symbolSize: function (val) { return val[2] !== 0 ? 50 : ""; // 주석: 데이터 값에 따라 점 크기가 달라지도록 설정 }, data: [[1, 1, 1], [2, 2, 1]], type: 'scatter', label: { show: true, formatter: function(params) { if (params.data[2] === 0) { return ""; } return params.data[2].toString() + '번'; }, textStyle: { fontWeight: 'bold', fontSize: 14 }, position: 'top' } } ] } ''', ), ), ElevatedButton(onPressed: () { captureGraph(); }, child: const Text("capture")) ], ), ), )), ); } } ```

Screenshots or Video

Screenshots / Video demonstration [Upload media here]

Logs

Logs ```console [Paste your logs here] ```

Flutter Doctor output

Doctor output ```console /Users/junga/dev/flutter/bin/flutter doctor --verbose [!] Flutter (Channel stable, 3.19.0, on macOS 14.4.1 23E224 darwin-x64, locale ko-KR) • Flutter version 3.19.0 on channel stable at /Users/junga/dev/flutter ! The flutter binary is not on your path. Consider adding /Users/junga/dev/flutter/bin to your path. ! The dart binary is not on your path. Consider adding /Users/junga/dev/flutter/bin to your path. • Upstream repository https://github.com/flutter/flutter.git • Framework revision bae5e49bc2 (3달 전), 2024-02-13 17:46:18 -0800 • Engine revision 04817c99c9 • Dart version 3.3.0 • DevTools version 2.31.1 • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades. [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) • Android SDK at /Users/junga/Library/Android/sdk • Platform android-34-ext8, build-tools 34.0.0 • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 15.2) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 15C500b • CocoaPods version 1.14.3 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2022.3) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231) [✓] IntelliJ IDEA Community Edition (version 2022.2.5) • IntelliJ at /Applications/IntelliJ IDEA CE.app • Flutter plugin version 76.2.1 • Dart plugin version 222.4582 [✓] VS Code (version 1.88.1) • VS Code at /Users/junga/Desktop/Visual Studio Code.app/Contents • Flutter extension can be installed from: 🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter [✓] Connected device (4 available) • iPad (mobile) • 00008103-001A043E3ED0C01E • ios • iOS 17.2 21C62 • iPhone (mobile) • 00008101-001E11243E10801E • ios • iOS 17.4.1 21E236 • macOS (desktop) • macos • darwin-x64 • macOS 14.4.1 23E224 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 124.0.6367.119 ! Error: Browsing on the local area network for iPhone. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this Mac. The device must be opted into Developer Mode to connect wirelessly. (code -27) [✓] Network resources • All expected network resources are available. ! Doctor found issues in 1 category. Process finished with exit code 0 ```
darshankawar commented 2 weeks ago

@junga970 Can you provide flutter doctor -v, webview plugin version and iOS versions on which this behavior occurs ? Also, please provide complete runnable reproducible code sample (ex: main.dart) without third party implementation that we can directly copy paste and run to verify this further.

junga970 commented 1 week ago

@darshankawar

I've made the changes as you suggested!

darshankawar commented 1 week ago

Thanks for the update. Can you also confirm if it occurs with Impeller or without it as well ? Also, is there a way for you to check if the chart is rendered using native iOS + webview ?

junga970 commented 1 week ago

@darshankawar

The result is the same whether using Impeller or not. I'm not entirely sure about native iOS, but it's clear that webview is being used.

darshankawar commented 1 week ago

Thanks for the update. I see that you are using community packages such as image_saver and flutter_echarts. Is there a way for you to confirm if the same happens without using these package's implementation and just using RepaintBoundary ? See this for your reference: https://github.com/flutter/flutter/issues/102866