skip to Main Content

I’m new to learning flutter and am learning about navigation. I have two screens in my app. The first screen has a button which pushes a named route along with arguments to the second screen. The second screen displays the arguments and when the back button on the appBar is pressed, I want the first screen to completely rebuild. I tried popping the first screen and then pushing it again and that causes some misbehaviors. Is there any other way?

I tried using .then method and setting the state again in it, but that does not work as well. Here’s the problem I’m facing:

enter image description here

The number should start from 1 but it just shows 1 and on increment it does not show 2. Here’s the code to reproduce the result:

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

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark(useMaterial3: true),
      routes: {
        '/list_screen': (ctx) => const NextScreen(),
      },
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Practice App'),
        ),
        body: const MyStatefulWidget(),
      ),
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  const MyStatefulWidget({super.key});

  @override
  State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  double noOfItems = 1;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const Text('Choose number of list view items:'),
          SizedBox(
            height: 75,
            child: Center(
              child: Text(noOfItems.round().toString()),
            ),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              UIStepper(
                value: noOfItems,
                stepValue: 1,
                onChanged: (double newValue) {
                  setState(() {
                    noOfItems = newValue;
                  });
                },
                showLabel: false,
              ),
            ],
          ),
          const SizedBox(height: 100),
          ElevatedButton(
            onPressed: () {
              Navigator.pushNamed(
                context,
                '/list_screen',
                arguments: noOfItems.round(),
              ).then((_) => setState(() {
                    noOfItems = 1;
                  }));
            },
            child: const Text('Go'),
          ),
        ],
      ),
    );
  }
}

class NextScreen extends StatefulWidget {
  const NextScreen({super.key});

  @override
  State<NextScreen> createState() => _NextScreenState();
}

class _NextScreenState extends State<NextScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ListView with ${getNoOfItems(ctx: context)} entries'),
      ),
      body: ListView.separated(
        itemBuilder: (BuildContext context, int index) {
          return Center(
            child: Padding(
              padding: const EdgeInsets.symmetric(vertical: 8.0),
              child: Text('Item ${index + 1}'),
            ),
          );
        },
        separatorBuilder: (BuildContext context, int index) => const Divider(),
        itemCount: getNoOfItems(ctx: context),
      ),
    );
  }
}

int getNoOfItems({required BuildContext ctx}) {
  String strNum = (ModalRoute.of(ctx)?.settings.arguments).toString();
  int number = int.parse(strNum);
  return number;
}

For UIStepper(version: 0.0.2) I’m using the package: https://pub.dev/packages/uistepper

I am running the code on simulator.

2

Answers


  1. The behavior of the back button on a screen depends on the platform or framework you’re using for development.

    1. Identify the platform/framework: Determine the platform or framework you’re working with, such as Android, iOS, or web (React, Angular, etc.). Different platforms have different mechanisms for handling the back button.
    2. Listen for back button press event: Most platforms provide an event or callback that is triggered when the back button is pressed. You need to identify and register a listener for this event.
    Login or Signup to reply.
  2. This is actually a very common task.

    To rebuild the First screen after the second screen was popped, you can do the following:

    Assuming that you are using Navigator.push to push a new screen onto the stack, Navigator.push returns a Future after popping from the second screen. so just use .then() and call setState:

    ElevatedButton(
                  onPressed: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(builder: (context) => const SecondScreen()),
                    ).then((_) => setState(() {}));
                  },
                  child: const Text('Launch screen'),
                ),
    
    

    Here is complete working example, it will update the counter variable (and UI) on the first screen everytime you push from the second screen:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(
        const MaterialApp(
          title: 'Updating the first Screen',
          home: FirstScreen(),
        ),
      );
    }
    
    class FirstScreen extends StatefulWidget {
      const FirstScreen({Key? key}) : super(key: key);
    
      @override
      State<FirstScreen> createState() => _FirstScreenState();
    }
    
    class _FirstScreenState extends State<FirstScreen> {
      var _counter = 0;
      @override
      Widget build(BuildContext context) {
        return SafeArea(
          child: Scaffold(
              body: Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  'Counter is $_counter',
                ),
                ElevatedButton(
                  onPressed: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(builder: (context) => const SecondScreen()),
                    ).then((_) => setState(() {
                          _counter++;
                        }));
                  },
                  child: const Text('Launch screen'),
                ),
              ],
            ),
          )),
        );
      }
    }
    
    class SecondScreen extends StatelessWidget {
      const SecondScreen({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return const Scaffold(body: Center(child: Text('Second Screen')));
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search