How to display a snackBar in scaffold is body is composed of Stack? - flutter

I am trying to display a snack bar on my screen. But the snack bar is covering the whole screen instead of just being displayed at the bottom. Here is my code.
Scaffold(
key: _scaffoldKey ,
backgroundColor: Colors.pink,
body: Stack(
children: <Widget>[
Text('Display Scaffold'),
Positioned(
top: 110,
child: Container(
child: FlatButton(
onpressed: (){
final snackBar = SnackBar(duration: Duration(seconds: 4),
content: Center(child: Text('Welcome')),
) ;
_scaffoldKey.currentState.showSnackBar(snackBar);
}
),
),
),
),
);

Remove Center widget. This makes the widget as big as the parent allows.
If you need to center your text, just use textAlign: TextAlign.center property in Text widget.

Have you try this ?
Scaffold.of(context).showSnackBar(snackBar);
instead of
_scaffoldKey.currentState.showSnackBar(snackBar);
It may be the solution.
I hope it could help you !

Related

switch between pages in the flutter using the Smooth Page Indicator

I want to make a steamer to the next page using the Smooth Page Indicator widget. I added this widget to the page but I don't know how to add the pages I want to go to. I will be grateful for your help
My code :
final controller = PageController(viewportFraction: 0.8, keepPage: true);
#override
Widget build(BuildContext context) {
return Scaffold(
body:
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(height: 35.0),
Container(
child: SmoothPageIndicator(
controller: controller,
count: 2,
effect: JumpingDotEffect(
dotHeight: 16,
dotWidth: 16,
jumpScale: .7,
verticalOffset: 15,
),
),
),
]),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_scanQR();
});
},
child: const Icon(Icons.qr_code),
backgroundColor: Colors.pink,
),
);
}
the name of my page to which I want to go Page2, and this Page1
I think you might be looking for the PageView widget : https://api.flutter.dev/flutter/widgets/PageView-class.html
By passing the same PageController to both, the PageView and the SmoothPageIndicator widgets you should be able to swipe left and right AND see the dots move along. That simple.

ListView containing a multiline Textfield followed by ListTiles in flutter

The goal is to have a ListView that contains a multiline texfield (with an arbitrary number of lines, maxLines=null) that is followed by several ListTiles. When lines are added to the TextField, it grows and the ListTiles should move accordingly. However, there is an unexpected behaviour with the following code:
#override
Widget build(BuildContext context) {
ListView l = new ListView(children: [
TextField(maxLines: null),
SizedBox(height: 50, child: ColoredBox(color: Colors.yellow,child: Text("Tile1"),) ),
ListTile(tileColor: Colors.blueGrey,title: Text("Tile1"),),
ListTile(tileColor: Colors.blueGrey,title: Icon(Icons.looks_two_rounded),)
]);
return Scaffold(backgroundColor: Color(0xdcdcffff), body: Center(child: l));
}
https://gfycat.com/fr/obviousshorttermchihuahua
The green colored box moves down at expected but the ListTiles do not (although their children do), until I scroll, then they move where they should've been.
Is there any way to solve this ?
I don't know what exactly caused the bug, but I found a workaround that could perhaps be useful to someone trying to do the same: I put the ListTile in transparent inside a Colored box:
#override
Widget build(BuildContext context) {
ListView l = new ListView(children: [
TextField(maxLines: null),
SizedBox(
height: 50,
child: ColoredBox(
color: Colors.green,
child: Text("Tile1"),
)),
ColoredBox(
color: Color(0x77ff0000),
child: ListTile(
tileColor: Colors.transparent,
title: Text("Tile1"),
),
),
ColoredBox(
color: Color(0x77ff0000),
child: ListTile(
tileColor: Colors.transparent,
title: Icon(Icons.looks_two_rounded),
)),
]);
return Scaffold(body: Center(child: l));
}
https://gfycat.com/fr/idioticquarrelsomegossamerwingedbutterfly

Color of a widget inside a Stack is always slightly transparent

I display a custom-made bottom app bar in a Stack because of keyboard padding reasons. The custom widget is fully opaque as it should be until it's a child of a Stack in which case, the content behind it starts to be visible since the color's opacity somehow changes.
As you can see, it's only the "main" color that's transparent. Icons remain opaque.
This is the build method of my custom BottomBar widget which is then just regularly put into a Stack. I have tried using a Material and even a simple Container in place of the BottomAppBar widget but the results are the same.
#override
Widget build(BuildContext context) {
return BottomAppBar(
color: Colors.blue.withOpacity(1),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(MdiIcons.plusBoxOutline),
onPressed: () {},
),
Text('Edited 11:57'),
IconButton(
icon: Icon(MdiIcons.dotsVertical),
onPressed: () {},
),
],
),
);
}
Can you interact with the BottomAppBar ? It looks like an order problem. Try to put the BottomAppBar as last in the Stack children.
Note that BottomAppBar doesn't have a constant size, if you did not add it to Scaffold bottomNavigationBar named parameter has a size if this is not null. Below is peace of code in Scaffold dart file:
double bottomNavigationBarTop;
if (hasChild(_ScaffoldSlot.bottomNavigationBar)) {
final double bottomNavigationBarHeight = layoutChild(_ScaffoldSlot.bottomNavigationBar, fullWidthConstraints).height;
bottomWidgetsHeight += bottomNavigationBarHeight;
bottomNavigationBarTop = math.max(0.0, bottom - bottomWidgetsHeight);
positionChild(_ScaffoldSlot.bottomNavigationBar, Offset(0.0, bottomNavigationBarTop));
}
You can even develop your own Widget without BottomAppBar but if you want things like centerDocked and things like circular notched, you will have to do more stuff (anyway you have flexibility to custom design the way you want).
Here is a simple example to do that(one way to do that):
import 'package:flutter/material.dart';
class CustomBottomBar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Container(
margin: EdgeInsets.only(bottom: 50),
color: Colors.greenAccent, // if you want this color under bottom bar add the margin to list view
child: ListView.builder(
itemCount: 100,
itemBuilder: (_, int index) => Text("Text $index"),
),
),
Positioned(
bottom: 0,
child: Container(
color: Colors.amber.withOpacity(.5),
width: MediaQuery.of(context).size.width,
height: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: List.generate(4, (int index) => Text("Text $index")), // you can make these clickable by wrapping with InkWell or any gesture widget
),
),
),
],
),
);
}
}

How to make bottomNavigationBar notch transparent

I want to make the notch margin spacing (space between FAB's sides and bottom bar) like android material design explain in Inset FAB, It looks like a zoom background text in this small visible round portion. How we can make notching space transparent to see the text behind it?
However, mine bottom bar is not showing like that
My implementation
Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.white,
child: Image.asset("images/paw.png"),
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => Map()));
},
),
bottomNavigationBar: BottomAppBar(
shape: CircularNotchedRectangle(),
child: new Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(Icons.menu),
color: Colors.transparent,
onPressed: () {},
),
],
),
color: Utiles.primary_bg_color,
),
body: Container(...)
You need extendBody: true in Scaffold
class SO extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
extendBody: true,
appBar: AppBar(),
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Text('text text text text text text text text text text text text text text text text text text text text ');
},
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
onPressed: () {},
),
bottomNavigationBar: BottomAppBar(
shape: CircularNotchedRectangle(),
notchMargin: 12,
color: Colors.blue,
child: Container(
height: 60,
),
),
);
}
}
BottomAppBar + BottomNavigationBar
The question title asks about BottomNavigationBar so I'm adding this answer to help people using both a BottomAppBar with a BottomNavigationBar.
If you're not using BottomNavigationBar, ignore this.
NavBar Covers Notch
By default, a BottomNavigationBar used as a child inside a BottomAppBar, will cover the notch like so:
We need to remove its color & shadow to let the notch show.
Using BottomNavigationBar in BottomAppBar
To keep the notch visible...
BottomNavigationBar needs:
a backgroundColor specified, with 0 alpha (completely transparent)
otherwise, the default onBackground theme color is used, covering the notch
elevation: 0 to remove an ugly shadow under BottomNavigationBar
the transparent backgroundColor makes the shadow visible & horrendous
BottomAppBar needs:
shape: CircularNotchedRectangle() obviously, to have a notch for the FAB
elevation: 0 to remove a slight shadow under the notched FAB (barely visible)
Scaffold needs:
extendBody: true to allow body content to flow underneath notched FAB
SafeArea needs:
if using SafeArea, use bottom:false arg, so our body can flow below past the BottomNavigationBar, under the FAB
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
extendBody: true, // CRITICAL for body flowing under FAB
body: SafeArea(
child: Center(
child: Container(
color: Colors.greenAccent,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
),
bottom: false,
// ↑ SafeArea(bottom:false) allows Scaffold body:+extendBody: to hit bottom edge
),
// ↓ Location: centerDocked positions notched FAB in center of BottomAppBar ↓
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
bottomNavigationBar: BottomAppBar( // ****** APP BAR ******************
clipBehavior: Clip.antiAlias,
shape: CircularNotchedRectangle(), // ← carves notch for FAB in BottomAppBar
color: Theme.of(context).primaryColor.withAlpha(255),
// ↑ use .withAlpha(0) to debug/peek underneath ↑ BottomAppBar
elevation: 0, // ← removes slight shadow under FAB, hardly noticeable
// ↑ default elevation is 8. Peek it by setting color ↑ alpha to 0
child: BottomNavigationBar( // ***** NAVBAR *************************
elevation: 0, // 0 removes ugly rectangular NavBar shadow
// CRITICAL ↓ a solid color here destroys FAB notch. Use alpha 0!
backgroundColor: Theme.of(context).primaryColor.withAlpha(0),
// ====================== END OF INTERESTING STUFF =================
selectedItemColor: Theme.of(context).colorScheme.onSurface,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.ac_unit_outlined,
size: 40,
color: Theme.of(context).colorScheme.onBackground),
label: 'Home'),
BottomNavigationBarItem(
icon: Icon(Icons.access_alarm,
size: 40,
color: Theme.of(context).colorScheme.onBackground),
label: 'Edit')
],
),
),
);
Result
With the above pieces in place you should see something like this:
Use, extendBody: true
From the docs,
extendBody: true ensures that that scaffold's body will be visible through the bottom navigation bar's notch
Do:
return Scaffold(
extendBody: true,
(...)
after
body: SafeArea(
bottom: false,
(...)
after "no add backgroundColor"
BottomNavigationBar(
//backgroundColor:
If you use safe Area ,then extended Body and probably other methods doesn't work. So set the safe Area to (false).

Flutter Showing Snackbar On Top of Bottom Sheet

In my code I call a bottom sheet to display a list of tiles. These tiles contain buttons that display a snackbar. That functionality works fine, the only issue is that the snackbar is displayed behind the bottom sheet so you can only see it if you close the bottom sheet. Each of them are called with the following code:
1. Bottom Sheet:
void _settingModalBottomSheet(context, stream, scaffoldKey ) {
if (_availableRides.length == 0) {
return null;
} else {
return scaffoldKey.currentState.showBottomSheet((context) {
return Column(
children: Widgets;
});
}
}
2. Snackbar
widget.scaffoldKey.currentState.showSnackBar(SnackBar(
content: Text("Created", textAlign:
TextAlign.center,),),
Does anyone know how I can position the snackbar in front of the bottom sheet
So I was able to solve this by just adding another Scaffold() to my Bottom sheet and passing it a new scaffold key
SnackBar has a property for this. It's called behavior, you could do this:
SnackBar(
behavior: SnackBarBehavior.floating,
...
SnackBarBehavior enum
floating → const SnackBarBehavior
This behavior will cause SnackBar to be shown above other widgets in
the Scaffold. This includes being displayed above a
BottomNavigationBar and a FloatingActionButton.
See material.io/design/components/snackbars.html for more details.
I solved by Set (padding from bottom to SnackBar) As much as the height of the (bottomSheet : height) .
In This Case I Have This bottomSheet:
bottomSheet: Container(
child: RaisedButton(...),
width: MediaQuery.of(context).size.width,
height: AppBar().preferredSize.height * 0.85,
),
And This snackBar:
_scaffoldKey.currentState.showSnackBar(SnackBar(
padding:EdgeInsetsDirectional.only(
bottom:AppBar().preferredSize.height * 0.85),
backgroundColor: Colors.red,
duration: new Duration(milliseconds: 3000),
content: Text('ETC..'),
));
You can achieve this Simply by wrapping your BottomSheet widget with a Scaffold.
eg:
void _settingModalBottomSheet(context, stream, scaffoldKey ) {
if (_availableRides.length == 0) {
return null;
} else {
return scaffoldKey.currentState.showBottomSheet((context) {
return Scaffold(
body: Column(
children: Widgets;
})
);
}
}
I arrived on pretty decent solution. I wrapped my bottom sheet in a Scaffold, but I added it as the bottomSheet parameter. While adding the Scaffold, some trailing background will be added, so I just made its background transparent.
Scaffold(
backgroundColor: Colors.transparent,
bottomSheet: ...,
)
This is a working solution according to documentation.
https://docs.flutter.dev/cookbook/design/snackbars
This example works with bottom sheets as well.
Initialize ScaffoldMessengerKey.
Wrap your component widget with Scaffold.
Wrap Scaffold with ScaffoldMessenger.
Add key scaffoldMessengerKey to ScaffoldMessenger
Call method scaffoldMessengerKey.currentState?.showSnackBar(SnackBar());
Example:
final scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
// Any widget with button.
// (Bottom sheet also) - root widget must be ScaffoldMessenger.
ScaffoldMessenger(
key: scaffoldMessengerKey,
child: Scaffold(
body: Container(
child: ElevatedButton(
style: raisedButtonStyle,
onPressed: () {
scaffoldMessengerKey.currentState?.showSnackBar(
//SnackBar design.
SnackBar(
backgroundColor: Colors.white,
elevation: 8,
content: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5),
),
child: Text(
'Simple snackbar text.',
style: FlutterFlowTheme.of(context).bodyText1
.override(fontFamily: 'Rubik',
fontWeight: FontWeight.w300,
lineHeight: 1.5,
),
),
action: SnackBarAction(
label: 'Undo',
onPressed: () {
// Some code to undo the change.
},
),
duration: Duration(seconds: 5),
behavior: SnackBarBehavior.floating,
},
child: Text('Open snackbar over bottom sheet!'),
); //ElevatedButton
); //Container
); //Scaffold
); //ScaffoldMessenger
Note:
With this approach you don't need to pass BuildContext.
If you don't want to register ScaffoldMessengerKey.
You can show SnackBar like this: ScaffoldMessenger.of(context).showSnackBar(SnackBar());
I solved this by changing bottomSheet to bottomNavigationBar since the floating snack bar solution didn't work for me.
you can use flushbar package. I think this is the better option if need to use with bottomSheet.
context should be your page's context, not bottomsheet context
any event inside bottomSheet
CustomFlushBar().flushBar(text: 'Thank you for your payment!', context: context,duration: 2);
CustomFlushBar class
class CustomFlushBar {
void flushBar({int duration, #required String text, Color iconColor, IconData iconData, Color backgroundColor, #required BuildContext context}) async {
await dismiss();
Flushbar(
margin: EdgeInsets.all(8),
borderRadius: 8,
backgroundColor: backgroundColor ?? Palette.greenButton,
icon: Icon(iconData ?? Icons.done, color: iconColor ?? Palette.white),
flushbarStyle: FlushbarStyle.FLOATING,
message: text,
duration: Duration(seconds: duration ?? 3),
)..show(context);
}
Future<void> dismiss() async {
if (!Flushbar().isDismissed()) {
await Flushbar().dismiss();
}
}
}