Issue
While send value from text field from different classes to App Bar, but what happens the button needs to be clicked (tapped) twice then the value only able to be sent to destination object (App Bar). Hope anyone can review and give me advice, your advice is appreciated.
Clicked outcomes as follow:
- 1st Clicked outcome is showing Empty and No Value.
- 2nd Clicked outcome is the wanted and expected value to be sent into destination object.
Screenshots as follow:
https://i.stack.imgur.com/2uUN3.png
https://i.stack.imgur.com/EiNvC.png
https://i.stack.imgur.com/soc7z.png
main.dart
import 'package:flutter/material.dart';
import 'custombutton.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'App Value is '),
);
}
}
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> {
final _textfield = TextEditingController();
String AppBarVar = 'UNKNOWN';
_callback(varAppBar){
setState(() {
AppBarVar = varAppBar;
});
}
@override
void dispose() {
_textfield.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title + AppBarVar),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Passing Value from TextField to App Bar',
),
TextField(
controller: _textfield,
keyboardType: TextInputType.text,
decoration: const InputDecoration(
hintText: 'Enter Values pass to Appbar'
),
),
CustomButton(AppBarVar: _textfield.text, callback: _callback)
],
),
),
);
}
}
customButton.dart
import 'package:flutter/material.dart';
class CustomButton extends StatefulWidget {
final String AppBarVar;
final Function callback;
const CustomButton({Key? key, required this.AppBarVar, required this.callback}) : super(key: key);
@override
State<CustomButton> createState() => _CustomButtonState();
}
class _CustomButtonState extends State<CustomButton> {
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: (){
setState(() {
widget.callback(widget.AppBarVar);
});
},
child: Text('Send to AppBar'),
);
}
}
Solution
Create callback function with wrapped setState at Home Page.
The Core Codes at Home Page as follows:
// CREATE callBack Function with wrapped setState.
// Always set callback function to passing value in good practice.
String appBarVar = 'UNKNOWN';
_callback(varAppBar){
setState(() {
appBarVar = varAppBar;
});
}
// Usage of callBack from other class and Usage of setState.
CustomButton(appBarVar: _textfield.text, callbackFunction: _callback),
CustomButton(appBarVar: 'Hello', callbackFunction: _callback),
Full Codes of 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> {
final _textfield = TextEditingController();
// Always set initState() for the value instantly to be sent and fired at one time.
//
// Text Field in callback is unable to fire the value at one time in completed
// to the destination target object. Issue is It needs to be fired twice to
// send the value.
// So we need to set initState with addListener() for the solution as below:
void _printValue(){ // To see examine the input codes whether correct or not.
print('Controller Output: $_textfield');
}
@override
void initState(){
_textfield.addListener(() {
setState(() {
_printValue(); // Can be removed, This is Unnecessary code.
});
});
super.initState();
}
// CREATE callBack Function with wrapped setState.
// Always set callback function to passing value in good practice.
String appBarVar = 'UNKNOWN';
_callback(varAppBar){
setState(() {
appBarVar = varAppBar;
});
}
@override
void dispose() {
_textfield.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title + appBarVar),
),
body: Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Passing Value from TextField to App Bar',
),
TextField(
controller: _textfield,
keyboardType: TextInputType.text, // Always specific the keyboard type, this is good practising on IOS.
decoration: const InputDecoration(
hintText: 'Enter Values pass to Appbar'
),
),
// Usage of callBack from other class and Usage of setState.
CustomButton(appBarVar: _textfield.text, callbackFunction: _callback),
CustomButton(appBarVar: 'Hello', callbackFunction: _callback),
],
),
),
),
);
}
}
Create callback constructor at custombutton.dart (Reusable Widget Page).
The Core Codes at Reusable Widget Page as follows:
// Create Constructor of callback to execute setState.
final String? appBarVar;
final Function callbackFunction;
const CustomButton({Key? key, required this.appBarVar, required this.callbackFunction}) : super(key: key);
// Execute SetState Codes here by onPressed:(){}
onPressed: (){
// Execute SetState Codes here from MyHomePage
callbackFunction(appBarVar);
},
Full Codes of Reusable Widget Page.
import 'package:flutter/material.dart';
class CustomButton extends StatelessWidget {
// Create Constructor of callback to execute setState.
final String? appBarVar;
final Function callbackFunction;
const CustomButton({Key? key, required this.appBarVar, required this.callbackFunction}) : super(key: key);
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: (){
// Execute SetState Codes here from MyHomePage
callbackFunction(appBarVar);
},
child: const Text('Send to App Bar'),
style: ElevatedButton.styleFrom(
primary: Colors.purple,
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
textStyle: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)
),
);
}
}
Answered By - ISOs
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.