- 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()
.