Flutter After Layout - Brings functionality to execute code after the first layout of a widget has been performed

Overview

Flutter Community: after_layout

Flutter After Layout

pub package

Brings functionality to execute code after the first layout of a widget has been performed, i.e. after the first frame has been displayed.

Quick Usage

Add with AfterLayoutMixin mixin to your State class and then implement the void afterFirstLayout(BuildContext context) abstract method. Code in this method will be called the first time this widget is laid out on the screen.

Motivation

If you want to display a widget that depends on the layout, such as a Dialog or BottomSheet, you can not use that widget in initState.

You might have tried this.

BAD CODE

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'After Layout - Bad Example',
      home: new HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  @override
  HomeScreenState createState() => new HomeScreenState();
}

class HomeScreenState extends State<HomeScreen> {
  @override
  void initState() {
    super.initState();
    // NOTE: Calling this function here would crash the app.
    showHelloWorld();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(body: new Container(color: Colors.red));
  }

  void showHelloWorld() {
    showDialog(
      context: context,
      builder: (context) => new AlertDialog(
            content: new Text('Hello World'),
            actions: <Widget>[
              new FlatButton(
                child: new Text('DISMISS'),
                onPressed: () => Navigator.of(context).pop(),
              )
            ],
          ),
    );
  }
}

Usage

This demo showcases how this package resolves the shortcomings shown above:

GOOD CODE

new AlertDialog( content: new Text('Hello World'), actions: [ new FlatButton( child: new Text('DISMISS'), onPressed: () => Navigator.of(context).pop(), ) ], ), ); } }">
import 'package:flutter/material.dart';
import 'package:after_layout/after_layout.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'After Layout - Good Example',
      home: new HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  @override
  HomeScreenState createState() => new HomeScreenState();
}

class HomeScreenState extends State<HomeScreen> with AfterLayoutMixin<HomeScreen> {

  @override
  Widget build(BuildContext context) {
    return new Scaffold(body: new Container(color: Colors.red));
  }

  @override
  void afterFirstLayout(BuildContext context) {
    // Calling the same function "after layout" to resolve the issue.
    showHelloWorld();
  }

  void showHelloWorld() {
    showDialog(
      context: context,
      builder: (context) => new AlertDialog(
            content: new Text('Hello World'),
            actions: <Widget>[
              new FlatButton(
                child: new Text('DISMISS'),
                onPressed: () => Navigator.of(context).pop(),
              )
            ],
          ),
    );
  }
}
Comments
  • error: The class 'AfterLayoutMixin' can't be used as a mixin because it extends a class other than Object

    error: The class 'AfterLayoutMixin' can't be used as a mixin because it extends a class other than Object

    Unable to use this package.

    Flutter 0.10.2-pre.53 • channel master • https://github.com/flutter/flutter.git
    Framework • revision 549e8e07c6 (4 days ago) • 2018-10-24 14:41:16 -0700
    Engine • revision 2586e94122
    Tools • Dart 2.1.0-dev.7.1.flutter-45f9462398
    
    opened by shashkiranr 8
  • Migrate to null safety

    Migrate to null safety

    Description

    All dependencies are migrated to null safety. So we should migrate this package to null safety. Resources

    https://www.youtube.com/watch?v=eBr5tlumwlg&feature=youtu.be https://medium.com/dartlang/announcing-dart-null-safety-beta-87610fee6730

    opened by kw2019ltd 4
  • after_layout VS addPostFrameCallback

    after_layout VS addPostFrameCallback

    Please help me understand the difference between this package and using WidgetsBinding.instance!.addPostFrameCallback in initState. A call back works fine for me, I just don't know if I am missing something? Thanks

    opened by mellowcello77 3
  • I want to wait for some data to load before i show the dialog

    I want to wait for some data to load before i show the dialog

    in my project i get data from database on initialization, and i want to show dialog after the data is fetched . can this library help me? the dialog pop up even before the data is fetched.

    opened by Emmanuelfrimpong 3
  • Hi,see SchedulerBinding.instance.endOfFrame,it's more simple

    Hi,see SchedulerBinding.instance.endOfFrame,it's more simple

    Hi,I try this:

    
    SchedulerBinding.instance.endOfFrame.then((value){
            showDialog(
              context: context,
              builder: (context){
                return Text('hello');
              }
            );
          });
    

    it can work nice!.

    opened by fantasy525 3
  • 'initState' is inherited as a getter (from 'State') and also a method (from 'AfterLayoutMixin').

    'initState' is inherited as a getter (from 'State') and also a method (from 'AfterLayoutMixin').

    import 'package:flutter/material.dart';
    import 'package:after_layout/after_layout.dart';
    
    class IntroPage extends StatefulWidget {
      @override
      _IntroPageState createState() => _IntroPageState();
    }
    
    class _IntroPageState extends State<IntroPage> with AfterLayoutMixin<IntroPage> {
      BuildContext ctx;
      
    @override
      Widget build(BuildContext context) {
        ctx = context;
        return new Scaffold(body: new Container(color: Colors.red));
      }
    
       @override
      void afterFirstLayout(BuildContext context) {
        // Calling the same function "after layout" to resolve the issue.
        firstRun();
      }
    
      Future<Null> firstRun() async {
         print("first run");
        
      }
    }
    

    please healp! I keep getting 'initState' is inherited as a getter (from 'State') and also a method (from 'AfterLayoutMixin'). thats my page code above.

    opened by igabice 2
  • VS Code dart linter error

    VS Code dart linter error

    Hi, I'm happily using this library but I have an error using it with Visual Studio Code. In fact, it's telling me this:

    [dart] The class 'AfterLayoutMixin' can't be used as a mixin because it extends a class other than Object. abstract class AfterLayoutMixin<T extends StatefulWidget> extends State<T>

    Except this, I have no problems compiling the app.

    opened by LRNZ09 2
  • Throws unhandled exception

    Throws unhandled exception

    E/flutter (28609): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
    E/flutter (28609): Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.
    E/flutter (28609): #0      State.context.<anonymous closure> (package:flutter/src/widgets/framework.dart:1088:9)
    E/flutter (28609): #1      State.context (package:flutter/src/widgets/framework.dart:1094:6)
    E/flutter (28609): #2      AfterLayoutMixin.initState.<anonymous closure> (package:after_layout/after_layout.dart:10:31)
    E/flutter (28609): #3      _rootRunUnary (dart:async/zone.dart:1362:47)
    E/flutter (28609): #4      _CustomZone.runUnary (dart:async/zone.dart:1265:19)
    E/flutter (28609): #5      _FutureListener.handleValue (dart:async/future_impl.dart:152:18)
    E/flutter (28609): #6      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:704:45)
    E/flutter (28609): #7      Future._propagateToListeners (dart:async/future_impl.dart:733:32)
    E/flutter (28609): #8      Future._completeWithValue (dart:async/future_impl.dart:539:5)
    E/flutter (28609): #9      Future._asyncCompleteWithValue.<anonymous closure> (dart:async/future_impl.dart:577:7)
    E/flutter (28609): #10     _rootRun (dart:async/zone.dart:1354:13)
    E/flutter (28609): #11     _CustomZone.run (dart:async/zone.dart:1258:19)
    E/flutter (28609): #12     _CustomZone.runGuarded (dart:async/zone.dart:1162:7)
    E/flutter (28609): #13     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1202:23)
    E/flutter (28609): #14     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
    E/flutter (28609): #15     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
    E/flutter (28609): 
    
    opened by alr2413 1
  • State build method blocked when running in release mode

    State build method blocked when running in release mode

    Tested on devices:

    • Android 11 SDK / API Level 30 (physical release/debug and emulated debug)
    • Android 9 Pie / API Level 28 (physical release/debug)

    I'm finding that when I implement the afterFirstLayout override, it works fine with debug builds (physical device, and emulated), but with a release build, I'm not seeing anything being drawn by the build method of my StatefulWidget's State class (_LoadingState.build).

    I was trying to make a splash screen that drew first, and then did some loading, and once done it would forward the result onto a new Navigator screen.

    Hopefully this makes sense:

    import 'package:after_layout/after_layout.dart';
    import 'package:flutter/material.dart';
    import 'dart:io';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      final String title = "My App Title";
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: title,
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          initialRoute: Loading.routeName,
          routes: {
            Loading.routeName: (context) => Loading(),
            Home.routeName: (context) => Home(),
          },
        );
      }
    }
    
    class HomeArgs {
      final TimeProvider time;
      HomeArgs(this.time);
    }
    
    class Home extends StatelessWidget {
      static const routeName = '/Home';
    
      @override
      Widget build(BuildContext context) {
        final HomeArgs args = ModalRoute.of(context).settings.arguments;
        final TimeProvider time = args.time;
        return Scaffold(
          body: Center(
              child: Text(
            "Loading...",
            style: TextStyle(fontSize: 30),
          )),
        );
      }
    }
    
    class Loading extends StatefulWidget {
      static const routeName = '/';
      @override
      _LoadingState createState() => _LoadingState();
    }
    
    class _LoadingState extends State<Loading> with AfterLayoutMixin<Loading> {
      static const int delay = 3;
    
      @override
      Widget build(BuildContext context) {
    	// _LoadingState.build isn't being drawn in release mode
        return Scaffold(
          body: SafeArea(
              child: Center(
                  child: Text('Loading Screen. Waiting for $delay seconds'))),
        );
      }
    
      @override
      void afterFirstLayout(BuildContext context) {
        final time = new TimeProvider();
        sleep(const Duration(seconds: delay));
        Navigator.pushReplacementNamed(
          context,
          Home.routeName,
          arguments: HomeArgs(time),
        );
      }
    }
    
    

    Interestingly, I notice the same behaviour when I use an alternate method:

    class _LoadingState extends State<Loading> {
    
      // ...
    
      @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addPostFrameCallback((_) => load(context));
      }
    
      // ...
    
      void load(BuildContext context) {
        final time = new TimeProvider();
        sleep(const Duration(seconds: delay));
        Navigator.pushReplacementNamed(
          context,
          Home.routeName,
          arguments: HomeArgs(time),
        );
      }
    
      // ...
    
    }
    
    opened by jameswilliamknight 1
  • Ensure that the callback is called only once.

    Ensure that the callback is called only once.

    I've used this plugin for a while now and I noticed that the callback sometimes is called twice, and I'm certain it's not a problem in my code. So this small fix will ensure that it's indeed called once.

    opened by noordawod 1
  • Context Issues

    Context Issues

    Hi,

    I'm experiencing an issue when i use this library,

    So i wanted to do Navigator.of(context).pushReplacement inside a stream that called inside afterFirstLayout callback

    But, when the pushReplacement is called, the old page's dispose method didn't get called. Frankly, when i call the pushReplacement method inside a button's onTap callback, it did and ran successfully.

    Did anybody had a clue or ever experiencing this kind of problem?

    Thanks!

    opened by blackmenthor 1
Owner
Flutter Community
A central place for all community made Flutter packages. To get started, see the README of the 'community' repository.
Flutter Community
Flutter package for displaying and animating Scalable Vector Graphics 1.1 files. The package has been written solely in Dart Language.

Animated SVG | Flutter Package Flutter package for displaying and animating Scalable Vector Graphics 1.1 files. The package has been written solely in

Bulent Baris Kilic 5 Jul 19, 2022
This application displays the characters of the series Breaking Bad, has been used Cubit state and API .

breaking_bad A new Flutter project using bloc. Getting Started This project is a starting point for bloc state_management. A few resources to get you

null 1 Dec 24, 2021
In this project, I performed a RESTful API operation with MobX.

In this project, I performed a RESTful API operation with MobX. When we click on one of the listed users, the post information of that user is display

Dilber KILIÇ 11 Sep 7, 2022
Material color picker, you can customize colors. Selection in two step, first main color and after shades.

Flutter Material Color Picker Material Color picker is a Flutter widget, that can be customizable. By default, it's Material Colors, but you can defin

Jean-Charles Moussé 70 Nov 25, 2022
A Flutter plugin which allows you to execute code in the background on Android and iOS.

Flutter Workmanager Flutter WorkManager is a wrapper around Android's WorkManager, iOS' performFetchWithCompletionHandler and iOS BGAppRefreshTask, ef

Flutter Community 699 Jan 5, 2023
Automatically generate profile picture with random first name and background color. But you can still provide pictures if you have them. As the default color, based on the name of the first letter. :fire: :fire: :fire:

FLUTTER PROFILE PICTURE Automatically generate profile picture with random first name and background color. But you can still provide pictures if you

Aditya Dharmawan Saputra 10 Dec 20, 2022
Makes it possible to safely execute and retry a Future inside a StatelessWidget

futuristic Makes it possible to safely execute and retry a Future inside a StatelessWidget. See the Mainstream package for a similar API for working w

Martin Rybak 28 Sep 15, 2022
A plugin that brings native iOS keyboard behavior to Flutter.

iKeyboard A plugin that brings native iOS keyboard behavior to Flutter. Getting Started Just put IKeyboard as MaterialApp ancestor and put IKeyboard.b

Jonny Borges 1 May 4, 2022
A flutter plugin that brings an in-background android app to the foreground

bg_launcher A flutter plugin that brings an in-background android app to the foreground (Android only) Restrictions on starting activities from the ba

Iheb Briki 5 Nov 25, 2022
A grid-based layout system for Flutter, inspired by CSS Grid Layout

Flutter Layout Grid A powerful grid layout system for Flutter, optimized for complex user interface design. Click images to see their code ✨ Featuring

Felt 307 Dec 24, 2022
A grid-based layout system for Flutter, inspired by CSS Grid Layout

Flutter Layout Grid A powerful grid layout system for Flutter, optimized for complex user interface design. Click images to see their code ✨ Featuring

Felt 307 Dec 24, 2022
Ruqe brings the convenient types and methods found in Rust into Dart, such as the Result, Option, pattern-matching, etc.

ruqe Ruqe brings the convenient types and methods found in Rust into Dart, such as the Result, Option, pattern-matching, etc. Additionally, the librar

Alexander Nitiola 12 Dec 28, 2022
A flutter plugin about qr code or bar code scan , it can scan from file、url、memory and camera qr code or bar code .Welcome to feedback your issue.

r_scan A flutter plugin about qr code or bar code scan , it can scan from file、url、memory and camera qr code or bar code .Welcome to feedback your iss

PengHui Li 112 Nov 11, 2022
A Flutter widget to show an icon collection to pick. This widget extend TextField and has a similar behavior as TextFormField

icon_picker A Flutter widget to show an icon collection to pick. This widget extend TextField and has a similar behavior as TextFormField Usage In the

m3uzz Soluções em TI 11 Sep 27, 2022
Searchhelperexample - SearchHelper - code wrapper for searching functionality

Overview SearchHelper is code wrapper for searching functionality developed by D

Osama Qureshi 3 Dec 19, 2022
A GraphQL client for Flutter, bringing all the features from a modern GraphQL client to one easy to use package. Built after react apollo

Flutter GraphQL Table of Contents Flutter GraphQL Table of Contents About this project Installation Usage GraphQL Provider [Graphql Link and Headers]

Snowball Digital 45 Nov 9, 2022
I just designed this within 30 min after watching a video by tech school on YouTube.

nft_app A new Flutter application. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if t

ogunmolu oluwaseun 0 Dec 25, 2021
A flutter UI package provides a cell widget that has leading and trailing swipe action menu.

Language: English |中文简体 flutter_swipe_action_cell A package that can give you a cell that can be swiped ,effect is like iOS native If you like this pa

WenJingRui 261 Jan 7, 2023
A widget that has a collapsible app bar.

CollapsibleAppBar A widget that has a collapsible app bar. Click to view Screenshots Expanded Collapsed Getting started Add dependency in your pubspec

null 3 Sep 15, 2022