I would like to implement an AlertDialog using Flutter and fluent_ui for Windows. This is a progressive progress bar, so the percentage will change when some of my other code executes. My problem is that the Progress Bar does not extend until the end of the AlertDialog. Currently, the progress bar looks like below, set at progress of 50.
Edit: Below is the code I have tried
showDialog(
context: context,
builder: (context) {
return ContentDialog(
title: Text(title),
content: const Expanded(
child: ProgressBar(value: 50, strokeWidth: 10),
),
actions: [
const SizedBox(),
Button(
style: MyButtonStyles.dialogYes(),
child: const Text('OK', style: TextStyle(fontSize: 16.0)),
onPressed: () {
Navigator.pop(context);
}),
],
);
},
);
You can replace Expanded with SizedBox by providing infinity/ specific width.
Also, can be use SizedBox.fromSize.
ContentDialog(
title: Text("title"),
content: SizedBox(
width: double.infinity,
child: ProgressBar(value: 50, strokeWidth: 10),
),
Related
I'm trying to find a way to place an AdMob ad at the top of my widget tree. The best way I thought of doing this was to try to place it in the flexible space inside the appbar. The spacing isn't quite how I want it as the ad is appearing behind the title, leading, and trailing widgets on the appbar. Is there any way to move the ad up so it's not placed behind the content of the appbar? If not, is there a way I can place the ad outside the appbar and have it appear above a scaffold (tried wrapping the scaffold in the column to achieve this and didn't work)?
Image of appbar:
AppBar returnAppBarForHomePagesTest(
BuildContext context,
String page_header,
localUser local_user,
Function updateUserState,
bool using_default_image,
String profile_pic,
GlobalKey<ScaffoldState> scaffold_key,
BannerAd ad,
bool ad_loaded) {
return AppBar(
toolbarHeight: 100,
flexibleSpace: ad_loaded /// TRYING TO PLACE AD HERE
? Container(
child: AdWidget(
ad: ad,
),
width: ad.size.width.toDouble(),
alignment: Alignment.center,
)
: const CircularProgressIndicator(),
elevation: 0,
backgroundColor: HEADER_FOOTER_BACKGROUND_COLOR,
centerTitle: true,
title: Text(page_header,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: PRIMARY_PAGE_HEADER_SIZE,
color: Colors.white,
)),
leadingWidth: 35,
automaticallyImplyLeading: false,
leading: Transform.translate(
offset: const Offset(8, 0),
child: GestureDetector(
onTap: () {
globals.GlobalVars()
.navigatorKey
.currentState
?.pushNamed(EditProfile.route_name, arguments: local_user)
.then((value) {
if (value != null) {
updateUserState(value);
}
});
},
child: CircleAvatar(
backgroundImage: using_default_image
? AssetImage(profile_pic) as ImageProvider
: NetworkImage(profile_pic),
radius: 5,
),
),
),
actions: [
IconButton(
icon: const Icon(
Icons.settings_outlined,
color: Colors.white,
size: 35,
),
onPressed: () {
scaffold_key.currentState?.openDrawer(); // do something
},
)
],
);
}
The easiest way would be to wrap your Scaffold in a Stack
return Stack(
children: [
Scaffold(
appBar: AppBar(
...
),
body: ...
),
if (showAd)
//Your ad here
Container(
height: kToolbarHeight,
width: MediaQuery.of(context).size.width,
child : ...
),
],
);
Here is a working gist you can try
I have a row which includes 3 icons, but one of them needs to be shown if notes have been added, but hidden if there are no notes.
I tried to use Visibility but couldn't get it right. If there are no notes, I need to use a SizedBox() so everything else stays aligned correctly.
What's the right way to do this?
Expanded(
flex: 14,
child: Center(
child: GestureDetector(
onTap: () {
print(data[index].rosterId);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ShiftsForRoster(
rId: data[index].rosterId,
),
),
);
},
child: Icon(Icons.note_alt_outlined, size: 35, color: kMainColor80),
),
),
),
I can't see in your code snippet, how you check if you have notes or not. I used a bool "notestExist", check if it's true and show your icon, else show an empty Container. You could also do something like notes.length != 0
Expanded(
flex: 14,
child: notesExist ? Center(
child: GestureDetector(
onTap: () {
print(data[index].rosterId);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ShiftsForRoster(
rId: data[index].rosterId,
),
),
);
},
child: Icon(Icons.note_alt_outlined, size: 35, color: kMainColor80),
),
) : Contaniner()
),
I am using Cards in Flutter and want Progress Indicator at the left bottom position for 2 seconds while Tap on the card so that another page load successfully.
Does anyone know how to add?
Container(
height: 130,
child: Card(
child: Row(
children: <Widget>[
Expanded(
child: ListTile(
title: Text(
'My card Location',
style: TextStyle(
fontSize: 15, fontWeight: FontWeight.w700),
),
leading: Icon(Icons.setting),
// color: Colors.blueAccent, size: mediumIconSize),
trailing: Icon(Icons.keyboard_arrow_right),
selected: true,
onTap: () async {
// I try this one but not working
// Flushbar(
//
// showProgressIndicator: true,
// duration: Duration(seconds: 2),
// );
getDetails().then((myCardlocations) {
Navigator
.of(context)
.pushNamed('/myCardlocations',
arguments: ObjectLocations(locations, 'myCardlocations'));
}
);
}
),
),
],
),
),
),
You can do something like this using Stack and CircularProgressIndicator..
class _MyWidgetState extends State<MyWidget> {
bool isLoading = false;
#override
Widget build(BuildContext context) {
return Container(
height: 130,
child: Stack(
children: [
Container(
height: 130,
child: Card(
child: Row(
children: <Widget>[
Expanded(
child: ListTile(
title: Text(
'My card Location',
style: TextStyle(
fontSize: 15, fontWeight: FontWeight.w700),
),
leading: Icon(Icons.settings),
// color: Colors.blueAccent, size: mediumIconSize),
trailing: Icon(Icons.keyboard_arrow_right),
selected: true,
onTap: () async {
setState(() {
isLoading = true;
});
getDetails().then((myCardLocations) {
setState(() {
isLoading = false;
});
// navigation code here
});
},
),
),
],
),
),
),
Align(
alignment: Alignment.bottomLeft,
child: isLoading
? Padding(
padding: EdgeInsets.fromLTRB(15,0,0,15),
child: SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(),
),
)
: SizedBox(),
),
],
),
);
}
}
Edit:
Looks like I misunderstood the question a bit. Specifically, the place where to show the progress indicator. Anyways, if you get the idea, you can put the indicator at a different place as per your requirement.
There are certain things, which I would like to mention before I give the actual answer.
Read about Flutter.delayed constructor, very useful thing to make some thing wait for a while and do the operation by providing Duration. Whatever you want to do after that duration, it will implement in the callback function
Future.delayed(Duration(seconds: your_time, (){
//it will perform this operation after that much of seconds
}));
You can always show/hide a Widget using bool value, and make changes accordingly
Use a column and Add the LinearProgressIndicator at the end of the Widget. Show/hide it based up on the data
Also, use MediaQuery to give out the height. It is more efficient way of giving the dimensions according to all phone size. Like match-parent in Android Studio. Do the math accordingly, I have shown in the code also
Column(
children: [
Row(),
bool val ? LinearProgressIndicator() : Container() // Container() is nothing but an empty widget which shows nothing
]
)
Some heads up: I have not used getData, since it is not defined properly but you can call it the in function which I will show you in the code, that is pageTransit(). Follow the comments and you are good to go
class _MyHomePageState extends State<MyHomePage> {
// this takes care of the show/hide of your progress indicator
bool _showProgress = false;
// this takes care of the operation
void pageTransit(){
// first show when the ListTile is clicked
setState(() => _showProgress = true);
Future.delayed(Duration(seconds: 2), (){
// hide it after 2 seconds
setState(() => _showProgress = false);
// do the page trnasition here
//getDetails().then((myCardlocations) {
//Navigator.of(context).pushNamed('/myCardlocations',
//arguments: ObjectLocations(locations, 'myCardlocations'));
//}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
height: MediaQuery.of(context).size.height * 0.1,
child: Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// use your items here, based upon the bool value show hide your
// progress indicator
Row(
children: <Widget>[
Expanded(
child: ListTile(
title: Text(
'My card Location',
style: TextStyle(
fontSize: 15, fontWeight: FontWeight.w700),
),
leading: Icon(Icons.settings),
// color: Colors.blueAccent, size: mediumIconSize),
trailing: Icon(Icons.keyboard_arrow_right),
selected: true,
onTap: () => pageTransit()
)
)
]
),
// show/hide in the card
_showProgress ? LinearProgressIndicator() : Container()
]
)
)
)
);
}
}
Result
Look at the ProgressIndicator, it remains there for 2 seconds, and then goes away
1. You need to define a GlobalKey for the Scaffold so that you can use a SnackBar (you can define the GloablKey in your page's State).
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
2. You need to set the key for the Scaffold.
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
...
3. You need to wrap the Card with a GestureDetector and set the onTap function to call showLoading which shows a SnackBar on the bottom of the screen. Call your getDetails function in the showLoading. Full code (except the define key step):
void _showLoading() {
_scaffoldKey.currentState.showSnackBar(new SnackBar(
duration: new Duration(seconds: 2),
content: new Row(
children: <Widget>[
new CircularProgressIndicator(),
new Text("Loading...")
],
),
));
// call to your getDetails and its steps should be here
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text("My app"),
),
body: Center(
child: GestureDetector(
child: Card(
child: Row(children: <Widget>[
Expanded(
child: ListTile(
title: Text(
'My card Location',
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w700),
),
leading: Icon(Icons.settings),
// color: Colors.blueAccent, size: mediumIconSize),
trailing: Icon(Icons.keyboard_arrow_right),
selected: true,
)),
])),
onTap: () => _showLoading(),
)),
);
}
}
Note: you can also style the SnackBar.
Result:
Consider I have two views, Orders view and Order Details view.
I would like to display an overlay (small section at the bottom) on Orders view, and when user selects an Order, we display Details view, but I want to continue to show the overlay, I want push route change so the back button etc work.
Is this doable
Use showModalBottomSheet
more examples: modal_bottom_sheet_demo persistent_bottom_sheet_demo
exam:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Modal bottom sheet'),
),
body: Center(
child: RaisedButton(
child: const Text('SHOW BOTTOM SHEET'),
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
child: Padding(
padding: const EdgeInsets.all(32.0),
child: Text(
'This is the modal bottom sheet. Tap anywhere to dismiss.',
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).accentColor, fontSize: 24.0),
),
),
);
},
);
},
),
),
);
}
I'm trying to show bottom sheet and let user pick choice. I did like so
showModalBottomSheet(
context: context,
builder: (builder) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new ListTile(
leading: new Icon(Icons.image),
title: new Text('From gallary'),
),
new ListTile(
leading: new Icon(Icons.camera_alt),
title: new Text('Take video'),
),
],
);
});
However it barely visible because of bottom navigation bar.
It looks like this.
I want to implement minimum height bottom sheet coming up from top edge of the bottom navigation bar. How can I achieve this?
The showModalBottomSheet has useRootNavigator which is by default false. The documentation says:
The useRootNavigator parameter ensures that the root navigator is used to
display the [BottomSheet] when set to true. This is useful in the case
that a modal [BottomSheet] needs to be displayed above all other content
but the caller is inside another [Navigator].
I think that is solution to your problem.
This could be a solution. Ensure that your main UI is a Stack.
Widget _buildOffstageMenu() => AnimatedPositioned(
duration: Duration(milliseconds: _showUpOffstageMenuDuration),
width: MediaQuery.of(context).size.width,
height: _offstageMenuHeight,
bottom: !_showMenu ? _bottomMenuOffset : 0.0,
curve: Curves.easeInOutExpo,
child: InkWell(
child: Container(
height: _offstageMenuHeight,
color: Colors.white,
child: Column(
children: [
/// your options
],
),
),
onTap: () {
setState(() {
_showMenu = !_showMenu;
});
},
),
);
So in the end you will have something like this
Stack(
children: [
/// your widgets
_buildOffstageMenu(),
],
)
Instead of Column try wrapping children with ListView and make sure shrinkWrap: true,
showModalBottomSheet(
context: context,
builder: (builder) {
return ListView(
shrinkWrap: true,
children: <Widget>[
new ListTile(
leading: new Icon(Icons.image),
title: new Text('From gallary'),
),
new ListTile(
leading: new Icon(Icons.camera_alt),
title: new Text('Take video'),
),
],
);
});