Home > Mobile >  Flutter switch animation is not showing in Alert Dialog
Flutter switch animation is not showing in Alert Dialog

Time:01-02

I have an alert dialog with a switch. If I press the switch, the boolean changes like I want it to (I have it set so the homepage background color changes based on the bool), but the switch animation does not register until I close out of the alert dialog and re-open it again. I tried wrapping it in a StatefulBuilder like I saw in another post, but in that case, the animation works but the bool does not change. I am trying to share this bool value throughout my app, so I'm using Shared Preferences.

here is the full code

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage();

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool bulb = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: bulb ? Colors.white : Colors.blue,
      appBar: AppBar(actions: <Widget>[
        IconButton(
            icon: Icon(Icons.settings),
            onPressed: () {
              showDialog(
                  context: context,
                  builder: (ctx) => AlertDialog(
                          content: Column(children: [
                        Switch(
                          value: bulb,
                          onChanged: (bool isChecked) async {
                            final prefs = await SharedPreferences.getInstance();
                            setState(() {
                              bulb = isChecked;
                              prefs.setBool('bulb', isChecked);
                            });
                          },
                        ),
                        StatefulBuilder(builder:
                            (BuildContext context, StateSetter setState) {
                          return Column(children: [
                            Switch(
                              value: bulb,
                              onChanged: (bool isChecked) async {
                                final prefs =
                                    await SharedPreferences.getInstance();
                                setState(() {
                                  bulb = isChecked;
                                  prefs.setBool('bulb', isChecked);
                                });
                              },
                            ),
                          ]);
                        })
                      ])));
            })
      ]),
      body: Center(),
    );
  }
}

Solution:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage();

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool bulb = false;
  Future openDialog() => showDialog(
      context: context,
      builder: (context) => StatefulBuilder(
          builder: (context, setState) => AlertDialog(
                  content: Column(children: [
                Switch(
                  value: bulb,
                  onChanged: (bool isChecked) async {
                    final prefs = await SharedPreferences.getInstance();
                    setState(() {
                      bulb = isChecked;
                      prefs.setBool('bulb', isChecked);
                    });
                  },
                ),
                ElevatedButton(
                    onPressed: () => Navigator.of(context).pop(),
                    child: Text("Save")),
              ]))));

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: bulb ? Colors.white : Colors.blue,
      appBar: AppBar(actions: <Widget>[
        IconButton(
            icon: Icon(Icons.settings),
            onPressed: () async {
              await openDialog();
              setState(() {});
            }),
      ]),
      body: Center(),
    );
  }
}

CodePudding user response:

You have to use the StatefulBuilder itself.

Now, when you are calling setState inside the dialog, only the state inside the dialog is changing. The state of the screen remains the same. This is why switch changed animation is happening but the bulb value in the screen is not changing.

The workaround is, you can use a callback function to call setState in the screen too, when the value of switch changes.

  • Related