flutter_percent_indicator icon indicating copy to clipboard operation
flutter_percent_indicator copied to clipboard

[LinearPercentIndicator] Cannot get size from a render object that has not been through layout

Open garbidge opened this issue 9 months ago • 0 comments

Fixes issue https://github.com/diegoveloper/flutter_percent_indicator/issues/175

Description:

It seems like this can at times be called before it has been through layout (in particular when restoring state). Changed to first check hasSize before using size.

Reproduction steps:

Using minimal sample code included below:

  • In Android emulator, go to developer options and enable "Don’t keep activities"
  • Run app
  • Click on button to restorablePush second route
  • Use device buttons to put app in background
  • Use device buttons to return to the app
  • It will restore and encounter this error

If relevant, this was reproduced on Android 12, Flutter 3.22.0

Sample code:

import 'package:flutter/material.dart';
import 'package:percent_indicator/linear_percent_indicator.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  Widget getView(BuildContext subContext, RouteSettings routeSettings) {
    switch (routeSettings.name) {
      case WidgetB.routeName:
        return const WidgetB();
      default:
        return const WidgetA();
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      restorationScopeId: "test",
      onGenerateRoute: (RouteSettings routeSettings) {
        var uri = Uri.parse(routeSettings.name ?? '');
        return MaterialPageRoute<void>(
          settings: routeSettings,
          builder: (BuildContext subContext) {
            return getView(subContext, RouteSettings(
                name: uri.path,
                arguments: routeSettings.arguments ?? uri.queryParameters));
          },
        );
      },
    );
  }
}

class WidgetA extends StatelessWidget {
  static const routeName = 'widget_a';

  const WidgetA({super.key,});

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      LinearPercentIndicator(),
      ElevatedButton(
        onPressed: () => Navigator.of(context).restorablePushNamed(WidgetB.routeName),
        child: const Text("Click me")
      )
    ],);
  }
}

class WidgetB extends StatelessWidget {
  static const routeName = 'widget_b';

  const WidgetB({super.key,});

  @override
  Widget build(BuildContext context) {
    return const Text("Now use device buttons to put app in background and then restore");
  }
}

garbidge avatar May 23 '24 07:05 garbidge