I want to be able to transfer data from one screen to another. What I have now does work, but I want to be able to have icon in
the AppBar that will only go to the second page, and not take any arguments. For now I have this:
FIRST PAGE
This is the icon on the first page that adds the list tile arguments to the Cart screen (and only adds , it doesn't push the Cart screen, that
should be done below in the appbar.
child: IconButton(
icon: Icon(Icons.add),
onPressed: () => MaterialPageRoute(
builder: (context) =>
Cart(person.name, person.surname),
)),
Below in the scaffold I have this in the AppBar, the icon that should only push the Cart screen, and not any other values.
IconButton(
icon: Icon(Icons.add_shopping_cart, color: Colors.white),
//this will be the cart window ontap, change icon to something better
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
Cart(//there should be arguments here, but I just want to go to Cart screen, the arguments were added in the first icon))),
This Cart class requires arguments (from the second page, like personName, personSurname), but I just want to be able to push
the second screen, and not have any arguments on there. It is the small cart icon in the appbar.
SECOND PAGE
Here is the second page (sudo cart screen) that should just take in the arguments from the first one.
class Cart extends StatefulWidget {
final String personName;
final String personSurname;
Cart(this.personName, this.personSurname);
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Cart'),
centerTitle: true,
),
body: Center(
child: Container(
child: Text('${widget.personName}, ${widget.personSurname}'))),
);
}
}
My issue is that I want to have the 2 separate functions for the cart. First one is on the first page where first icon
only adds the whatever argument I want to the cart, and the second icon in the app bar of first page just pushes the Cart screen.
In the second screen, I just want to have whatever data pushed from the first page.
Try it like this:
Declare two variables above:
String name = '';
String surname = '';
Assign your data to them:
child: IconButton(
icon: Icon(Icons.add),
onPressed: () {
name = person.name;
surname = person.surname;
},
And use them as arguments:
IconButton(
icon: Icon(Icons.add_shopping_cart, color: Colors.white),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => Cart(name, surname))
),
Related
so I have a Drawer with currently two Drawer-Items leading to Page1 and Page2. Lets say I am currently on Page1. I can still press the Drawer-Item "Page1" and another "Page1" will be opened. I don#t want this to happen, therefore my question.
How do I disable Drawer-Item "Page1" when I am currently on Page1 and Drawer-Item "Page2" if I am on Page2.
Thank you in advance.
class PrimaryDrawer extends StatelessWidget {
const PrimaryDrawer({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
const DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue,
),
child: Text('Drawer Header'),
),
ListTile(
title: const Text('Neuigkeiten'),
onTap: () {
Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (context){
return const NewsPage(title: 'Neuigkeiten');
}));
},
),
ListTile(
title: const Text('Geburtstage'),
onTap: () {
Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (context){
return const BirthdayPage(title: 'Geburtstage');
}));
},
),
],
),
);
}
}
Edit: So i added a code snippet, so whats bothering me is that If I am on the "NewsPage" and I open up the Drawer I can open up "NewsPage" again, I want to prohibit that. IDK if it even matters if there is the same page multiple times in the Route, but It just bothers me, probably a me thing i guess.
before navigate to new Page2 close the Drawer
Navigator.pop(context);
You can use provider to save your current page index and put condition while clicking on drawer item to check if its current page index is 1 then Page 1 will be not clickable and drawer is closed after the same
I have a simple list of ListTile s that I nested in Slidable widget using the flutter_slidable package. However there is one issue that when I use the delete button, the item stays on the screen, even though it is successfully removed from the list (If i make a hot reload, it will actually get removed from screen). I tried to add a setState method inside the onPressed function but I cannot add it because the SlidableAction widget is a stateless widget. How can I make the item disappear when I tap on this button?
Here is a small video demonstration. I delete two lists with the delete button. They stay on the screen. I go home screen and come back to see they got deleted.
https://streamable.com/td7blf
Here is my code:
Expanded(
child: ListView.builder(
itemCount: likedNames.length,
itemBuilder: (context, index) {
return Slidable(
key: const ValueKey(0),
endActionPane: ActionPane(
motion: ScrollMotion(),
dismissible: DismissiblePane(onDismissed: () {
likedNames.remove(likedNames[index]);
}),
children: [
SlidableAction(
onPressed: (context) {
likedNames.remove(likedNames[index]); // <- this is the part where I want to do the removing of the item
},
label: 'Delete',
backgroundColor: AppColors.error,
),
],
),
child: ListTile(
onTap: () {},
title: Text(likedNames[index].name),
trailing: Icon(Icons.chevron_right),
),
);
}),
),
onPressed: (context) {
setState() => likedNames.remove(likedNames[index])
},
I've used this solution:
onPressed: (BuildContext context) async {
await Provider.of<MyList>(context, listen: false)
.remove(MyList[index]);
}
MyList is a separate class:
class MyList extends ChangeNotifier
Whit this methods:
final List<String> _myList = [];
List<String> get items => _myList;
.
.
.
Future<bool> remove(String item) async {
_myList.remove(item);
notifyListeners();
return true;
}
I have bottom tab navigator that contains of A and B screens, inside B screen I have widget that navigate to C page and inside C page I want to add back arrow to go back to previous screen (B screen), so...
I have simple widget that the code looks like this
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(),
),
title: Text("XXX"),
centerTitle: true,
),
body: detail()));
}
the problem is whenever I click back arrow.. it turns to black screen... I don't get any idea what the problem is... so is there a way to go to my previous screen?
and this is how I ndo navigate from B screen to C page
InkWell(
onTap: () {Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => new NextScreen(check: values)));
},
child: Text(
"Next...",
style: TextStyle(
fontSize: 13.0,
),
),
)
The reason why you see a blank screen is because you navigated using pushReplacement. What pushReplacement does it that it will navigate to the next screen without stacking itself to the route meaning that it will make the app forget that the last screen was your screen B. Try using Navigator.push() instead.
Here is an example:
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ScreenC()),
);
}
When the user clicks the FAB, i want it to create a new Card widget wrapped in a GestureDetector. I have created a list of type widget and also created a function with a setState to add to the list and display it in a SliverGrid. but when i click the FAB, it doesnt seem to be adding.
Could i get a small guide on how to add a Card using an FAB. (or adding any type of widget in a SliverGrid).
the list : List<Widget> cardList = <Widget>[];
function for adding items to the list :
void addItems() async{
setState(() {
cardList.insert(0, GestureDetector(
onTap: () async {
await Navigator.push( context, MaterialPageRoute(
builder: (context) => TodoList(), // this just navigates to another screen ; not important in this question
)
);
},
child: Card(
child:Center(child: whitefontstylemont(text: "project 1", size:20,)) //this is just a custom TextStyle
),
));
});
}
the floating action button which adds a new Card to the list :
floatingActionButton: FloatingActionButton( // this is inside a Scaffold
onPressed: ()async {
setState(() {
addItems();
});
},
heroTag: "btn2",
child: Icon(Icons.add, color: Color(whitecolor),), backgroundColor: Color(redcolor),),
the SliverGrid where i want a new card to be displayed :
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2
),
delegate: new SliverChildBuilderDelegate((context, index) {
return cardList[index];
},
childCount: cardList.length // this is where i want a new Card to be displayed
)
),
I am using interceptor https://pub.dartlang.org/packages/back_button_interceptor to execute a method when the page 1 is back from page 2.
If I come back from page 2 to page 1 using device back button, the method is executed.
But if I come back from page 2 to page 1 using the arrow button at appBar I am not able to execute the method.
How can the back arrow button functionality default to the device back button?
You can surround your scaffold on Page 2 with WillPopScope, set onWillPop to false to prevent the page from being popped by the system and then add your own back button into the app bar's leading widget and perform your pop in there.
#override
Widget build(BuildContext context) {
return new WillPopScope(
onWillPop: () async => false,
child: new Scaffold(
appBar: new AppBar(
title: new Text("data"),
leading: new IconButton(
icon: new Icon(Icons.ac_unit),
onPressed: () => Navigator.of(context).pop(),
),
),
),
);
}
code for the answer from this post
Edit: Addition to Page 2 to control navigation
In addition to the above code you'll add the below code to page 2. Change
Navigator.of(context).pop()
to
Navigator.of(context).pop('upload_files')
Then in your page 1 where you navigate you'll await the navigation and use the result returned from the pop on page 2 and run your logic
var navigationResult = await Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => Page2()));
if(navigationResult == 'upload_files') {
uploadFiles(); // Perform your custom functionality here.
}
The default back button in AppBar is BackButton widget from material.dart. You may create it manually and pass your own onPressed to do what you want:
return Scaffold(
appBar: AppBar(
leading: BackButton(onPressed: _onBackPressed),
title: Text('Title'),
),
body: Container(),
);
If you do not specify leading in AppBar, then it creates a BackButton with the handler that does Navigator.maybePop(context).