Even though I implemented backbutton App close. If you press the backbutton, no message appears and you are returned to the login screen.
The homepage is running in the homescreen.
In order to find any possible errors, I put the backbutton close code in both places.
I am not sure what is wrong.
I need help.
HomeScreen
class HomeScreen extends StatelessWidget {
DateTime currentBackPressTime;
final scaffoldKey = GlobalKey<ScaffoldState>();
final FirebaseUser user;
HomeScreen({this.user});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Custom Navigation Drawer Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: WillPopScope(
onWillPop: () async {
bool result = onPressBackButton();
return await Future.value(result);
},
child: MyHomePage(),
),
);
}
bool onPressBackButton() {
DateTime now = DateTime.now();
if (currentBackPressTime == null ||
now.difference(currentBackPressTime) > Duration(seconds: 2)) {
currentBackPressTime = now;
scaffoldKey.currentState
..hideCurrentSnackBar()
..showSnackBar(SnackBar(
content: Text("Tap back again to leave."),
));
return false;
}
return true;
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
scaffoldBackgroundColor: Colors.white,
primaryColor: Colors.white
),
home: SideBarLayout(),
);
}
}
HomeScreen
import 'package:flutter/material.dart';
import 'package:aciel_pro/navigation_bloc/navigation_bloc.dart';
class Home extends StatelessWidget {
DateTime currentBackPressTime;
final scaffoldKey = GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Custom Navigation Drawer Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: WillPopScope(
onWillPop: () async {
bool result = onPressBackButton();
return await Future.value(result);
},
child: HomePage(),
),
);
}
bool onPressBackButton() {
DateTime now = DateTime.now();
if (currentBackPressTime == null ||
now.difference(currentBackPressTime) > Duration(seconds: 2)) {
currentBackPressTime = now;
scaffoldKey.currentState
..hideCurrentSnackBar()
..showSnackBar(SnackBar(
content: Text("Tap back again to leave."),
));
return false;
}
return true;
}
}
class HomePage extends StatelessWidget with NavigationStates {
BuildContext ctx;
#override
Widget build(BuildContext context) {
ctx = context;
return Scaffold(
body: Center(
child: Column(
children: <Widget>[
FlatButton(
child: Text('예약하기',style: TextStyle(fontSize: 40)),
onPressed: () =>showMessage('예약하기'),
color:Colors.green,
textColor: Colors.white,
)
],
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
),
),
);
}
void showMessage(String msg) {
final snackbar = SnackBar(content: Text(msg));
Scaffold.of(ctx)
..removeCurrentSnackBar()
..showSnackBar(snackbar);
}
}
You can copy paste run full code below
Step 1 : move final scaffoldKey = GlobalKey<ScaffoldState>(); out of Home
Step 2 : add Scaffold key
return Scaffold(
key: scaffoldKey,
Step 3: showMessage() use scaffoldKey
scaffoldKey.currentState
..removeCurrentSnackBar()
..showSnackBar(snackbar);
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp(Home());
}
final scaffoldKey = GlobalKey<ScaffoldState>();
class Home extends StatelessWidget {
DateTime currentBackPressTime;
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Custom Navigation Drawer Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: WillPopScope(
onWillPop: () async {
bool result = onPressBackButton();
return await Future.value(result);
},
child: HomePage(),
),
);
}
bool onPressBackButton() {
DateTime now = DateTime.now();
if (currentBackPressTime == null ||
now.difference(currentBackPressTime) > Duration(seconds: 2)) {
currentBackPressTime = now;
scaffoldKey.currentState
..hideCurrentSnackBar()
..showSnackBar(SnackBar(
content: Text("Tap back again to leave."),
));
return false;
}
return true;
}
}
class HomePage extends StatelessWidget {
BuildContext ctx;
#override
Widget build(BuildContext context) {
ctx = context;
return Scaffold(
key: scaffoldKey,
body: Center(
child: Column(
children: <Widget>[
FlatButton(
child: Text('예약하기', style: TextStyle(fontSize: 40)),
onPressed: () => showMessage('예약하기'),
color: Colors.green,
textColor: Colors.white,
)
],
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
),
),
);
}
void showMessage(String msg) {
final snackbar = SnackBar(content: Text(msg));
scaffoldKey.currentState
..removeCurrentSnackBar()
..showSnackBar(snackbar);
}
}
Related
In my flutter project I made a floating button that help to auto scroll to the top of the page with one click, and when it reach the top it disappear. It work perfectly. But my problem is that I need to double click in it so it can disappear I want it to automatically disappear if it reach the top. Any help is highly appreciated.
void scrollToTop(){
_controller.runJavascript("window.scrollTo({top: 0, behavior: 'smooth'});");
floatingButtonVisibility();
}
void floatingButtonVisibility() async {
int y = await _controller.getScrollY();
if(y>50){
setState(() {
buttonshow = true;
});
}else {
setState(() {
buttonshow = false;
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter WebView'),
),
body: WebView(
initialUrl: 'https://flutter.dev',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller = webViewController;
},
gestureRecognizers: Set()
..add(
Factory<VerticalDragGestureRecognizer>(() => VerticalDragGestureRecognizer()
..onDown = (tap) {
floatingButtonVisibility();
}))
),
floatingActionButton: Visibility(
visible: buttonshow,
child: FloatingActionButton(
onPressed: () {
scrollToTop();
},
backgroundColor: Colors.blue,
child: const Icon(Icons.navigation),
),
),
);
}
}
Here is my solution.
Register 'window.onscroll' in to send webview's scroll position to outside of Webview widget.
Register receiver to receive event from webview.
If scroll is 0, change 'buttonshow' value and rebuild widget.
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
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> {
WebViewController _controller;
bool buttonshow = false;
#override
void initState() {
super.initState();
}
void scrollToTop() {
_controller.evaluateJavascript(
"window.onscroll = function () {scrollEventChannel.postMessage(window.scrollY)};");
_controller
.evaluateJavascript("window.scrollTo({top: 0, behavior: 'smooth'});");
floatingButtonVisibility();
}
void floatingButtonVisibility() async {
int y = await _controller.getScrollY();
if (y > 50) {
setState(() {
buttonshow = true;
});
} else {
setState(() {
buttonshow = false;
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter WebView'),
),
body: WebView(
initialUrl: 'https://flutter.dev',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller = webViewController;
},
javascriptChannels: {
JavascriptChannel(
name: 'scrollEventChannel',
onMessageReceived: (JavascriptMessage message) {
print('>>>>: ${message.message}');
if (message.message == '0') {
setState(() {
buttonshow = false;
});
}
}),
},
gestureRecognizers: Set()
..add(Factory<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer()
..onDown = (tap) {
floatingButtonVisibility();
}))),
floatingActionButton: Visibility(
visible: buttonshow,
child: FloatingActionButton(
onPressed: () {
scrollToTop();
},
backgroundColor: Colors.blue,
child: const Icon(Icons.navigation),
),
),
);
}
}
I changed button show trigger from gestureRecognizers to postion event.
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
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> {
WebViewController _controller;
bool buttonshow = false;
#override
void initState() {
super.initState();
}
void scrollToTop() {
_controller
.evaluateJavascript("window.scrollTo({top: 0, behavior: 'smooth'});");
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter WebView'),
),
body: WebView(
initialUrl: 'https://flutter.dev',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller = webViewController;
},
onPageFinished: (String url) async {
_controller.evaluateJavascript(
"window.onscroll = function () {scrollEventChannel.postMessage(window.scrollY)};");
},
javascriptChannels: {
JavascriptChannel(
name: 'scrollEventChannel',
onMessageReceived: (JavascriptMessage message) {
print('>>>>: ${message.message}');
int position = int.parse(message.message);
if (position == 0) {
setState(() {
buttonshow = false;
});
} else if (position > 60) {
setState(() {
buttonshow = true;
});
}
}),
},
),
floatingActionButton: Visibility(
visible: buttonshow,
child: FloatingActionButton(
onPressed: () {
scrollToTop();
},
backgroundColor: Colors.blue,
child: const Icon(Icons.navigation),
),
),
);
}
}
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget{
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Home()
);
}
}
class Home extends StatefulWidget {
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
ScrollController scrollController = ScrollController();
bool showbtn = false;
List<String> countries = ["USA", "United Kingdom", "China", "Russia", "Brazil",
"India", "Pakistan", "Nepal", "Bangladesh", "Sri Lanka",
"Japan", "South Korea", "Mongolia"];
#override
void initState() {
scrollController.addListener(() { //scroll listener
double showoffset = 10.0; //Back to top botton will show on scroll offset 10.0
if(scrollController.offset > showoffset){
showbtn = true;
setState(() {
//update state
});
}else{
showbtn = false;
setState(() {
//update state
});
}
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Scroll Back to Top Button"),
backgroundColor: Colors.redAccent
),
floatingActionButton: AnimatedOpacity(
duration: Duration(milliseconds: 1000), //show/hide animation
opacity: showbtn?1.0:0.0, //set obacity to 1 on visible, or hide
child: FloatingActionButton(
onPressed: () {
scrollController.animateTo( //go to top of scroll
0, //scroll offset to go
duration: Duration(milliseconds: 500), //duration of scroll
curve:Curves.fastOutSlowIn //scroll type
);
},
child: Icon(Icons.arrow_upward),
backgroundColor: Colors.redAccent,
),
),
body: SingleChildScrollView(
controller: scrollController, //set controller
child:Container(
child:Column(
children: countries.map((country){
return Card(
child:ListTile(
title: Text(country)
)
);
}).toList(),
)
)
)
);
}
So I have this code and I take an image from Internet with webscrapper, the problem is that when I try to take the image with the basic URl without the http:// behind it don't work and when I add it I don't have any error but I got a black screen on my emulator and I can't see this value of the image on my terminal even if I know the value is not null.
If someone can help I will be very greatful thank you very much !
class ContentScreen extends StatefulWidget {
const ContentScreen({Key? key}) : super(key: key);
#override
_ContentScreenState createState() => _ContentScreenState();
}
class _ContentScreenState extends State<ContentScreen> {
List<Map<String,dynamic>>? contentPages;
bool Data = false;
Future<void> getcontent() async{
final webscraper = WebScraper("https://manhuas.net/");
String TempRoute = "manhua/what-harm-would-my-girl-do-manhua/what-harm-would-my-girl-do-chapter-1/";
if (await webscraper.loadWebPage(TempRoute)){
contentPages = webscraper.getElement("div.page-break.no-gaps > img ", ["data-src"]);
setState(() {
Data = true;
});
print(contentPages);
}
}
#override
void initState() {
// TODO: implement initState
super.initState();
getcontent();
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getcontent(),
builder: (context, snapshot) {
return Scaffold(
body: Data? Container(
child: ListView.builder(
shrinkWrap: true,
itemCount: contentPages!.length,
itemBuilder: (context,index ) {
return Image.network(contentPages![index]['attributes']['src'].toString().trim(),
fit: BoxFit.fitWidth,loadingBuilder: (context , child, loadingprogress){
if (loadingprogress != null) return child;
return Center(
child: CircularProgressIndicator(),
);
},);
},
)
)
: Center(
child: CircularProgressIndicator(
color: Constants.mygreen,
)
));
}
);
}
}
And this is a screen of my screen for more details:
Please check the below code it's working perfectly
import 'package:flutter/material.dart';
import 'package:web_scraper/web_scraper.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'OverlayEntry Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: ContentScreen(),
);
}
}
class ContentScreen extends StatefulWidget {
const ContentScreen({Key? key}) : super(key: key);
#override
_ContentScreenState createState() => _ContentScreenState();
}
class _ContentScreenState extends State<ContentScreen> {
List<Map<String, dynamic>>? contentPages;
bool Data = false;
Future<void> getcontent() async {
final webscraper = WebScraper("https://manhuas.net/");
String TempRoute =
"manhua/what-harm-would-my-girl-do-manhua/what-harm-would-my-girl-do-chapter-1/";
if (await webscraper.loadWebPage(TempRoute)) {
contentPages =
webscraper.getElement("div.page-break.no-gaps > img ", ["data-src"]);
setState(() {
Data = true;
});
print(contentPages);
}
}
#override
void initState() {
// TODO: implement initState
super.initState();
getcontent();
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getcontent(),
builder: (context, snapshot) {
return Scaffold(
body: Data
? Container(
child: ListView.builder(
shrinkWrap: true,
itemCount: contentPages!.length,
itemBuilder: (context, index) {
return Image.network(
contentPages![index]['attributes']
['data-src']
.toString()
.trim(),
fit: BoxFit.fitWidth,
);
},
))
: Center(
child: CircularProgressIndicator(
color: Colors.green,
)));
});
}
}
In my program I put the add button to create stateful box with stateful drop down button inside of it, each time I add the box I add it to Map<int, Widget> and pass it to the column. When I click on the cross button it delete the widget from the map in parent. But when I click on cross button on the widget, it show wrong colour of the box and wrong drop down value.Watch the GIF I posted to get the overview of the problem
Link to dart pad to run the example : dart pad code link here
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {
#override
_StateMyWidget createState() => _StateMyWidget();
}
class _StateMyWidget extends State<MyWidget> {
Map<int, Widget> widgetList = {};
int boxCount = 0;
#override
initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return ListView(children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: widgetList.values.toList()),
TextButton(
onPressed: () {
widgetList[boxCount] =
new MyBox(boxIndex: boxCount, deleteFunction: deleteBox);
setState(() {});
boxCount += 1;
},
child: Text("Add"))
],
)
]);
}
deleteBox(boxIndex) {
widgetList.remove(boxIndex);
setState(() {});
}
}
class MyBox extends StatefulWidget {
final int boxIndex;
final Function deleteFunction;
MyBox({required this.boxIndex, required this.deleteFunction});
_StateMyBox createState() => _StateMyBox();
}
class _StateMyBox extends State<MyBox> {
var containerColor;
#override
initState() {
super.initState();
containerColor =
Colors.primaries[Random().nextInt(Colors.primaries.length)];
}
#override
Widget build(BuildContext context) {
return Container(
width: 200,
height: 200,
margin: EdgeInsets.all(17),
padding: EdgeInsets.all(10),
color: containerColor,
child: Column(children: [
Row(children: [
Text("Box Number: ${widget.boxIndex}"),
Spacer(),
IconButton(
icon: const Icon(Icons.clear),
onPressed: () {
widget.deleteFunction(widget.boxIndex);
},
),
]),
RegistrationDropdown(listData: ['One', 'Two', 'Three', 'Four']),
]));
}
}
class RegistrationDropdown extends StatefulWidget {
final List<String> listData;
RegistrationDropdown({
required this.listData,
});
#override
_StateRegistrationDropdown createState() {
return _StateRegistrationDropdown();
}
}
class _StateRegistrationDropdown extends State<RegistrationDropdown> {
String dropdownValue = 'One';
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
padding: EdgeInsets.only(left: 10, right: 10),
child: DropdownButton<String>(
isExpanded: true,
underline: SizedBox(),
value: dropdownValue,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
onChanged: (String? newValue) {
print("Previous dropdown value $dropdownValue");
print("New value $newValue");
setState(() {
dropdownValue = newValue!;
});
},
items: widget.listData.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
));
}
}
The solution is a Key of the widget. The When to Use Keys: Flutter Youtube will be helpful.
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {
#override
_StateMyWidget createState() => _StateMyWidget();
}
class _StateMyWidget extends State<MyWidget> {
Map<int, Widget> widgetList = {};
int boxCount = 0;
#override
initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return ListView(
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: widgetList.values.toList(),
),
TextButton(
onPressed: () {
widgetList[boxCount] = new MyBox(
key: UniqueKey(), // <---------------------
boxIndex: boxCount,
deleteFunction: deleteBox,
);
setState(() {});
boxCount += 1;
},
child: Text("Add"),
)
],
)
],
);
}
deleteBox(boxIndex) {
widgetList.remove(boxIndex);
setState(() {});
}
}
class MyBox extends StatefulWidget {
final int boxIndex;
final Function deleteFunction;
MyBox({
Key? key, // <---------------------
required this.boxIndex,
required this.deleteFunction,
}) : super(key: key); // <---------------------
_StateMyBox createState() => _StateMyBox();
}
class _StateMyBox extends State<MyBox> {
var containerColor;
#override
initState() {
super.initState();
containerColor =
Colors.primaries[Random().nextInt(Colors.primaries.length)];
}
#override
Widget build(BuildContext context) {
return Container(
width: 200,
height: 200,
margin: EdgeInsets.all(17),
padding: EdgeInsets.all(10),
color: containerColor,
child: Column(children: [
Row(children: [
Text("Box Number: ${widget.boxIndex}"),
Spacer(),
IconButton(
icon: const Icon(Icons.clear),
onPressed: () {
widget.deleteFunction(widget.boxIndex);
},
),
]),
RegistrationDropdown(listData: ['One', 'Two', 'Three', 'Four']),
]));
}
}
class RegistrationDropdown extends StatefulWidget {
final List<String> listData;
RegistrationDropdown({
required this.listData,
});
#override
_StateRegistrationDropdown createState() {
return _StateRegistrationDropdown();
}
}
class _StateRegistrationDropdown extends State<RegistrationDropdown> {
String dropdownValue = 'One';
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
padding: EdgeInsets.only(left: 10, right: 10),
child: DropdownButton<String>(
isExpanded: true,
underline: SizedBox(),
value: dropdownValue,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
onChanged: (String? newValue) {
print("Previous dropdown value $dropdownValue");
print("New value $newValue");
setState(() {
dropdownValue = newValue!;
});
},
items: widget.listData.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
);
}
}
Using this code brings me this warning when I run :
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xffebebeb),
body: AnimatedCrossFade(
firstChild: SplashScreen1(),
secondChild: SplashScreen2(),
crossFadeState:
!phaseTwo ? CrossFadeState.showFirst : CrossFadeState.showSecond,
duration: Duration(seconds: 1),
)
);
}
SplashScreen1()
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xffebebeb),
);
}
SplashScreen2()
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xffebebeb),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Image.asset('assets/images/splash_image_1.png'),
],
),
);
}
You can copy paste run full code below
You can replace Scaffold of SplashScreen1 and SplashScreen2 with Container
code snippet
class SplashScreen1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: const Color(0xffebebeb),
);
}
}
working demo
full code
import 'package:flutter/material.dart';
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> {
bool phaseTwo = false;
#override
void initState() {
super.initState();
Future.delayed(const Duration(seconds: 3), () {
setState(() {
phaseTwo = true;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xffebebeb),
body: AnimatedCrossFade(
firstChild: SplashScreen1(),
secondChild: SplashScreen2(),
crossFadeState:
!phaseTwo ? CrossFadeState.showFirst : CrossFadeState.showSecond,
duration: Duration(seconds: 1),
));
}
}
class SplashScreen1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: const Color(0xffebebeb),
);
}
}
class SplashScreen2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: const Color(0xffebebeb),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Image.network('https://picsum.photos/250?image=9'),
],
),
);
}
}
I have this event form, it's to create or edit events data. The save button is inside the app bar action, and the form is inside the body. In this project, I have all of the widgets in different files. How do I run the save function inside EventFormForm.dart when I tap the save button inside EventFromAppBar.dart?
This is the structure :
These are my codes :
EventForm.dart
class EventForm extends StatelessWidget {
// Some Code
// Some Const
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: EventFormAppBar(
// Some Params
),
body: EventFormBody(
// Some Params
)
);
}
}
EventFormAppBar.dart
class EventFormAppBar extends PreferredSize{
// Some Code
// Some Const
// Some Code
#override
Widget build(BuildContext context) {
return AppBar(
// Some Code
actions: <Widget>[
IconButton(
icon: Icon(Icons.save),
onPressed: () {
}
)
]
);
}
}
EventFormBody.dart
class EventFormBody extends StatelessWidget {
// Some Code
// Some Const
#override
Widget build(BuildContext context) {
return SafeArea(
child: SingleChildScrollView(
child: EventFormForm(
// Some Params
),
),
);
}
}
EventFormForm.dart
class EventFormForm extends StatefulWidget {
// Some Code
// Some Const
#override
EventFormFormState createState() => EventFormFormState();
}
class EventFormFormState extends State<EventFormForm> {
//
//
// Some Code
//
//
#override
Widget build(BuildContext context) {
return Form(
//
// Some Code
//
);
}
saveForm() {
//
// Some Code
//
}
}
Tag #chunhunghan
You can copy paste run each files below
Step 1: Use final keyForm = GlobalKey<EventFormFormState>();
Step 2: Pass keyForm to EventFormForm(key: keyForm)
Step 3: In IconButton call keyForm.currentState.saveForm();
IconButton(
icon: Icon(Icons.save),
onPressed: () {
keyForm.currentState.saveForm();
})
working demo
full code
main.dart
import 'package:flutter/material.dart';
import 'event_form.dart';
import 'event_form_form.dart';
void main() => runApp(MyApp());
final keyForm = GlobalKey<EventFormFormState>();
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: EventForm(),
);
}
}
event_form.dart
import 'package:flutter/material.dart';
import 'event_form_appbar.dart';
import 'event_form_body.dart';
class EventForm extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(appBar: EventFormAppBar(), body: EventFormBody());
}
}
event_form_appbar.dart
import 'package:flutter/material.dart';
import 'main.dart';
class EventFormAppBar extends PreferredSize {
#override
Widget build(BuildContext context) {
return AppBar(actions: <Widget>[
IconButton(
icon: Icon(Icons.save),
onPressed: () {
keyForm.currentState.saveForm();
})
]);
}
#override
get preferredSize => Size.fromHeight(50);
}
event_form_body.dart
import 'package:flutter/material.dart';
import 'main.dart';
import 'event_form_form.dart';
class EventFormBody extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SafeArea(
child: SingleChildScrollView(
child: EventFormForm(key: keyForm),
),
);
}
}
event_form_form.dart
import 'package:flutter/material.dart';
class EventFormForm extends StatefulWidget {
EventFormForm({Key key}) : super(key: key);
#override
EventFormFormState createState() {
return EventFormFormState();
}
}
class EventFormFormState extends State<EventFormForm> {
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextFormField(
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: RaisedButton(
onPressed: () {
saveForm();
},
child: Text('Submit'),
),
),
],
),
);
}
void saveForm() {
print("execute save Form");
if (_formKey.currentState.validate()) {
// If the form is valid, display a Snackbar.
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text('Processing Data')));
}
}
}