Home > Software design >  Is there a way to change the state of widget variable located in initState in flutter?
Is there a way to change the state of widget variable located in initState in flutter?

Time:11-27

  • I have a variable which contains a map of widget in initState.
  • One of this widget inside my variable is a gestureDetector who onTap change the value of a variable to change the animation of his child AnimatedAlign.

My problem is that when I active the onTap my animatedAlign stay static.

How should I do to be able to toogle the value of selected ?

import 'dart:developer';

import 'package:flutter/material.dart';

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

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  late Map<String, Map<String, List<Widget>>> data;

  bool selected = false;

  @override
  void initState() {
    // TODO: implement initState

    data = {
      "Animation and motion widgets": {
        "AnimatedAlign": [
          GestureDetector(
            onTap: () {
              setState(() {
                selected = !selected;
              });
              log('$selected inside data');
            },
            child: Center(
              child: Container(
                width: 250.0,
                height: 250.0,
                color: Colors.red,
                child: AnimatedAlign(
                  alignment:
                      selected ? Alignment.topRight : Alignment.bottomLeft,
                  duration: const Duration(seconds: 1),
                  curve: Curves.easeInCirc,
                  child: const FlutterLogo(size: 50.0),
                ),
              ),
            ),
          )
        ],
      },
      "Animation and motion widgets2": {
        "2widget1": [const Text('2widget1')],
        "2widget2": [const Text('2widget2')]
      }
    };
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Widget catalog'),
      ),
      body: PageView(
        children: _getCategories(),
      ),
    );
  }

  List<Widget> _getCategories() {
    List<Widget> categories = [];

    for (int i = 0; i < data.length; i  ) {
      categories.add(
        PageView(
          scrollDirection: Axis.vertical,
          children: getWidgets(i),
        ),
      );
    }
    return categories;
  }

  List<Widget> getWidgets(i) {
    List<Widget> widgetPage = [];
    widgetPage.add(Container(
      color: Colors.red,
      child: Center(
        child: Text(data.keys.toList()[i]),
      ),
    ));
    data[data.keys.toList()[i]]!.forEach((key, value) {
      widgetPage.add(Container(
        color: Colors.blue,
        child: Padding(
          padding: const EdgeInsets.only(top: 20.0),
          child: Column(
            children: [
              Center(child: Text(key)),
              Padding(
                padding: const EdgeInsets.all(20.0),
                child: Column(
                  children: value,
                ),
              ),
            ],
          ),
        ),
      ));
    });
    return widgetPage;
  }
}

CodePudding user response:

Everytime setState() is called, build() is called in response to it and all the widgets are rebuilt. However, initState() is called only when the StatefulWidget (HomeScreen in your case) is created.

The problem in your code is that AnimatedAlign widget is built only once when initState() is called. When setState() is called, your code reuses the same instance of AnimatedAlign as stored in data instead of rebuilding it.

For your code to work, you will have to instantiate data map object in build() instead of initState().

There are other ways of achieving this but this is the simplest in order for you to understand what is happening here.

CodePudding user response:

Create variable breaks the context chain, doesnt update the ui properly. Instead of create variable, you can create method that will be called inside build method. I am referring

  Map<String, Map<String, List<Widget>>> data() => {
        "Animation and motion widgets": {

And replace the use case data with data().

  • Related