1. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

[Flutter] Form set after Future.delayed won't rebuild after subsequent state change of variable

Discussão em 'Mobile' iniciado por Stack, Outubro 17, 2024 às 21:52.

  1. Stack

    Stack Membro Participativo

    I have a scenario in which I need to show a Form only after a certain Future is completed (In reality, it is after an animation is completed, but I simplified things in the snippet below for reproducibility).

    Then, when the form is filled and submitted and the answer provided in the form is correct, I need to change the color of the font of the form (among other things, but I'm simplifying).

    I've tried to do that (changing the form font color) by changing the value of a variable _isAnswerCorrect in a setState, which is passed down to a stateless widget NumberInputField, which is a wrapper to a TextFormField. However, the NumberInputField won't rebuild.

    I've also tried setting a key (both UniqueKey() and ValueKey(_isAnswerCorrect.toString())) to NumberInputField, since this solution worked for me in another similar scenarios, but neither have worked.

    Just copy and paste the code below in the dartpad to see the actual behavior (here it does not work):

    import 'package:flutter/material.dart';

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

    class MyApp extends StatelessWidget {
    const MyApp({super.key});

    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    home: const MyHomePage(),
    );
    }
    }

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

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

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

    Widget _questionForm = Container();

    final _formKey = GlobalKey<FormState>();

    void _answerIsCorrect() {
    setState(() {
    _isAnswerCorrect = true;
    });
    }

    @override
    Widget build(BuildContext context) {
    return Scaffold(
    body: Center(
    child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
    ElevatedButton(
    child: Text('Show form'),
    onPressed: () {
    Future.delayed(
    const Duration(milliseconds: 100),
    () => setState(
    () {
    _questionForm = SizedBox(
    width: 100,
    child: Column(
    children: [
    Form(
    key: _formKey,
    child: NumberInputField(
    isAnswerCorrect: _isAnswerCorrect,
    ),
    ),
    SizedBox(height: 20),
    ElevatedButton(
    child: Text('Change Color?'),
    onPressed: _answerIsCorrect,
    ),
    ],
    ),
    );
    },
    ),
    );
    },
    ),
    SizedBox(height: 20),
    _questionForm,
    ],
    ),
    ),
    );
    }
    }

    class NumberInputField extends StatelessWidget {
    final bool isAnswerCorrect;

    const NumberInputField({
    super.key,
    required this.isAnswerCorrect,
    });

    @override
    Widget build(BuildContext context) {
    Color fontColor = Colors.blue;

    if (isAnswerCorrect) {
    fontColor = Colors.black;
    }

    return TextFormField(
    style: TextStyle(color: fontColor),
    textAlign: TextAlign.center,
    decoration: InputDecoration(
    hintText: '?',
    ),
    );
    }
    }




    However, I had successfully managed to do that in another form that was not set only after a Future (here it works) (Just copy and paste the code below in the dartpad to see the behavior):

    import 'package:flutter/material.dart';

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

    class MyApp extends StatelessWidget {
    const MyApp({super.key});

    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    home: const MyHomePage(),
    );
    }
    }

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

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

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

    final _formKey = GlobalKey<FormState>();

    void _answerIsCorrect() {
    setState(() {
    print('setting state');
    _isAnswerCorrect = true;
    });
    }

    @override
    Widget build(BuildContext context) {
    return Scaffold(
    body: Center(
    child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
    SizedBox(
    width: 100,
    child: Column(
    children: [
    Form(
    key: _formKey,
    child: NumberInputField(
    isAnswerCorrect: _isAnswerCorrect,
    ),
    ),
    SizedBox(height: 20),
    ElevatedButton(
    child: Text('Change Color?'),
    onPressed: _answerIsCorrect,
    ),
    ],
    ),
    ),
    ],
    ),
    ),
    );
    }
    }

    class NumberInputField extends StatelessWidget {
    final bool isAnswerCorrect;

    const NumberInputField({
    super.key,
    required this.isAnswerCorrect,
    });

    @override
    Widget build(BuildContext context) {
    Color fontColor = Colors.blue;

    if (isAnswerCorrect) {
    fontColor = Colors.black;
    }

    return TextFormField(
    style: TextStyle(color: fontColor),
    textAlign: TextAlign.center,
    decoration: InputDecoration(
    hintText: '?',
    ),
    );
    }
    }




    I must be missing something very trivial here. Any ideas of why that might be?

    Continue reading...

Compartilhe esta Página