Android Pysical Back Button closes the app - flutter

i am pushing the new widget by below code:
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => BigPhoto(widget.images)))
},
After the new page opened then when I click to back button which android physical back button then the app closing instead of popping back. How can i fix it?
full implementation:
return Stack(
children: <Widget>[
StreamBuilder<int>(
stream: bloc.currentItemStream,
builder: (context, snapshot) {
return GestureDetector(
onTap: () => {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => BigPhoto(widget.images, snapshot.data - 1)))
},
child: AspectRatio(
aspectRatio: 411 / 308,
child: PageView.builder(
physics: BouncingScrollPhysics(),
itemCount: widget.images.length,
onPageChanged: (value) {
bloc.changeCurrentItemIndex(value + 1);
},
itemBuilder: (context, position) {
return FittedBox(
fit: BoxFit.cover,
child: Container(
child: Image.network(
"{widget.images[position]}",
fit: BoxFit.cover,
),
),
);
},
)),
);
}
),
Positioned(
left: 26,
bottom: 9,
child: StreamBuilder<int>(
stream: bloc.currentItemStream,
builder: (context, snapshot) {
return Container(
padding: const EdgeInsets.only(
bottom: 3, top: 3, left: 7, right: 7),
decoration: BoxDecoration(
border: Border.all(width: 3.0, color: Colors.white),
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(20.0)),
),
child: Text(
" ${snapshot.data} / ${widget.images.length}",
style: TextStyle(
fontSize: 11.0,
fontFamily: 'Roboto-Regular',
backgroundColor: Colors.white),
),
);
}),
),
],
);

I would suggest this solution:
You can unable the return with the physical back button on the page that you are navigating to, by putting the build widget into a WillPopScoop widget and set onWillPop to false. And implement your own back button just like that.
Widget build(BuildContext context) {
WillPopScope(
onWillPop: () async => false,
child: Material(
child: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () {
_goBack(context);
})),
body : Image.asset("YOUR_URL_IMAGE"));
the _goback() methode :
_goBack(BuildContext context) {
Navigator.pop(context); }

Related

what is the best way to use MaterialPageRoute in list view

I have this ListView and I want to add a MaterialPageRoute. How can I do it that it opens a diverent page when I click on anoter item from the ListView.
(I dont want to want to send selected item data to next screen)
Example:
I click on ExamplePage it shod Navigate to ExamplePage() when I click on TestPage it shod Navigate to TestPage()
Expanded(
child: ListView.builder(
itemCount: categories.length,
itemBuilder: (BuildContext ctx, int index) {
return GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return ExamplePage();
},
),
);
},
child: Container(
margin: const EdgeInsets.all(20),
height: 150,
child: Stack(
children: [
Positioned.fill(
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Image.asset(
'images/${categories[index].imgName}.png',
fit: BoxFit.cover),
),
),
Positioned(
bottom: 0,
child: Padding(
padding: const EdgeInsets.all(10.0),
Text(
categories[index].name,
style: const TextStyle(fontSize: 25),
)
),
)
],
),
),
);
},
),
)

Flutter: FloatingActionButton over last element of GridView

I have a scrollable list with a FloatingActionButton. I would like to make the list to finish before the FloatingActionButton because the last item of the list isn't visible anymore just like in the Gmail application.
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
backgroundColor: Colors.white,
resizeToAvoidBottomInset: false,
appBar: AppBar(
brightness: Brightness.light,
elevation: 0.0,
backgroundColor: Colors.transparent,
title: Text(
'OnePictura',
style: TextStyle(color: dark, fontSize: 20),
),
actions: [
Padding(
padding: const EdgeInsets.all(8),
child: Container(
decoration:
BoxDecoration(shape: BoxShape.circle, color: textWhite),
child: IconButton(
icon: Image.asset(
'graphics/setting_icon.png',
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new SettingPage(),
),
);
},
),
),
),
],
),
body: LoadingIndicatorPage(
loading: _loading,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Align(
alignment: Alignment.topLeft,
child: IconButton(
icon: ImageIcon(
AssetImage("graphics/icon_search.png"),
),
onPressed: () {
showSearch(context: context, delegate: DataSearch(albumList, _userId));
},
),
),
xyz(),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
var result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new CreateAlbumPage(),
),
);
if (result) {
_getAllAlbum();
setState(() {
albumList.clear();
});
}
},
backgroundColor: Colors.white,
child: Icon(
Icons.add,
color: purpleishBlueTwo,
),
),
);
}
Widget xyz() {
if (albumList.length == 0) {
return Expanded(
child: SmartRefresher(
onRefresh: _onRefresh,
controller: _refreshController,
enablePullDown: true,
enablePullUp: false,
child: Center(
child: Text(_message),
),
),
);
} else {
return Expanded(
child: SmartRefresher(
onRefresh: _onRefresh,
controller: _refreshController,
enablePullDown: true,
enablePullUp: false,
child: GridView.builder(
controller: _scrollController,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.5),
),
itemCount: albumList.length,
itemBuilder: (BuildContext context, int index) {
return buildRow(index);
},
),
),
);
}
}
Widget buildRow(int index) {
return Padding(
padding: EdgeInsets.only(top: 10.0, right: 10.0, left: 10.0, bottom: 10.0),
child: GestureDetector(
onTap: () async {
var result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
new AlbumPage(tabIndex: index, albumList: albumList),
),
);
if (result) {
_getAllAlbum();
_getSubscriptionDetails();
setState(() {
albumList.clear();
});
}
},
child: AlbumTile(
index: index,
currentUser: _userId,
albumList: albumList,
deleteAlbum: _deleteDialog,
),
),
);
}
child: GridView.builder(
controller: _scrollController,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.5),
),
itemCount: albumList.length,
itemBuilder: (BuildContext context, int index) {
return buildRow(index);
},
),
to
child: GridView.builder(
controller: _scrollController,
padding: EdgeInsets.only(bottom: 70),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.5),
),
itemCount: albumList.length,
itemBuilder: (BuildContext context, int index) {
return buildRow(index);
},
),

Hw to substitute one specific Widget with another One once OnPressed is performed

I have 2 specific Widget which the first One has a RaisedButton which should be clicked and the widget with the RaisedButton will be substitute with another one.
this is my code:
Widget FundsWidget() {
return Container(
height: 200,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Devi acquistare dei crediti per poter vedere i Post di ${widget.user.name}',
style: TextStyle(fontSize: 12),
),
RaisedButton(
elevation: 10,
color: Colors.blue,
child: Text('Acquista Crediti'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => PostGrid(),
),
),
),
],
),
);
}
and this is called into the main build method, once RaisedButton is clicked, should be substited by another one
Widget PostGrid() {
return Container(
height: 291,
child: GridView.builder(
controller: controller,
itemCount: widget.user.imageUrl.length + 1,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
itemBuilder: (BuildContext context, int index) {
if (index == widget.user.imageUrl.length) {}
return GestureDetector(
onTap: () => showDialog(
context: context,
builder: (context) => AlertDialog(
actions: [
Image.asset(widget.user.imageUrl),
Text(widget.user.name),
],
),
),
child: Card(
elevation: 5,
child: Image.asset(widget.user.imageUrl),
),
);
},
),
);
}
that at the moment is not into the build method.
how I can perform that?
I think you can use setState method inside your onPresesd and change a bool in it.
and check that bool to set suitable widget like below pattern:
class Test2 extends StatefulWidget {
#override
_Test2State createState() => _Test2State();
}
class _Test2State extends State<Test2> {
bool boolName = true;
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child:boolName ?FontWeight:PostGrid ));
}
Widget FundsWidget() {
return Container(
height: 200,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Devi acquistare dei crediti per poter vedere i Post di ${widget.user.name}',
style: TextStyle(fontSize: 12),
),
RaisedButton(
elevation: 10,
color: Colors.blue,
child: Text('Acquista Crediti'),
onPressed: () {
setState(() {
boolName = false;
});
}
),
),
],
),
);
}
Widget PostGrid() {
return Container(
height: 291,
child: GridView.builder(
controller: controller,
itemCount: widget.user.imageUrl.length + 1,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
itemBuilder: (BuildContext context, int index) {
if (index == widget.user.imageUrl.length) {}
return GestureDetector(
onTap: () => showDialog(
context: context,
builder: (context) => AlertDialog(
actions: [
Image.asset(widget.user.imageUrl),
Text(widget.user.name),
],
),
),
child: Card(
elevation: 5,
child: Image.asset(widget.user.imageUrl),
),
);
},
),
);
}
}

How I can put Widget above Widget using List<Widget> widget in Flutter?

Is it possible to stack multiple widget ?
I have widgets variable that wanted to be placed below InkWell widget.
How should I solve this ?
This is my code :
final List<Widget> widgets = [Home1(), Home2(),Home3()];
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Container(
child: new PageView.builder(
controller: new PageController(
viewportFraction: 1.0,
),
itemCount: widget.length,
itemBuilder: (BuildContext context, int i) {
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 5.0,
vertical: 22.0,
),
child: Material(
borderRadius: BorderRadius.circular(15.0,),
elevation: 1.0,
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Hero(
tag: widget[i],
child: Material(
child: InkWell(
onTap:() => Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) => Home(),
),
),
child: ..........?????????
),
),
),
],
),
),
);
},
),
),
);
}

Scroll through Flutter Bottom Sheet

I'm using a Flutter modal bottom sheet to display some options for the user to select.
I have a Column with a list of ListTiles as the content of the bottom sheet.
My problem is that if I have more than 6 ListTiles, some are cut off and not displayed.
Is there a way to make the bottom Sheet scrollable?
Just change your Column into a ListView, like so:
return ListView(
children: <Widget>[
...
]
);
What if I don't want the content of the sheet to be scrolled, but the sheet itself?
If you want the user to be able to swipe up the bottom sheet to fill the screen, I'm afraid this isn't possible in the current implementation of the modular bottom sheet.
I've found a solution implementing the code below
void _showBottomSheet(BuildContext context) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) {
return GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Container(
color: Color.fromRGBO(0, 0, 0, 0.001),
child: GestureDetector(
onTap: () {},
child: DraggableScrollableSheet(
initialChildSize: 0.4,
minChildSize: 0.2,
maxChildSize: 0.75,
builder: (_, controller) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(25.0),
topRight: const Radius.circular(25.0),
),
),
child: Column(
children: [
Icon(
Icons.remove,
color: Colors.grey[600],
),
Expanded(
child: ListView.builder(
controller: controller,
itemCount: 100,
itemBuilder: (_, index) {
return Card(
child: Padding(
padding: EdgeInsets.all(8),
child: Text("Element at index($index)"),
),
);
},
),
),
],
),
);
},
),
),
),
);
},
);
}
If you want a model bottom sheet that can be scrolled.
You can use the isScrollControlled attribute of showModalBottomSheet to achieve the effect.
If you want a persistent bottom sheet that can be scrolled.
You can use the DraggableScrollableSheet
Example:
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('DraggableScrollableSheet'),
),
body: SizedBox.expand(
child: DraggableScrollableSheet(
builder: (BuildContext context, ScrollController scrollController) {
return Container(
color: Colors.blue[100],
child: ListView.builder(
controller: scrollController,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text('Item $index'));
},
),
);
},
),
),
);
}
}
Here is the official video from the Flutter team.
A live demo on DartPad can be found here.
Almost the same solution like this one but without the unnecessary layers of gesture detectors etc.
The important part is the expand: false, in DraggableScrollableSheet, because it defaults to true. This causes the bottom sheet to expand to full height in default config. With this set to false there is no need to wrap the bottom sheet with two gesture detectors to detect the outside tap.
Also in this case only one shape is required.
showModalBottomSheet(
context: context,
isScrollControlled: true,
isDismissible: true,
shape: const RoundedRectangleBorder(
borderRadius:
BorderRadius.vertical(top: Radius.circular(16))),
builder: (context) => DraggableScrollableSheet(
initialChildSize: 0.4,
minChildSize: 0.2,
maxChildSize: 0.75,
expand: false,
builder: (_, controller) => Column(
children: [
Icon(
Icons.remove,
color: Colors.grey[600],
),
Expanded(
child: ListView.builder(
controller: controller,
itemCount: 100,
itemBuilder: (_, index) {
return Card(
child: Padding(
padding: EdgeInsets.all(8),
child: Text("Element at index($index)"),
),
);
},
),
),
],
),
),
);