I want to pass data from alert dialog.Alert dialog contains textfield,so whatever the user type on the textfield that text should pass to the main page (screen).Below is the code of the alert dialog
Padding(
padding: const EdgeInsets.only(left: 42.0),
child: Align(
alignment: Alignment.topCenter,
child: RaisedButton(onPressed: (){
_showDialog();
},
),
),
Padding(
padding: const EdgeInsets.only(top: 50.0),
child: new Text('// Displays text'););
void _showDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
// return object of type Dialog
return AlertDialog(
title: new Text("Alert Dialog title"),
content: TextField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: 'Enter the number'
),
)
,
actions: <Widget>[
// usually buttons at the bottom of the dialog
Row(
children: <Widget>[
new FlatButton(
child: new Text("Cancel"),
onPressed: () {
Navigator.of(context).pop();
},
),
new FlatButton(onPressed: (){
}, child: new Text("OK"))
],
),
],
);
},
);
}
Edit new solution:
// write this in your main page
String onMainPageText;
you can display like this in on your main page! after clicking the okey in your _showdialog method Text(onMainPageText)
change your _showDialog method with the following code.
void _showDialog() {
String dialogText;
showDialog(
context: context,
builder: (BuildContext context) {
// return object of type Dialog
return AlertDialog(
title: new Text("Alert Dialog title"),
content: TextField(
onChanged: (String textTyped) {
setState(() {
dialogText = textTyped;
});
},
keyboardType: TextInputType.number,
decoration: InputDecoration(hintText: 'Enter the number'),
),
actions: <Widget>[
// usually buttons at the bottom of the dialog
Row(
children: <Widget>[
new FlatButton(
child: new Text("Cancel"),
onPressed: () {
setState(() {
onMainPageText = '';
});
Navigator.of(context).pop();
},
),
new FlatButton(
onPressed: () {
setState(() {
onMainPageText = dialogText;
});
Navigator.of(context).pop();
},
child: new Text("OK"))
],
),
],
);
},
);
}
Old answer:
create a global TextEditingController will handle your problem you can access the text field text with textEditingConroller.text
dont forget to define textEditingController inside your class
class YourMainPageState extends State<YourMainPage>{
TextEditingController textEditingController = new TextEditingController();
}
void _showDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
// return object of type Dialog
return AlertDialog(
title: new Text("Alert Dialog title"),
content: TextField(
controller: textEditingController,
keyboardType: TextInputType.number,
decoration: InputDecoration(hintText: 'Enter the number'),
),
actions: <Widget>[
// usually buttons at the bottom of the dialog
Row(
children: <Widget>[
new FlatButton(
child: new Text("Cancel"),
onPressed: () {
Navigator.of(context).pop();
},
),
new FlatButton(onPressed: () {print(textEditingController.text);}, child: new Text("OK"))
],
),
],
);
},
);
}
You can display typed text with that code :
Padding(
padding: const EdgeInsets.only(top: 50.0),
child: new Text(texEditingController.text););
The textfield has a parameter called onChanged: you can use that to pass a function
TextField(
keyboardType: TextInputType.number,
onChange: onChange
decoration: InputDecoration(
hintText: 'Enter the number'
),
)
in your main screen use this:
void onChange(String text) {
//do stuff here with text like maybe setState
}
I am learning to build apps in Flutter. Now I have come to alert dialogs. I have done them before in Android and iOS, but how do I make an alert in Flutter?
Here are some related SO questions:
How to style AlertDialog Actions in Flutter
adding dropdown menu in alert dialog box in flutter
Show alert dialog on app main screen load automatically
how to refresh alertdialog in flutter
Alert Dialog with Rounded corners in flutter
I'd like to make a more general canonical Q&A so my answer is below.
One Button
showAlertDialog(BuildContext context) {
// set up the button
Widget okButton = TextButton(
child: Text("OK"),
onPressed: () { },
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
title: Text("My title"),
content: Text("This is my message."),
actions: [
okButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
Two Buttons
showAlertDialog(BuildContext context) {
// set up the buttons
Widget cancelButton = TextButton(
child: Text("Cancel"),
onPressed: () {},
);
Widget continueButton = TextButton(
child: Text("Continue"),
onPressed: () {},
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
title: Text("AlertDialog"),
content: Text("Would you like to continue learning how to use Flutter alerts?"),
actions: [
cancelButton,
continueButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
Three Buttons
showAlertDialog(BuildContext context) {
// set up the buttons
Widget remindButton = TextButton(
child: Text("Remind me later"),
onPressed: () {},
);
Widget cancelButton = TextButton(
child: Text("Cancel"),
onPressed: () {},
);
Widget launchButton = TextButton(
child: Text("Launch missile"),
onPressed: () {},
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
title: Text("Notice"),
content: Text("Launching this missile will destroy the entire universe. Is this what you intended to do?"),
actions: [
remindButton,
cancelButton,
launchButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
Handling button presses
The onPressed callback for the buttons in the examples above were empty, but you could add something like this:
Widget launchButton = TextButton(
child: Text("Launch missile"),
onPressed: () {
Navigator.of(context).pop(); // dismiss dialog
launchMissile();
},
);
If you make the callback null, then the button will be disabled.
onPressed: null,
Supplemental code
Here is the code for main.dart in case you weren't getting the functions above to run.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Flutter'),
),
body: MyLayout()),
);
}
}
class MyLayout extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
child: Text('Show alert'),
onPressed: () {
showAlertDialog(context);
},
),
);
}
}
// replace this function with the examples above
showAlertDialog(BuildContext context) { ... }
I used similar approach, but I wanted to
Keep the Dialog code as a widget in a separated file so I can reuse it.
Blurr the background when the dialog is shown.
Code:
1. alertDialog_widget.dart
import 'dart:ui';
import 'package:flutter/material.dart';
class BlurryDialog extends StatelessWidget {
String title;
String content;
VoidCallback continueCallBack;
BlurryDialog(this.title, this.content, this.continueCallBack);
TextStyle textStyle = TextStyle (color: Colors.black);
#override
Widget build(BuildContext context) {
return BackdropFilter(
filter: ImageFilter.blur(sigmaX: 6, sigmaY: 6),
child: AlertDialog(
title: new Text(title,style: textStyle,),
content: new Text(content, style: textStyle,),
actions: <Widget>[
new FlatButton(
child: new Text("Continue"),
onPressed: () {
continueCallBack();
},
),
new FlatButton(
child: Text("Cancel"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
));
}
}
You can call this in main (or wherever you want) by creating a new method like:
_showDialog(BuildContext context)
{
VoidCallback continueCallBack = () => {
Navigator.of(context).pop(),
// code on continue comes here
};
BlurryDialog alert = BlurryDialog("Abort","Are you sure you want to abort this operation?",continueCallBack);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
You can use this code snippet for creating a two buttoned Alert box,
import 'package:flutter/material.dart';
class BaseAlertDialog extends StatelessWidget {
//When creating please recheck 'context' if there is an error!
Color _color = Color.fromARGB(220, 117, 218 ,255);
String _title;
String _content;
String _yes;
String _no;
Function _yesOnPressed;
Function _noOnPressed;
BaseAlertDialog({String title, String content, Function yesOnPressed, Function noOnPressed, String yes = "Yes", String no = "No"}){
this._title = title;
this._content = content;
this._yesOnPressed = yesOnPressed;
this._noOnPressed = noOnPressed;
this._yes = yes;
this._no = no;
}
#override
Widget build(BuildContext context) {
return AlertDialog(
title: new Text(this._title),
content: new Text(this._content),
backgroundColor: this._color,
shape:
RoundedRectangleBorder(borderRadius: new BorderRadius.circular(15)),
actions: <Widget>[
new FlatButton(
child: new Text(this._yes),
textColor: Colors.greenAccent,
onPressed: () {
this._yesOnPressed();
},
),
new FlatButton(
child: Text(this._no),
textColor: Colors.redAccent,
onPressed: () {
this._noOnPressed();
},
),
],
);
}
}
To show the dialog you can have a method that calls it NB after importing BaseAlertDialog class
_confirmRegister() {
var baseDialog = BaseAlertDialog(
title: "Confirm Registration",
content: "I Agree that the information provided is correct",
yesOnPressed: () {},
noOnPressed: () {},
yes: "Agree",
no: "Cancel");
showDialog(context: context, builder: (BuildContext context) => baseDialog);
}
OUTPUT WILL BE LIKE THIS
Here is a shorter, but complete code.
If you need a dialog with only one button:
await showDialog(
context: context,
builder: (context) => new AlertDialog(
title: new Text('Message'),
content: Text(
'Your file is saved.'),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.of(context, rootNavigator: true)
.pop(); // dismisses only the dialog and returns nothing
},
child: new Text('OK'),
),
],
),
);
If you need a dialog with Yes/No buttons:
onPressed: () async {
bool result = await showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Confirmation'),
content: Text('Do you want to save?'),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.of(context, rootNavigator: true)
.pop(false); // dismisses only the dialog and returns false
},
child: Text('No'),
),
FlatButton(
onPressed: () {
Navigator.of(context, rootNavigator: true)
.pop(true); // dismisses only the dialog and returns true
},
child: Text('Yes'),
),
],
);
},
);
if (result) {
if (missingvalue) {
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text('Missing Value'),
));
} else {
saveObject();
Navigator.of(context).pop(_myObject); // dismisses the entire widget
}
} else {
Navigator.of(context).pop(_myObject); // dismisses the entire widget
}
}
Simply used this custom dialog class which field you not needed to leave it or make it null so this customization you got easily.
import 'package:flutter/material.dart';
class CustomAlertDialog extends StatelessWidget {
final Color bgColor;
final String title;
final String message;
final String positiveBtnText;
final String negativeBtnText;
final Function onPostivePressed;
final Function onNegativePressed;
final double circularBorderRadius;
CustomAlertDialog({
this.title,
this.message,
this.circularBorderRadius = 15.0,
this.bgColor = Colors.white,
this.positiveBtnText,
this.negativeBtnText,
this.onPostivePressed,
this.onNegativePressed,
}) : assert(bgColor != null),
assert(circularBorderRadius != null);
#override
Widget build(BuildContext context) {
return AlertDialog(
title: title != null ? Text(title) : null,
content: message != null ? Text(message) : null,
backgroundColor: bgColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(circularBorderRadius)),
actions: <Widget>[
negativeBtnText != null
? FlatButton(
child: Text(negativeBtnText),
textColor: Theme.of(context).accentColor,
onPressed: () {
Navigator.of(context).pop();
if (onNegativePressed != null) {
onNegativePressed();
}
},
)
: null,
positiveBtnText != null
? FlatButton(
child: Text(positiveBtnText),
textColor: Theme.of(context).accentColor,
onPressed: () {
if (onPostivePressed != null) {
onPostivePressed();
}
},
)
: null,
],
);
}
}
Usage:
var dialog = CustomAlertDialog(
title: "Logout",
message: "Are you sure, do you want to logout?",
onPostivePressed: () {},
positiveBtnText: 'Yes',
negativeBtnText: 'No');
showDialog(
context: context,
builder: (BuildContext context) => dialog);
Output:
Or you can use RFlutter Alert library for that. It is easily customizable and easy-to-use. Its default style includes rounded corners and you can add buttons as much as you want.
Basic Alert:
Alert(context: context, title: "RFLUTTER", desc: "Flutter is awesome.").show();
Alert with Button:
Alert(
context: context,
type: AlertType.error,
title: "RFLUTTER ALERT",
desc: "Flutter is more awesome with RFlutter Alert.",
buttons: [
DialogButton(
child: Text(
"COOL",
style: TextStyle(color: Colors.white, fontSize: 20),
),
onPressed: () => Navigator.pop(context),
width: 120,
)
],
).show();
You can also define generic alert styles.
*I'm one of developer of RFlutter Alert.
Minumum code for alert dialog
showDialog(
context: context,
builder: (_) => AlertDialog(
title: Text('Title'),
content: Text(
'Content widget',
),
),
);
If you want beautiful and responsive alert dialog then you can use flutter packages like
rflutter alert ,fancy dialog,rich alert,sweet alert dialogs,easy dialog & easy alert
These alerts are good looking and responsive. Among them rflutter alert is the best. currently I am using rflutter alert for my apps.
showAlertDialog(BuildContext context, String message, String heading,
String buttonAcceptTitle, String buttonCancelTitle) {
// set up the buttons
Widget cancelButton = FlatButton(
child: Text(buttonCancelTitle),
onPressed: () {},
);
Widget continueButton = FlatButton(
child: Text(buttonAcceptTitle),
onPressed: () {
},
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
title: Text(heading),
content: Text(message),
actions: [
cancelButton,
continueButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
called like:
showAlertDialog(context, 'Are you sure you want to delete?', "AppName" , "Ok", "Cancel");
Check out Flutter Dropdown Banner to easily alert users of events and prompt action without having to manage the complexity of presenting, delaying, and dismissing the component.
To set it up:
import 'packages:dropdown_banner/dropdown_banner.dart';
...
class MainApp extends StatelessWidget {
...
#override
Widget build(BuildContext context) {
final navigatorKey = GlobalKey<NavigatorState>();
...
return MaterialApp(
...
home: DropdownBanner(
child: Scaffold(...),
navigatorKey: navigatorKey,
),
);
}
}
To use it:
import 'packages:dropdown_banner/dropdown_banner.dart';
...
class SomeClass {
...
void doSomethingThenFail() {
DropdownBanner.showBanner(
text: 'Failed to complete network request',
color: Colors.red,
textStyle: TextStyle(color: Colors.white),
);
}
}
Click here to see an example
Just to add to the great answers - the best package I found is:
adaptive_dialog: ^1.8.0+1
For a one OK button the best thing I found is using showOkAlertDialog
Implementation:
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:flutter/material.dart';
Widget build(BuildContext context) {
return Container(
child: Center(
child: IconButton(
icon: Icon(
Icons.info,
),
onPressed: () => showOkAlertDialog(
context: context,
okLabel: 'OK',
title: 'Title',
message: 'This is the message',
),
)),
);
}
Clean and dismisses when you click 'Ok'.
If you need a dialog so this code for you. just use showDialog() onPress or any inside a function.
void showDialog() {
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: const Text("Login Failed!"),
content: const Text(
"Invalid credential !! Please check your email or password",
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w400),
),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(ctx).pop();
},
child: Container(
child: const Text(
"Try again",
style: TextStyle(color: Colors.cyan, fontSize: 17),
),
),
),
],
),
)}
Demo dialog screenshots
hope its helpful๐๐๐
Simple and working solution that I used: Enjoy
// Sample can be used for exit dialog box on apps
showAlertDialog(BuildContext context) {
Widget okButton = TextButton(
child: const Text("Leave now",style: TextStyle(color: Colors.red),),
onPressed: () { SystemNavigator.pop(); },
);
Widget nopeButton = TextButton(
child: const Text("Stay here"),
onPressed: () { Navigator.pop(context); },
);
AlertDialog alert = AlertDialog(
title: const Text("Leave"),
content: const Text("Are you sure you want to leave?"),
actions: [
nopeButton,
okButton,
],
);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
Another easy option to show Dialog is to use stacked_services package
_dialogService.showDialog(
title: "Title",
description: "Dialog message Tex",
);
});
This code works and demonstrates how to obtain the button value pressed by the user:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const Center(
child: MyStatelessWidget(),
),
),
);
}
}
class MyStatelessWidget extends StatelessWidget {
const MyStatelessWidget({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return TextButton(
onPressed: () {
// set up the buttons
Widget cancelButton = TextButton(
child: Text("Cancel"),
onPressed: () => Navigator.pop(context, 'Cancel'),
);
Widget continueButton = TextButton(
child: Text("Ok"),
onPressed: () => Navigator.pop(context, 'Ok'),
);
showDialog<String>(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text('AlertDialog Title'),
content: const Text('AlertDialog description'),
actions: <Widget>[
cancelButton,
continueButton,
],
),
).then((value) => print(value));
},
child: const Text('Show Dialog'),
);
}
}
Pressing on Ok button. then on Cancel button print
`showDialog<String>(
context: context,
builder: (BuildContext context) =>
AlertDialog(
title: const Text(
'Invalid Password',
style: TextStyle(color: Colors.red),
),
content:
const Text('Create Strong Password'),
actions: <Widget>[
Center(
child: TextButton(
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors
.red, // Background Color
),
onPressed: () => Navigator.pop(
context, 'Cancel'),
child: const Text('Cancel'),
),
),
],
),
),`
I'm quite new with Flutter and I'm coming from using the Angular framework. Currently, I'm experimenting with flutter to make a desktop application using the following flutter embedding project: https://github.com/Drakirus/go-flutter-desktop-embedder.
I was wondering if someone could explain to me the best way to implement the following:
The black box represents the application as a whole.
The red box represents the custom menu.
The green box represents the content of the page.
How would I go about routing between "widgets" inside of the green area without changing the widget holding the application?
I'd love some direction please.
I am contributing Drakirus 's go-flutter plugin.
This projecd had moved to https://github.com/go-flutter-desktop
The question you ask can use package responsive_scaffold
https://pub.dev/packages/responsive_scaffold
or
you can reference this doc https://iirokrankka.com/2018/01/28/implementing-adaptive-master-detail-layouts/
Basically, there two are different layouts, see comments for detail
class _MasterDetailContainerState extends State<MasterDetailContainer> {
// Track the currently selected item here. Only used for
// tablet layouts.
Item _selectedItem;
Widget _buildMobileLayout() {
return ItemListing(
// Since we're on mobile, just push a new route for the
// item details.
itemSelectedCallback: (item) {
Navigator.push(...);
},
);
}
Widget _buildTabletLayout() {
// For tablets, return a layout that has item listing on the left
// and item details on the right.
return Row(
children: <Widget>[
Flexible(
flex: 1,
child: ItemListing(
// Instead of pushing a new route here, we update
// the currently selected item, which is a part of
// our state now.
itemSelectedCallback: (item) {
setState(() {
_selectedItem = item;
});
},
),
),
Flexible(
flex: 3,
child: ItemDetails(
// The item details just blindly accepts whichever
// item we throw in its way, just like before.
item: _selectedItem,
),
),
],
);
}
For package responsive_scaffold
on-line demo https://fluttercommunity.github.io/responsive_scaffold/#/
github https://github.com/fluttercommunity/responsive_scaffold/
more template code snippets for layout
https://github.com/fluttercommunity/responsive_scaffold/tree/dev
more pictures and demo can found here https://github.com/fluttercommunity/responsive_scaffold/tree/dev/lib/templates/3-column
code snippet 1
import 'package:flutter/material.dart';
import 'package:responsive_scaffold/responsive_scaffold.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
var _scaffoldKey = new GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
return MaterialApp(
home: ResponsiveListScaffold.builder(
scaffoldKey: _scaffoldKey,
detailBuilder: (BuildContext context, int index, bool tablet) {
return DetailsScreen(
// appBar: AppBar(
// elevation: 0.0,
// title: Text("Details"),
// actions: [
// IconButton(
// icon: Icon(Icons.share),
// onPressed: () {},
// ),
// IconButton(
// icon: Icon(Icons.delete),
// onPressed: () {
// if (!tablet) Navigator.of(context).pop();
// },
// ),
// ],
// ),
body: Scaffold(
appBar: AppBar(
elevation: 0.0,
title: Text("Details"),
automaticallyImplyLeading: !tablet,
actions: [
IconButton(
icon: Icon(Icons.share),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.delete),
onPressed: () {
if (!tablet) Navigator.of(context).pop();
},
),
],
),
bottomNavigationBar: BottomAppBar(
elevation: 0.0,
child: Container(
child: IconButton(
icon: Icon(Icons.share),
onPressed: () {},
),
),
),
body: Container(
child: Center(
child: Text("Item: $index"),
),
),
),
);
},
nullItems: Center(child: CircularProgressIndicator()),
emptyItems: Center(child: Text("No Items Found")),
slivers: <Widget>[
SliverAppBar(
title: Text("App Bar"),
),
],
itemCount: 100,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: Text(index.toString()),
);
},
bottomNavigationBar: BottomAppBar(
elevation: 0.0,
child: Container(
child: IconButton(
icon: Icon(Icons.share),
onPressed: () {},
),
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
_scaffoldKey.currentState.showSnackBar(SnackBar(
content: Text("Snackbar!"),
));
},
),
),
);
}
}
code snippet 2
import 'package:flutter/material.dart';
import 'package:responsive_scaffold/responsive_scaffold.dart';
class MultiColumnNavigationExample extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ThreeColumnNavigation(
title: Text('Mailboxes'),
showDetailsArrows: true,
backgroundColor: Colors.grey[100],
bottomAppBar: BottomAppBar(
elevation: 1,
child: Row(
children: <Widget>[
IconButton(
icon: Icon(
Icons.filter_list,
color: Colors.transparent,
),
onPressed: () {},
),
],
),
),
sections: [
MainSection(
label: Text('All Inboxes'),
icon: Icon(Icons.mail),
itemCount: 100,
itemBuilder: (context, index, selected) {
return ListTile(
leading: CircleAvatar(
child: Text(index.toString()),
),
selected: selected,
title: Text('Primary Information'),
subtitle: Text('Here are some details about the item'),
);
},
bottomAppBar: BottomAppBar(
elevation: 1,
child: Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.filter_list),
onPressed: () {},
),
],
),
),
getDetails: (context, index) {
return DetailsWidget(
title: Text('Details'),
child: Center(
child: Text(
index.toString(),
),
),
);
},
),
MainSection(
label: Text('Sent Mail'),
icon: Icon(Icons.send),
itemCount: 100,
itemBuilder: (context, index, selected) {
return ListTile(
leading: CircleAvatar(
child: Text(index.toString()),
),
selected: selected,
title: Text('Secondary Information'),
subtitle: Text('Here are some details about the item'),
);
},
getDetails: (context, index) {
return DetailsWidget(
title: Text('Details'),
actions: [
IconButton(
icon: Icon(Icons.share),
onPressed: () {},
),
],
child: Center(
child: Text(
index.toString(),
),
),
);
},
),
],
);
}
}
I'm a noob so please take anything I say with a grain of salt.
I know 2 ways to navigate through widgets and you can find them both here
https://flutter.io/docs/development/ui/navigation
I believe the main difference I can perceive is if you want to
send data to the new 'route' or not (the named route way cannot, at least that I'm aware of);
said so you can keep your main 'screen' and change the red and green widget
using the state of the widget where they are contained
example
class BlackWidget extends StatefulWidget
bla bla bla => BlackWidgetState();
class BlackWidget extend State<BlackWidget>
Widget tallWidget = GreenWidget();
Widget bigWidget = RedWidget();
return
container, column.. etc
Row(
children:[tallWidget,bigWidget
])
button onTap => tallWidget = YellowWidget();
}
GreenWidget... bla bla bla...
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => RedWidget()),
);
}
sorry for the 'bla bla', the part you need is at the bottom,
just added the 'yellow' widget to underline that you can
actually swap the 'green widget' with anything you want
This will be a lot of explaining but i hope someone will be able to help.
Currently i have search button on my appbar that, when pressed, covers over my appbar title with a textfield
The normal appbar title is an image and i am adding functionality that when pressed, it brings you to the home screen. This is were it gets tricky, because i need to use this line of code to accomplish just that
new InkWell (
child: Image.asset(
'images/logoGrey.png',
fit: BoxFit.fill,
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
LandingPage(),
),
);
},
);
so i set that to a variable like so
class _ControlsPageState extends State<ControlsPage> {
Widget appBarTitle = new InkWell (
child: Image.asset(
'images/logoGrey.png',
fit: BoxFit.fill,
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
LandingPage(),
),
);
},
);
The reason i have this variable is so that i can change the state of the appbar(title) to a textfield when i click on the search button and back to the image when i close out.
but this wont work (error on "context") seeing as though this line of code below can only be used under "Widget build(BuildContext context)" and not in my class....
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
LandingPage(),
),
);
},
The bottom line is i need my appbar title to be a callback to the variable "appBarTitle", and the variable gets an error on "context", is there anyway i can make this work?
here is the appbar code in case it helps
appBar: AppBar(
iconTheme: new IconThemeData(color: Theme.CompanyColors.coolGrey),
backgroundColor: Colors.white,
centerTitle: true,
title: appBarTitle ,
actions: <Widget>[
new IconButton(
icon: actionIcon,
onPressed: () {
setState(() {
if (this.actionIcon.icon == Icons.search) {
this.actionIcon =
new Icon(Icons.close, color: Theme.CompanyColors.coolGrey);
this.appBarTitle = new TextField(
onSubmitted: (String str) {
setState(() {
result = str;
});
controller.text = "";
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ControlSearchPage(
search: result, title: "${widget.title}"),
),
);
},
style: new TextStyle(
color: Colors.black,
),
decoration: new InputDecoration(
prefixIcon:
new Icon(Icons.search, color: Theme.CompanyColors.coolGrey),
hintText: "Search...",
hintStyle: new TextStyle(color: Theme.CompanyColors.coolGrey)),
);
} else {
this.actionIcon =
new Icon(Icons.search, color: Theme.CompanyColors.coolGrey);
this.appBarTitle = new InkWell (
child: Image.asset(
'images/logoGrey.png',
fit: BoxFit.fill,
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
LandingPage(),
),
);
},
);
}
});
},
),
],
),
any comments will be appreciated
You should change appBarTitle to be a method that can generate the widget on state change rather than saving it to a variable. This way, you can ensure that it will only be generated when context is available.
// Define a bool to hold the current search state
bool _isSearching = false;
...
// In your build method
appBar: AppBar(
iconTheme: new IconThemeData(color: Theme.CompanyColors.coolGrey),
backgroundColor: Colors.white,
centerTitle: true,
title: _buildAppBarTitle(),
actions: <Widget>[
new IconButton(
icon: _isSearching
? new Icon(Icons.close, color: Theme.CompanyColors.coolGrey)
: new Icon(Icons.search, color: Theme.CompanyColors.coolGrey),
onPressed: () {
setState(() => _isSearching = !_isSearching);
},
),
],
),
...
// Define a separate method to build the appBarTitle
Widget _buildAppBarTitle() {
if (_isSearching) {
return new TextField(
onSubmitted: (String str) {
setState(() {
result = str;
});
controller.text = "";
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ControlSearchPage(
search: result, title: "${widget.title}"),
),
);
},
style: new TextStyle(
color: Colors.black,
),
decoration: new InputDecoration(
prefixIcon:
new Icon(Icons.search, color: Theme.CompanyColors.coolGrey),
hintText: "Search...",
hintStyle: new TextStyle(color: Theme.CompanyColors.coolGrey)),
);
} else {
return new InkWell (
child: Image.asset(
'images/logoGrey.png',
fit: BoxFit.fill,
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
LandingPage(),
),
);
},
);
}