1
votes

Creating a sample calculator app in flutter. But no idea how to communicate each widgets, which are different dart files.

  • Main.dart ---------- ( starting point of the application)
  • CalculatorFrame.dart --------- ( importing numberboards , entry textbox and forms calculator view)
  • NumberButton.dart -------- ( represent the button widget)
  • NumberBoards.dart ---------- ( import numberbutton and creates the buttons ( 0-9) portion of the calculator)
  • EntryTextbox.dart ----------- ( represent the textbox entry for button pressed action and calculated values)

I have a difficulty to implement the interaction with these widgets. On button pressed, need to update the EntryTextbox widget. How can it be done if the widgets are in different dart files.

Please suggest.

2

2 Answers

3
votes
  • 1.) You need to make your CalculatorFrame a Stateful widget.
  • 2.) You need to create a state for your EntryTextbox widget like a userInput state to track what the current user input was.
  • 3.) You need to create a method to update the state by using the setState method that is built in when using the Stateful widget.
  • 4.) You need to pass that method to the NumberBoards then create a constructor to receive that method then pass the method to the NumberButton widget.
3
votes

To change the state of EntryTextbox widget when a button was pressed, declare a containing widget (I suppose it's CalculatorFrame) as StatefullWidget with String or whatever field, which you will initialize EntryTextbox from. Implement a function that changes that field when a button is pressed, and pass it as a constructor parameter to a NumberButton widget.
Here is a schematic example:

import 'package:flutter/material.dart';

class CalculatorFrame extends StatefulWidget {
  @override
  _CalculatorFrameState createState() => _CalculatorFrameState();
}

class _CalculatorFrameState extends State<CalculatorFrame> {
  String _text;

  @override
  Widget build(BuildContext context) => ...( // container widget of your choice
    EntryTextbox(text: _text),
    NumberButton(text: '0', onPressed: _onPressed,),
    ...,
    NumberButton(text: '9', onPressed: _onPressed,),
  );

  void _onPressed(String buttonText) =>
      setState(() => _text += buttonText);
}

class EntryTextbox extends StatelessWidget {
  final String text;

  const EntryTextbox({Key key, this.text}) : super(key: key);

  @override
  Widget build(BuildContext context) => ...(text: text); // text entry widget of your choice
}

class NumberButton extends StatelessWidget {
  final String text;
  final Function(String) onPressed;

  const NumberButton({Key key, this.onPressed, this.text}) : super(key: key);

  @override
  Widget build(BuildContext context) => ...Button( // button widget of your choice
    child: Text(text),
    onPressed: () => onPressed(text),
  );
}

Since in your example NumberButton widgets sit inside NumberBoards widget, it's NumberBoards responsibility to accept onPressed as a constructor parameter and pass it to each NumberButton constructor.
In my example, onPressed accepts String parameter - text of the button which was pressed. You might decide to pass int or perhaps a more complex data class.

This non-architectural approach works fine for tiny apps and samples. However, I'd rather recommend using BLoC or ScopedModel for your task. Simple app state management section of the official documentation might be helpful.