Flutter RenderFlex and setState issue while doing buttons and callbacks - flutter

Hello I am getting two errors on my code, this code should produce a input box where when the information is submitted via a button it pushes that to the body of the page.
The issues are:
The following assertion was thrown during layout: A RenderFlex
overflowed by 99359 pixels on the bottom.
The following assertion was thrown building TextInputWidget(dirty,
state: _TextInputWidgetState#e5726): setState() or markNeedsBuild()
called during build.
main.dart:
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.orange,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String text = "";
void changeText(String text) {
this.setState(() {
this.text = text;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Hello World!'),
),
body: Column(
children: <Widget>[
TextInputWidget(this.changeText),
Text(this.text),
],
),
);
}
}
class TextInputWidget extends StatefulWidget {
final Function(String) callback;
TextInputWidget(this.callback);
#override
_TextInputWidgetState createState() => _TextInputWidgetState();
}
class _TextInputWidgetState extends State<TextInputWidget> {
final controller = TextEditingController();
#override
void dispose() {
super.dispose();
controller.dispose();
}
click() {
widget.callback(controller.text);
controller.clear();
}
#override
Widget build(BuildContext context) {
return TextField(
controller: this.controller,
decoration: InputDecoration(
prefixIcon: Icon(Icons.message),
labelText: "Type a message.",
suffixIcon: IconButton(
icon: Icon(Icons.send),
splashColor: Colors.orange,
tooltip: "Post message",
onPressed: this.click(),
)));
}
}

The issue is coming from onPressed: this.click(),. It is calling/running the method while first build, but you wish to call it when button is pressed, in this case do it like.
onPressed: click,
If you like to have move things inside onPressed do it like
onPressed: () {
click();
},

Related

How to delete a custom TextFormField in a list of custom TextFormFields without losing the information in the other TextFormFields?

I tried to create a list of custom TextformField which can be deleted using a button with the Map function but the Textformfield is not deleting properly.
It is always the last Widget that is deleted.
Does anyone have a solution?
Est-ce qu'il est possible de créer un objet qui peut se suprrimer lui même ?
Thanks !
Here is my test code
you can try this code in Darpad
enter image description here
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late List<int> _listID = [0, 1, 2, 3];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: _listID.map((id) {
print(id);
return TestWidget(
id: id,
onPressed: () {
setState(() {
_listID.remove(id);
print(_listID);
});
},
);
}).toList()),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
class TestWidget extends StatefulWidget {
TestWidget({super.key, this.onPressed, required this.id});
late VoidCallback? onPressed;
late int id;
#override
State<TestWidget> createState() =>
_TestWidgetState(onPressed: this.onPressed, id: id);
}
class _TestWidgetState extends State<TestWidget> {
late VoidCallback? onPressed;
late int id;
_TestWidgetState({required this.id, this.onPressed});
#override
Widget build(BuildContext context) {
return TextFormField(
decoration: InputDecoration(
labelText: id.toString(),
suffixIcon: IconButton(
icon: const Icon(Icons.clear), onPressed: () => onPressed!()),
));
}
}
You dont need to pass data to state class, you can use widget.variableName
class TestWidget extends StatefulWidget {
const TestWidget({super.key, this.onPressed, required this.id});
final VoidCallback? onPressed;
final int id;
#override
State<TestWidget> createState() => _TestWidgetState();
}
class _TestWidgetState extends State<TestWidget> {
#override
Widget build(BuildContext context) {
return TextFormField(
decoration: InputDecoration(
labelText: widget.id.toString(),
suffixIcon: IconButton(
icon: const Icon(Icons.clear), onPressed: () => widget.onPressed!()),
));
}
}
you have to pass a key to your TestWidget to preserve the state object of every widget here is how:
return TestWidget(
key: ValueKey(id), // a value key with id as a value for every TestWidget
id: id,
onPressed: () {
setState(() {
_listID.remove(id);
print(_listID);
});
},
);
you can learn more about keys from the Flutter youtube channel
Finally for a perfect behavior of what I wanted to do I had to define a class TestWidgetData to contain the data of each widget TestWidget, including the unique identifier and the user name. When the user presses the "clear" button in one of the TestWidget widgets, I use the removeWhere method of the _listData list to remove the item corresponding to the given id, rather than removing an item from the index given. This keeps the state of existing TestWidget widgets when I delete an item from the list, rather than rebuilding them all.
Thank you for your answers they were very helpful!
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<TestWidgetData> _listData = [
TestWidgetData(id: 0, textValue: ""),
TestWidgetData(id: 1, textValue: ""),
TestWidgetData(id: 2, textValue: ""),
TestWidgetData(id: 3, textValue: ""),
];
void removeTestWidgetData(int id) {
setState(() {
_listData.removeWhere((data) => data.id == id);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: _listData.map((data) {
return TestWidget(
key: ValueKey(data.id),
data: data,
onPressed: () {
removeTestWidgetData(data.id);
},
);
}).toList()),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
class TestWidget extends StatefulWidget {
final TestWidgetData data;
final VoidCallback? onPressed;
const TestWidget({
Key? key,
required this.data,
this.onPressed,
}) : super(key: key);
#override
State<TestWidget> createState() => _TestWidgetState();
}
class _TestWidgetState extends State<TestWidget> {
final TextEditingController textController = TextEditingController();
#override
void initState() {
super.initState();
textController.text = widget.data.textValue;
}
#override
Widget build(BuildContext context) {
return TextFormField(controller: textController,
decoration: InputDecoration(
labelText: widget.data.id.toString(),
suffixIcon: IconButton(
icon: const Icon(Icons.clear), onPressed: () => widget.onPressed!()),
));
}
}
class TestWidgetData {
final int id;
String textValue;
TestWidgetData({required this.id, required this.textValue});
}

How to fix hive box already open error in flutter?

I am trying to use hive to store data on a local machine using hive but each time when I compile the code it gives the error "The box "notebook" is already open and of type Box."
Can someone help me to resolve the issue as I am new to it? Thanks
I am just trying to add data to the database in this app without any change to the state of the app interface. I have tried to change the main method to void but no luck on this.
All the code is located in the main file
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'notes.dart';
import 'notesStoring.dart';
Future main() async{
WidgetsFlutterBinding.ensureInitialized();
await Hive.initFlutter();
Hive.registerAdapter(NotesAdapter());
await Hive.openBox<NotesAdapter>('noteBook');
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
#override
void dispose() {
Hive.close();
// TODO: implement dispose
super.dispose();
}
#override
Future incrementCounter(String title) async {
final notes = Notes()
..title = title;
final box =Boxes.getNotesValues();
box.add(notes);
}
final titleForNotes=TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body:
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
TextField(
controller: titleForNotes,
cursorColor: Colors.pink,
),
ValueListenableBuilder<Box<Notes>>(valueListenable: Boxes.getNotesValues().listenable(), builder: (context,box,_){
final noteBook =box.values.toList().cast<Notes>();
return buildContent(noteBook);
})
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
incrementCounter(titleForNotes.text);
},
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
class Boxes {
static Box<Notes> getNotesValues()=>Hive.box<Notes>('noteBook');
}
Widget buildContent(List<Notes> noteBook){
return Column(
children: [
Expanded(child:
ListView.builder(
padding: EdgeInsets.all(8),
itemCount: noteBook.length,
itemBuilder: (BuildContext context, int index){
final notes= noteBook[index];
return buildTransaction(context, notes);
}
)
)
],
);
}
Widget buildTransaction(
BuildContext context,
Notes notes,
){
return Card(
color: Colors.green,
child: Text(notes.title),
);
}
1.You can open your notebook Box in the main method of your app:
Future<void> main() async {
...
final appDocumentDirectory = await
path_provider.getApplicationDocumentsDirectory();
Hive.init(appDocumentDirectory.path);
Hive.registerAdapter(UserAdapter());
// open the user box
await Hive.openBox('notebook');
_setUpLogging();
runApp(MultiProvider(providers: providers, child:
StartupApplication()));
}
2 Access the previously opened box like below:
class MyHomePage extends StatefulWidget {
const MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// user box
Box notebookBox;
#override
void initState() {
super.initState();
// get the previously opened user box
notebookBox = Hive.box('notebook');
}
#override
Widget build(BuildContext context) {
// check for your conditions
return (notebookBox.values.isNotEmpty && notebookBox.get(0).active == 1)
? HomeView()
: Intro();
}
}

How to Change Button text depending on textfield?

enter image description here
Here I want to change the button which depends on a text field, like when the text field is filled then show the button C, and when clicked the C button then change the button name C to AC and also need to change text field fill to empty.
check this example to demonstrate the output you need
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Location',
theme: ThemeData(
primarySwatch: Colors.amber,
),
home: const MyHomePage(title: 'Flutter Location Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, this.title}) : super(key: key);
final String? title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final TextEditingController _controller = TextEditingController();
String? buttonText;
#override
void initState() {
_controller.addListener(_checkTextIsEmpty);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title!),
),
body: Center(
child: Column(
children: [
TextField(
controller: _controller,
onChanged: (value) {},
),
Text(buttonText ?? ''),
],
),
),
);
}
void _checkTextIsEmpty() {
final value = _controller.text.isEmpty ? "AC" : "C";
setState(() {
buttonText = value;
});
}
}

Creating model with contains list of widget flutter

hii i'm a newbie in flutter and now i'm creating screen model(screen_model.dart) like this
class ScreenModel{
final String title;
final Widget screen;
final List<Widget> actions;
ScreenModel({#required this.titleScreen, #required this.widgetScreen, this.actions});
}
then when i try to initialize model in main.dart
final List<Widget> defaultActions = [
IconButton(
icon: Icon(Icons.filter_list, color: Colors.white), onPressed: null),
IconButton(icon: Icon(Icons.add, color: Colors.white), onPressed: null)
];
final List<ScreenModel> _widgetOptions = [
ScreenModel(title: 'Purchasing', screen: PurchasingScreen(),actions: defaultactions)
];
i get an error "The instance member 'defaultActions' can't be accessed in an initializer.
Try replacing the reference to the instance member with a different expression"
how to fix this?
thanks in advance
You can copy paste run full code below
You can use init _widgetOptions in initState()
List<ScreenModel> _widgetOptions;
#override
void initState() {
_widgetOptions = [
ScreenModel(
title: 'Purchasing',
screen: PurchasingScreen(),
actions: defaultActions)
];
super.initState();
}
working demo
full code
import 'package:flutter/material.dart';
class ScreenModel {
final String title;
final Widget screen;
final List<Widget> actions;
ScreenModel({#required this.title, #required this.screen, this.actions});
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<Widget> defaultActions = [
IconButton(
icon: Icon(Icons.filter_list, color: Colors.blue), onPressed: null),
IconButton(icon: Icon(Icons.add, color: Colors.blue), onPressed: null)
];
List<ScreenModel> _widgetOptions;
#override
void initState() {
_widgetOptions = [
ScreenModel(
title: 'Purchasing',
screen: PurchasingScreen(),
actions: defaultActions)
];
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: _widgetOptions[0].actions,
),
),
);
}
}
class PurchasingScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container();
}
}

Flutter: Widget State: Is this code safe?

The code below is an example to illustrate this question. The code below works, however the following line:
class WidgetCustom extends StatefulWidget {
has "WidgetCustom" underlined in green in vsCode, and when the cursor is positioned over it, it shows the message:
"This class (or a class this class inherits from) is marked as #immutable, but one or more of its instance fields are not final".
The code works fine.
Is it safe to use this code?
Is there a way to achieve this without the warning?
import 'package:flutter/material.dart';
class WidgetCustom extends StatefulWidget {
_WidgetCustomState _state;
WidgetCustom({#required int iCount}) {
_state = _WidgetCustomState(iCount);
}
#override
State<StatefulWidget> createState() {
return _state;
}
int get getIcount => _state.iCount;
}
class _WidgetCustomState extends State<WidgetCustom> {
int iCount;
_WidgetCustomState(this.iCount);
#override
Widget build(BuildContext context) {
return Container(
child: Row(children: <Widget>[
Column(
children: <Widget>[
RaisedButton(
child: const Text("Please tap me"),
onPressed: () {
setState(() => iCount = iCount + 1);
}),
SizedBox(height: 40),
Text("Tapped $iCount Times")
],
),
]));
}
}
Edited to add main.dart
import 'package:flutter/material.dart';
import 'widgetCustom.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Custom Widget Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
WidgetCustom _widgetCustom;
String _sMessage = "Fab has not been pressed";
#override
void initState() {
super.initState();
_widgetCustom = WidgetCustom(iCount: 99);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(children: [
_widgetCustom,
SizedBox(height: 40),
Text(_sMessage),
]),
floatingActionButton: FloatingActionButton(
onPressed: _fabPressed,
tooltip: 'Get Value',
child: Icon(Icons.add),
),
);
}
_fabPressed() {
setState(() => _sMessage =
"Value from last button click = ${_widgetCustom.getIcount}");
}
}
Pass the initial value to the constructor when creating the widget as a final value, and then get it from the State class.
Updated code:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData.dark(),
home: MyHomePage(title: 'Custom Widget Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
WidgetCustom _widgetCustom;
String _sMessage = "Fab has not been pressed";
int _value = 99;
#override
void initState() {
super.initState();
_widgetCustom = WidgetCustom(iCount: _value, function: _update);
}
void _update(int value) {
setState(() {
_value = value;
_widgetCustom = WidgetCustom(iCount: _value, function: _update);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: Column(
children: [
_widgetCustom,
SizedBox(height: 40),
Text(_sMessage),
],
),
floatingActionButton: FloatingActionButton(
onPressed: _fabPressed,
tooltip: 'Get Value',
child: Icon(Icons.add),
),
);
}
_fabPressed() {
setState(() => _sMessage = "Value from last button click = ${_value}");
}
}
class WidgetCustom extends StatefulWidget {
final int iCount;
final Function function;
WidgetCustom({#required this.iCount, this.function});
#override
State<StatefulWidget> createState() {
return _WidgetCustomState();
}
}
class _WidgetCustomState extends State<WidgetCustom> {
int _iCount;
#override
void initState() {
super.initState();
_iCount = widget.iCount;
}
#override
Widget build(BuildContext context) {
return Container(
child: Row(
children: <Widget>[
Column(
children: <Widget>[
RaisedButton(child: const Text("Please tap me"), onPressed: (){
_iCount = _iCount + 1;
widget.function(_iCount);
}),
SizedBox(height: 40),
Text("Tapped $_iCount Times")
],
),
],
),
);
}
}