I´m learning flutter and as a first app I chose to make a calculator. I have got the layout set and now I need to do some work with data. The core of the problem is that I would like to change output (which is StatefullWidget) every time I press a button.
This is my main.dart where I use my custom widgets OutputWindow and Numberlane.
import 'package:flutter/material.dart';
import 'package:study_project/NumberLane.dart';
import 'NumberLane.dart';
import 'OutputWindow.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
var custom = OutputWindow();
//Function f = custom.outputText;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text("calculator"),
titleTextStyle: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
)),
body: Column(
//mainAxisAlignment: MainAxisAlignment.center,'
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
//textoutput
Expanded(child: OutputWindow()),
//input
Expanded(
child: NumberLane(4),
),
Expanded(
child: NumberLane(3),
),
Expanded(
child: NumberLane(2),
),
Expanded(
child: NumberLane(1),
),
])));
}
}
Numberlane is there just to make the code more readable and its only purpose is to fill rows with another custom class Button
import 'package:flutter/material.dart';
import 'Button.dart';
class NumberLane extends StatelessWidget {
int positioning = 0;
NumberLane(this.positioning);
@override
Widget build(BuildContext context) {
if (positioning == 1) {
return Row(
//crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(child: Button(".")),
Expanded(child: Button("0")),
Expanded(child: Button("=")),
Expanded(child: Button("/")),
],
);
} else if (positioning == 2) {
return Row(
//crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(child: Button("1")),
Expanded(child: Button("2")),
Expanded(child: Button("3")),
Expanded(child: Button(" ")),
],
);
} else if (positioning == 3) {
return Row(
//crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(child: Button("4")),
Expanded(child: Button("5")),
Expanded(child: Button("6")),
Expanded(child: Button("-")),
],
);
} else if (positioning == 4) {
return Row(
//crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(child: Button("7")),
Expanded(child: Button("8")),
Expanded(child: Button("9")),
Expanded(child: Button("*")),
],
);
} else {}
}
}
And here comes the problem. I have my TextButtons and from onPressed I need to call outputText method which is property of StatefullWidget OutputWindow. I would ideally like to change OutputWindow every time a button is tapped.
**Button
import 'package:flutter/material.dart';
import 'OutputWindow.dart';
class Button extends StatelessWidget {
String description;
//final Function outputText;
Button(this.description) {}
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
height: double.infinity,
child: TextButton(
onPressed: () => {/*****here********/ },
style: TextButton.styleFrom(
primary: const Color.fromARGB(255, 227, 100, 61)),
child: Text(
description,
style: const TextStyle(color: Color.fromARGB(255, 235, 88, 43)),
),
));
}
}
**OutputWindow
import 'package:flutter/material.dart';
import 'package:study_project/Button.dart';
import 'NumberLane.dart';
import 'main.dart';
class OutputWindow extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return OutputWindowState();
}
}
class OutputWindowState extends State<OutputWindow> {
String output = "0";
void outputText(String write) {
setState(() {
if (output == "0" ||
write == "." ||
write == " " ||
write == "-" ||
write == "*" ||
write == "/" ||
write == "=") {
output = write;
} else if (write != "." &&
write != " " &&
write != "-" &&
write != "*" &&
write != "/" &&
write != "=") {
output = write;
}
});
}
@override
Widget build(BuildContext context) {
return Text(output,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 35,
color: Colors.black87,
));
}
}
I have tried importing all packages and files but still couldn´t call the method and instantiation of my OutputWindow and calling the method via Instance.method(). Another thing that came my to mind is to pass function via pointer to constructor but that works only down the widget tree and I can´t get the method from OutputWindow to main.dart.
Thank you so much for your help.
CodePudding user response:
I have added some code so it will work.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(home: Home());
}
}
String outputText = "";
class Home extends StatefulWidget {
const Home({
Key? key,
}) : super(key: key);
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
String output = '';
@override
void initState() {
super.initState();
outputText = output;
}
changeOutut(String value) {
outputText = value;
setState(() {
output = value;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text("calculator"),
titleTextStyle: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
)),
body: Column(
//mainAxisAlignment: MainAxisAlignment.center,'
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
//textoutput
Expanded(
child: OutputWindow(
output: output,
)),
//input
Expanded(
child: NumberLane(4, changeOutut),
),
Expanded(
child: NumberLane(3, changeOutut),
),
Expanded(
child: NumberLane(2, changeOutut),
),
Expanded(
child: NumberLane(1, changeOutut),
),
]));
}
}
class NumberLane extends StatelessWidget {
final int positioning;
final dynamic changeOutut;
const NumberLane(this.positioning, this.changeOutut, {Key? key})
: super(key: key);
add(String value) {
changeOutut(outputText value);
}
@override
Widget build(BuildContext context) {
if (positioning == 1) {
return Row(
//crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(child: Button(".",add)),
Expanded(child: Button("0",add)),
Expanded(child: Button("=",add)),
Expanded(child: Button("/",add)),
],
);
} else if (positioning == 2) {
return Row(
//crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(child: Button("1",add)),
Expanded(child: Button("2",add)),
Expanded(child: Button("3",add)),
Expanded(child: Button(" ",add)),
],
);
} else if (positioning == 3) {
return Row(
//crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(child: Button("4",add)),
Expanded(child: Button("5",add)),
Expanded(child: Button("6",add)),
Expanded(child: Button("-",add)),
],
);
} else if (positioning == 4) {
return Row(
//crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(child: Button("7",add)),
Expanded(child: Button("8",add)),
Expanded(child: Button("9",add)),
Expanded(child: Button("*",add)),
],
);
} else {
return SizedBox();
}
}
}
class Button extends StatelessWidget {
final String description;
final dynamic add;
const Button(this.description,this.add, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
height: double.infinity,
child: TextButton(
onPressed: () => {
add(description),
},
style: TextButton.styleFrom(
primary: const Color.fromARGB(255, 227, 100, 61)),
child: Text(
description,
style: const TextStyle(color: Color.fromARGB(255, 235, 88, 43)),
),
));
}
}
class OutputWindow extends StatelessWidget {
final String output;
const OutputWindow({Key? key, required this.output}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(output,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 35,
color: Colors.black87,
));
}
}