Skip to content

FlutterEngineGroup may affect RepaintBoundary toImage() #105392

@behind47

Description

@behind47

Problem description

Hello, I met a problem while using screen shot with RepaintBoundary toImage() in Project code https://github.com/flutter/samples/tree/master/add_to_app/multiple_flutters and I find the issue #89468 that mentioned the same problem but timeout. I provide my minimal code sample here.

Steps to Reproduce

  1. git clone https://github.com/flutter/samples/tree/master/add_to_app/multiple_flutters.
  2. replace lib/main.dart, add lib/entry_widget.dart with following code.
  3. run multiple_flutters_ios project.
  4. click button 'screen shot' on SingleViewController separately created without and with FlutterEngineGroup, and results is as follow.

Expected results:

click button 'screen shot' and result expected should be as follow:

Simulator Screen Shot - iPod touch (7th generation) - 2022-06-05 at 20 26 44

Actual results:

click next to SingleViewController created with FlutterEngineGroup, click button 'screen shot' and result expected is as follow, where space takes place of Micky in screen shot image:

Simulator Screen Shot - iPod touch (7th generation) - 2022-06-05 at 20 32 22

main.dart

// Copyright 2021 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'entry_widget.dart';

void main() => runApp(const MyApp(color: Colors.blue));

@pragma('vm:entry-point')
void topMain() => runApp(const MyApp(color: Colors.green));

@pragma('vm:entry-point')
void bottomMain() => runApp(const MyApp(color: Colors.purple));

class MyApp extends StatelessWidget {
  const MyApp({Key? key, required this.color}) : super(key: key);

  final MaterialColor color;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: color,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int? _counter = 0;
  late MethodChannel _channel;

  @override
  void initState() {
    super.initState();
    _channel = const MethodChannel('multiple-flutters');
    _channel.setMethodCallHandler((call) async {
      if (call.method == "setCount") {
        // A notification that the host platform's data model has been updated.
        setState(() {
          _counter = call.arguments as int?;
        });
      } else {
        throw Exception('not implemented ${call.method}');
      }
    });
  }

  void _incrementCounter() {
    // Mutations to the data model are forwarded to the host platform.
    _channel.invokeMethod<void>("incrementCount", _counter);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const MyEntryWiget(),
              const Text(
                'You have pushed the button this many times:',
              ),
              Text(
                '$_counter',
                style: Theme.of(context).textTheme.headline4,
              ),
              TextButton(
                onPressed: _incrementCounter,
                child: const Text('Add'),
              ),
              TextButton(
                onPressed: () {
                  _channel.invokeMethod<void>("next", _counter);
                },
                child: const Text('Next'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

entry_widget.dart

import 'dart:typed_data';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class MyEntryWiget extends StatefulWidget {
  const MyEntryWiget({Key? key}) : super(key: key);

  @override
  _MyEntryWigetState createState() => _MyEntryWigetState();
}

class _MyEntryWigetState extends State<MyEntryWiget> {
  late GlobalKey _globalKey;
  Uint8List? screenshot;
  @override
  void initState() {
    super.initState();
    _globalKey = GlobalKey();
  }

  @override
  Widget build(BuildContext context) {
    return RepaintBoundary(
        key: _globalKey,
        child: Column(
          children: [
            Container(
                width: 120,
                height: 120,
                child: Image.network(
                    "https://avatars.githubusercontent.com/u/30870216?v=4")),
            TextButton(
              onPressed: () async {
                screenshot = await captureImage(_globalKey);
                if (screenshot != null) setState(() {});
              },
              child: Text(
                "screen shot",
                style: TextStyle(color: Colors.red),
              ),
            ),
            if (screenshot != null) Image.memory(screenshot!),
          ],
        ));
    ;
  }

  /// pass return  data to any platform to show
  Future<Uint8List?> captureImage(GlobalKey rootKey) async {
    try {
      RenderRepaintBoundary boundary =
          rootKey.currentContext!.findRenderObject() as RenderRepaintBoundary;
      var image = await boundary.toImage(pixelRatio: 3.0);
      ByteData? byteData = await image.toByteData(format: ImageByteFormat.png);
      Uint8List? pngBytes = byteData?.buffer.asUint8List();
      return pngBytes;
    } catch (e) {
      print(e);
    }
    return null;
  }
}

flutter doctor -v

[✓] Flutter (Channel unknown, 3.0.0, on macOS 12.3 21E230 darwin-x64, locale zh-Hans-CN)
    • Flutter version 3.0.0 at /Users/behind47/flutter
    • Upstream repository unknown
    • Framework revision ee4e09cce0 (4 weeks ago), 2022-05-09 16:45:18 -0700
    • Engine revision d1b9a6938a
    • Dart version 2.17.0
    • DevTools version 2.12.2

[✗] Android toolchain - develop for Android devices
    ✗ Unable to locate Android SDK.
      Install Android Studio from: https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK components.
      (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.


[✓] Xcode - develop for iOS and macOS (Xcode 13.3)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • CocoaPods version 1.11.3

[✗] Chrome - develop for the web (Cannot find Chrome executable at /Applications/Google
    Chrome.app/Contents/MacOS/Google Chrome)
    ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.

[!] Android Studio
    • 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
    ✗ Unable to find bundled Java version.
    • Try updating or re-installing Android Studio.

[✓] VS Code (version 1.67.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.42.0

[✓] Connected device (2 available)
    • iPod touch (7th generation) (mobile) • 2165CFFF-9982-4AD2-B18B-BCA7B1A71C59 • iOS        •
      com.apple.CoreSimulator.SimRuntime.iOS-15-4 (simulator)
    • macOS (desktop)                      • macos                                • darwin-x64 • macOS 12.3
      21E230 darwin-x64

[✓] HTTP Host Availability
    • All required HTTP hosts are available

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work lista: existing-appsIntegration with existing apps via the add-to-app flowa: imagesLoading, displaying, rendering imagesengineflutter/engine related. See also e: labels.found in release: 3.0Found to occur in 3.0found in release: 3.1Found to occur in 3.1has reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-iosiOS applications specificallyr: fixedIssue is closed as already fixed in a newer version

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions