skip to Main Content

im programming an app with flutter and im a little bit stuck atm.
What I have in my mind: I have a Homescreen, that has a floatingAcctionButton. If you press this, another screen will open, where you can write some data (think of it like a formular).
As soon as you press the save button in the second screen, a ciruclar diagramm should get created in the homescreen, which functions as a container, where the formular is saved.
It should be possible to a couple of those formulars, so you have them next to each other.

This is my Code:

Homescreen

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../widgets/add_goal_button.dart';
import '../widgets/goal_app_bar.dart';

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

  @override
  _HomescreenWidgetState createState() => _HomescreenWidgetState();
}

class _HomescreenWidgetState extends State<HomescreenWidget> {
  final scaffoldKey = GlobalKey<ScaffoldState>();
  late FocusNode unfocusNode;

  @override
  void initState() {
    super.initState();
    unfocusNode = FocusNode();
  }

  @override
  void dispose() {
    unfocusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (Theme.of(context).platform == TargetPlatform.iOS) {
      SystemChrome.setSystemUIOverlayStyle(
        SystemUiOverlayStyle(
          statusBarBrightness: Theme.of(context).brightness,
          systemStatusBarContrastEnforced: true,
        ),
      );
    }

    return GestureDetector(
      onTap: () => unfocusNode.canRequestFocus
          ? FocusScope.of(context).requestFocus(unfocusNode)
          : FocusScope.of(context).unfocus(),
      child: Scaffold(
        backgroundColor: Colors.white,
        key: scaffoldKey,
        appBar: GoalAppBar(),
        body: SafeArea(
          top: true,
          child: Stack(
            children: [
              AddGoalButton(),
            ],
          ),
        ),
      ),
    );
  }
}

Checklist

import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:flutter/services.dart';
import '../utils/theme_utils.dart';
import 'dart:io';

import 'homescreen.dart';

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

  @override
  _ChecklistState createState() => _ChecklistState();
}

class _ChecklistState extends State<Checklist> {
  List<bool> checkBoxValues = [false, false, false, false, false];
  File? selectedImage;

  Future<void> _pickImage() async {
    final imagePicker = ImagePicker();
    try {
      final pickedFile = await imagePicker.pickImage(source: ImageSource.gallery);
      if (pickedFile != null) {
        setState(() {
          selectedImage = File(pickedFile.path);
        });
      }
    } on PlatformException catch (e) {
      print("Fehler beim Bildauswählen: $e");
    }
  }

  void _createCircleDiagram() {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => const HomescreenWidget()),
      //TODO
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Ziel"),
        backgroundColor: ThemeUtils.baseColor,
        actions: [
          IconButton(
            icon: const Icon(Icons.save),
            onPressed: () {
              _createCircleDiagram();
            },
          ),
        ],
      ),
      body: SingleChildScrollView(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Padding(
              padding: EdgeInsets.all(16.0),
              child: Text(
                "Mein SMARTes Ziel",
                style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
              ),
            ),
            Container(
              margin: const EdgeInsets.all(16),
              padding: const EdgeInsets.all(8),
              decoration: BoxDecoration(
                border: Border.all(color: Colors.grey),
              ),
              child: const TextField(
                keyboardType: TextInputType.multiline,
                maxLines: null,
                decoration: InputDecoration(
                  hintText: "Dein Text hier...",
                  border: InputBorder.none,
                ),
              ),
            ),
            const Padding(
              padding: EdgeInsets.all(16.0),
              child: Text(
                "Aktivitäten",
                style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
              ),
            ),
            Container(
              margin: const EdgeInsets.all(16),
              child: Column(
                children: List.generate(5, (index) {
                  return Row(
                    children: [
                      Checkbox(
                        value: checkBoxValues[index],
                        onChanged: (bool? value) {
                          setState(() {
                            checkBoxValues[index] = value ?? false;
                          });
                        },
                      ),
                      Expanded(
                        child: Container(
                          margin: const EdgeInsets.only(left: 8),
                          padding: const EdgeInsets.all(8),
                          decoration: BoxDecoration(
                            border: Border.all(color: Colors.grey),
                          ),
                          child: TextField(
                            keyboardType: TextInputType.multiline,
                            maxLines: null,
                            decoration: InputDecoration(
                              hintText: "Aktivität $index...",
                              border: InputBorder.none,
                            ),
                          ),
                        ),
                      ),
                    ],
                  );
                }),
              ),
            ),
            const Padding(
              padding: EdgeInsets.all(16.0),
              child: Text(
                "Mein Glaube",
                style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
              ),
            ),
            Container(
              margin: const EdgeInsets.all(16),
              child: GestureDetector(
                onTap: _pickImage,
                child: Container(
                  height: 200,
                  decoration: BoxDecoration(
                    border: Border.all(color: Colors.grey),
                  ),
                  child: selectedImage != null
                      ? Image.file(selectedImage!)
                      : const Center(
                    child: Text("Bild auswählen"),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

2

Answers


  1. @HatGuy
    I would create a homepage with the button. On onPressed, use ()=> context.go(String route). Additionally, create a MyFormPage implementing the Form widget with a Column/ListView as a child. Here, you can use the image picker, text form fields, etc. The widget will declare a GlobalKey, and with that, at the save button, you can perform _formState.save() and go back to the homepage. The saved fields can be passed as arguments to the router or can be saved in a state manager such as Bloc, etc.

    In the homepage, if the fields are not empty, you can load the circular diagram. There are libraries for this, such as https://pub.dev/packages/circular_chart_flutter.

    Hope that helps!

    Login or Signup to reply.
  2. You can achieve this by passing the values as parameters in the navigation.

    In HomeScreen.dart Add the below code in the function of your button press.

    //Global variables
    List<bool> checkBoxValues;
    File? selectedImage
    
    ElevatedButton(
                    onPressed: () async {
                      Map<String, dynamic> map = await Navigator.push(
                        context,
                        MaterialPageRoute(
                          builder: (context) => const Checklist(),
                        ),
                      );
                      setState(() {
                        checkBoxValues = map['checkBoxValues'];
                        selectedImage = map['selectedImage'];
                      });
                    },
                    child: const Text('Second Screen'),
                  ),
    

    In the above code await keyword is added before the Navigator.push() function and async keyword is added to make the onPressed function Future.
    The await keyword will wait for the SecondScreen (CheckList in your case) to pop and pass the map with values such as checkBoxValues and selectedImage.
    You can access these values using the map that is returned from the SecondScreen and assign it to a global variable and call setState() to rebuild the UI;

    In the secondScreen the function when you click save should be:

    void _createCircleDiagram() {
        Map<String, dynamic> map = {
          'checkBoxValues': checkBoxValues,
          'selectedImage': selectedImage
        };
        Navigator.pop(context, map);
        // Navigator.push(
        //   context,
        //   MaterialPageRoute(builder: (context) => const HomescreenWidget()),
        //   //TODO
        // );
      }
    

    Create a map which will hold all the values that you need to pass to first screen. Similarly you can pass any text values from the textfiels through the map.

    Secondly, you may use Navigator.pop() instead of Navigator.push() to return to HomeScreen.

    pop is used to pop current screen from the stack, so it will close the second screen and go back to first screen.

    If you use push in second screen the first page will be again created resulting in two first screens at the first and last of the stack.

    Now whenever you call the function on save button click, a map containing the values will be created and passed as the second parameter to Navigator.pop() function. Then the same map will be retrieved at the HomeScreen and will set the view according to the values received.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search