Flutter Userinput will only get displayed after a hotreload, but not in the application itself

Viewed 36

Hi im new to Flutter and coding and tried do build my first to do app. I've created a textformfield to add new todos with a button in a container above. I used the texteditingcontroller to get the userinput and stored the input in a variable. I tried to display the userInput on a toDoSection, but it only appears, if im hot reloading the application. My button, which should do the work instead, doesn't work. What did I do wrong here?

landing_page.dart

import 'package:flutter/material.dart';
import 'package:flutter_application_1/presentation/widgets/to_do_section.dart';

 final _textController = TextEditingController();
    String userInput = "";
class LandingPage extends StatefulWidget {
  const LandingPage({Key? key}) : super(key: key);

  @override
  State<LandingPage> createState() => _LandingPageState();
}

class _LandingPageState extends State<LandingPage> {
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      
      appBar: AppBar(
        title: const Center(child: Text("To-Do-App")),
        backgroundColor: Colors.redAccent,
      ),
      body: SingleChildScrollView(
        child: Column(
          children: [
            const ToDos(),
            ToDoAdd()
            ],
        ),
      ),
    );
  }

 

  Column ToDoAdd() {
    return Column(
          children:  [
            Padding(
              padding: EdgeInsets.only(top: 8.0, left: 20, right: 20, bottom: 20),
              child: TextField(
                controller: _textController,
                textAlign: TextAlign.center,
                decoration: InputDecoration(
                  border: OutlineInputBorder(),
                  hintText: "Add a new ToDo",
                )  ,
              ),
              
            ),
            MaterialButton(
              color: Colors.redAccent,
                onPressed: () {
                  setState(() {
                  userInput = _textController.text; 
                  toDoList.add(userInput);
                  
                });
                  
                },
                child: Text("Admit", style: TextStyle(color: Colors.white),),
                ),
                Text(userInput)
          ],
        );
  }


}

to_do_section.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/foundation/key.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter_application_1/presentation/widgets/landing_page.dart';
import 'package:flutter_application_1/responsive_layout.dart';

var toDoList = <String> [userInput];
class ToDos extends StatefulWidget {
  
  const ToDos({Key? key, }) : super(key: key);

  @override
  State<ToDos> createState() => _ToDosState();
}

class _ToDosState extends State<ToDos> {
  
  
  @override
  Widget build(BuildContext context) {
    SizeConfig().init(context);
    return Padding(
      padding: EdgeInsets.only(
          top: SizeConfig.blockSizeHorizontal * 10,
          left: SizeConfig.blockSizeVertical * 2.5,
          right: SizeConfig.blockSizeVertical * 2.5,
          bottom: SizeConfig.screenHeight / 8
          ),
      child: SizedBox(
        width: SizeConfig.blockSizeHorizontal*100,
        height: SizeConfig.blockSizeVertical*40,
        child: Container(
          decoration: BoxDecoration(
              color: Colors.grey[400],
              borderRadius: BorderRadius.circular(30),
              border: Border.all(
                  color: Colors.black45, style: BorderStyle.solid, width: 4)),
          child: Padding(
            padding:  EdgeInsets.all(8.0),
            child: Column(
              children: [
                   Text(userInput)               
                ]),
          ),
        ),
      ),
    );
  }
}
1 Answers

The following code should do the trick. The problem was not using setState to refresh the screen with the new data and not iterating over all values to display them (Also, moved global variables to local).

Check out the live demo on DartPad

enter image description here

And the code:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const LandingPage(),
    );
  }
}

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

  @override
  State<LandingPage> createState() => _LandingPageState();
}

class _LandingPageState extends State<LandingPage> {
  String userInput = "";
  var toDoList = <String>[];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Center(child: Text("To-Do-App")),
        backgroundColor: Colors.redAccent,
      ),
      body: SingleChildScrollView(
        child: Column(
          children: [ToDos(list: toDoList), ToDoAdd()],
        ),
      ),
    );
  }

  Column ToDoAdd() {
    return Column(
      children: [
        Padding(
          padding:
              const EdgeInsets.only(top: 8.0, left: 20, right: 20, bottom: 20),
          child: TextField(
            onChanged: (value) => setState(() => userInput = value),
            textAlign: TextAlign.center,
            decoration: const InputDecoration(
              border: OutlineInputBorder(),
              hintText: "Add a new ToDo",
            ),
          ),
        ),
        MaterialButton(
          color: Colors.redAccent,
          onPressed: () => setState(() => toDoList.add(userInput)),
          child: const Text(
            "Admit",
            style: TextStyle(color: Colors.white),
          ),
        ),
        Text(userInput)
      ],
    );
  }
}

class ToDos extends StatefulWidget {
  final List<String> list;
  const ToDos({
    Key? key,
    required this.list,
  }) : super(key: key);

  @override
  State<ToDos> createState() => _ToDosState();
}

class _ToDosState extends State<ToDos> {
  @override
  Widget build(BuildContext context) {
    SizeConfig().init(context);
    return Padding(
      padding: EdgeInsets.only(
          top: SizeConfig.blockSizeHorizontal * 10,
          left: SizeConfig.blockSizeVertical * 2.5,
          right: SizeConfig.blockSizeVertical * 2.5,
          bottom: SizeConfig.screenHeight / 8),
      child: SizedBox(
        width: SizeConfig.blockSizeHorizontal * 100,
        height: SizeConfig.blockSizeVertical * 40,
        child: Container(
          decoration: BoxDecoration(
              color: Colors.grey[400],
              borderRadius: BorderRadius.circular(30),
              border: Border.all(
                  color: Colors.black45, style: BorderStyle.solid, width: 4)),
          child: Padding(
            padding: EdgeInsets.all(8.0),
            child: Column(children: [
              for (final value in widget.list)
                Text(value),
            ]),
          ),
        ),
      ),
    );
  }
}

class SizeConfig {
  static late MediaQueryData _mediaQueryData;
  static late double screenWidth;
  static late double screenHeight;
  static late double blockSizeHorizontal;
  static late double blockSizeVertical;
  static late double _safeAreaHorizontal;
  static late double _safeAreaVertical;
  static late double safeBlockHorizontal;
  static late double safeBlockVertical;

  void init(BuildContext context) {
    _mediaQueryData = MediaQuery.of(context);
    screenWidth = _mediaQueryData.size.width;
    screenHeight = _mediaQueryData.size.height;
    blockSizeHorizontal = screenWidth / 100;
    blockSizeVertical = screenHeight / 100;
    _safeAreaHorizontal =
        _mediaQueryData.padding.left + _mediaQueryData.padding.right;
    _safeAreaVertical =
        _mediaQueryData.padding.top + _mediaQueryData.padding.bottom;
    safeBlockHorizontal = (screenWidth - _safeAreaHorizontal) / 100;
    safeBlockVertical = (screenHeight - _safeAreaVertical) / 100;
  }
}
Related