I have a Custom BottomSheetDilaog in a flutter.
There are two ways this dialog can be open
1)Via Floating Button above Bottom navigation that is attached To HomeMainScreen
2)Via Button on HomeScreen Tab that is the first widget in Bottom navigation.
When a user clicks on the floating button the TextFieldForm Resize as the keyboards open.
But when it is open via HomeScreen Tab Button then Its root view is Resize and not the Bottom sheet Dialog.
showModalBottomSheet(
backgroundColor: foreground_color,
isScrollControlled: true,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(20.r))),
context: context,
builder: (builder) {
return AnimatedPadding(
duration: const Duration(milliseconds: 250),
curve: Curves.easeInOutSine,
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: SafeArea(
maintainBottomViewPadding: true,
child: Wrap(
children: [
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
How to make sure that in both cases it resize as expected when the keyboard is opened.
Sample Code
https://github.com/parmarravi/bottom_sheet_bug
Related
I have an app with two features, that have routes such as:
/feature1
/feature1/a
/feature2
/feature2/a
/feature2/a/b
/feature2/c
I can use GoRouter and its ShellRoute to switch between these one at a time using context.goNamed('feature2'), which would replace the entire screen with feature 2 (when tapping a tab in a tab bar for example). Here's a diagram of just the top level routes using tabs:
However, I would like to have an overview style menu which displays multiple destinations at once, so the user can see where they will be going before they go there (for example the preview page tabs in a mobile web browser). Here's a diagram:
and then tapping on either of the two pages would make them full screen:
Pressing the menu button at the bottom would return you to the overview menu page.
One way I have thought about solving this would be to make static preview images out of the routes when the menu button is tapped, and just display the previews. But these won't be live, and I would like a more elegant approach that actually displays the live contents of the route if possible.
Another way I have thought about solving this would be to use a top level GoRouter and then two descendant GoRouters each containing just one branch of the routes. I'm not sure if multiple GoRouters would lead to problems with things like if I wanted to context.go() to another branch.
If the ShellRoute.builder gave me access to all of the child page's widgets, I could display them however I wanted, but it just provides a single child.
I have not worked with 'go_router' or 'ShellRoute.builder', but I like to make custom animated widgets like this for apps. It's also hard to explain how it would work in your app, but here is my take on this.
Try copy pasting this in an empty page. I have written some notes in code comments that might help explain things a little bit. And, this is not perfect but with more polishing according to the needs it could work.
class CustomPageView extends StatefulWidget {
const CustomPageView({Key? key}) : super(key: key);
#override
State<CustomPageView> createState() => _CustomPageViewState();
}
class _CustomPageViewState extends State<CustomPageView> {
// Scroll Controller required to control scroll via code.
// When user taps on the navigation buttons, we will use this controller
// to scroll to the next/previous page.
final ScrollController _scrollController = ScrollController();
// Saving screen width and height to use it for the page size and page offset.
double _screenWidth = 0;
double _screenHeight = 0;
// A bool to toggle between full screen mode and normal mode.
bool _viewFull = false;
#override
void initState() {
super.initState();
// Get the screen width and height.
// This will be used to set the page size and page offset.
// As of now, this only works when page loads, not when orientation changes
// or page is resized. That requires a bit more work.
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
_screenWidth = MediaQuery.of(context).size.width;
_screenHeight = MediaQuery.of(context).size.height;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
// 'Column' to wrap the 'Body' and 'BottomNavigationBar'
body: Column(
children: [
// 'Expanded' to take up the remaining space after the 'BottomNavigationBar'
Expanded(
// A 'Container' to wrap the overall 'Body' and aligned to center.
// So when it resizes, it will be centered.
child: Container(
alignment: Alignment.center,
// 'AnimatedContainer' to animate the overall height of the 'Body'
// when user taps on the 'Full Screen' button.
child: AnimatedContainer(
duration: const Duration(milliseconds: 500),
height: _viewFull ? 200 : _screenHeight,
// A 'ListView' to display the pages.
// 'ListView' is used here because we want to scroll horizontally.
// It also enables us to use 'PageView' like functionality, but
// requires a bit more work, to make the pages snap after scrolling.
child: ListView(
controller: _scrollController,
scrollDirection: Axis.horizontal,
children: [
// A 'Container' to display the first page.
AnimatedContainer(
duration: const Duration(milliseconds: 500),
width: _viewFull ? (_screenWidth / 2) - 24 : _screenWidth,
margin: _viewFull ? const EdgeInsets.all(12) : const EdgeInsets.all(0),
color: Colors.blue,
),
// A 'Container' to display the second page.
AnimatedContainer(
duration: const Duration(milliseconds: 500),
width: _viewFull ? (_screenWidth / 2) - 24 : _screenWidth,
margin: _viewFull ? const EdgeInsets.all(12) : const EdgeInsets.all(0),
color: Colors.yellow,
),
],
),
),
),
),
// 'BottomNavigationBar' to show the navigation buttons
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// 'Feature 1' button
GestureDetector(
onTap: () {
// Scroll to the first page
_scrollController.animateTo(
0,
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOut,
);
},
child: Container(
height: 60,
alignment: Alignment.center,
color: Colors.red,
padding: const EdgeInsets.all(12),
child: const Text('Feature 1'),
),
),
// 'Feature 2' button
GestureDetector(
onTap: () {
// Scroll to the second page
_scrollController.animateTo(
_screenWidth,
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOut,
);
},
child: Container(
height: 60,
alignment: Alignment.center,
color: Colors.green,
padding: const EdgeInsets.all(12),
child: const Text('Feature 2'),
),
),
// 'Full Screen' button
GestureDetector(
onTap: () {
// Toggle between full screen mode and normal mode
setState(() {
_viewFull = !_viewFull;
});
},
child: Container(
height: 60,
alignment: Alignment.center,
color: Colors.purple,
padding: const EdgeInsets.all(12),
child: const Text('View Full'),
),
),
],
),
],
),
);
}
}
I have a dialog I am trying to wrap the content in the dialog however I am having few problems
1)Use of wrap does not guarantee that content is in the alert dialog box
2)alignment of content is not center.
I have tried all possible alignment and it does not work.
While using column stretch the widget I thought maybe using wrap will work . But it does not.
Any solution?
With Column
With Colored Container in a wrap to check the issue and with size box with defined width of display * 0.25 so that text does not go away from screen
Code
showDialog(
barrierDismissible: false,
barrierColor: Colors.black26,
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
contentPadding: EdgeInsets.all(20),
content: Wrap(
direction: Axis.vertical,
alignment: WrapAlignment.spaceAround,
runAlignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
runSpacing: 10,
children: [
Lottie.asset(
Constants.location_anim,
height: displaySize.height * 0.25,
repeat: true,
reverse: true,
animate: true
),
Text(locationMsgTextView,softWrap: true,),
getLocationDeniedWidget(context,state),
],
),
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
);
},
);
});
I created a form that once submitted shows a dialog to the user, like this:
.....
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) {
return AlertDialog(
contentPadding: EdgeInsets.all(0),
content: Container(
child: Wrap(
children: [
Container(
width: double.infinity,
margin: EdgeInsets.all(0),
padding: EdgeInsets.all(20),
decoration: BoxDecoration(gradient: linearGradientCustom),
child: Column(
children: [
.....
I am not using any button or icon to close the dialog, since the dialog box is quite small and it just makes sense to simply tap away from it to dismiss it.
The issue is that I need to redirect the users to a different route on dismiss, instead of simply popping the dialog context.
How can I achieve this?
Thanks a lot.
You can use .then like this
await showDialog(
....//Your Dialog Code
).then((val){
// reditect to specific route
});
Click the action of appBar to expand a pop-up window below, and click action again to shrink the pop-up window.Or is there a plugin recommendation with such an effect?
If view of you is simple view, you can use simple popup, see this tutorial.
If view of you complex more, you have to custom it. You need create Widget container both menu and expand part, custom display like main page. Then show it as dialog.
showGeneralDialog(
context: context,
barrierColor: Colors.black12.withOpacity(0.6), // background color
barrierDismissible: false, // should dialog be dismissed when tapped outside
barrierLabel: "Dialog", // label for barrier
transitionDuration: Duration(milliseconds: 400), // how long it takes to popup dialog after button click
pageBuilder: (_, __, ___) { // your widget implementation
FocusScope.of(context).requestFocus(_focusNodeCity);
return SafeArea(
child: Material(
color: Colors.transparent,
child: SizedBox.expand( // makes widget fullscreen
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
],
),
),
),
);
},
);
i am using showModalBottomSheet and given the height of 90% at start. There are two tabs(repeat and onetime) inside bottomsheet, repeat tab has a lot of contents and it is showing perfectly fine with 90% height. But when i tab on onetime tab, i want to decrease the size of bottomsheet to 40% because it does not have more content in it and it does not look nice. But i am unable to change dynamically the height of bottom sheet on pressing onetime tab button.
Can anyone help me how can i achieve this functionality in flutter?
You can use the following code by replacing PutYourWidgetHere() with your custom widget.
void showBottomSheet() {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (BuildContext context) {
return SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: PutYourWidgetHere(),
));
});
}
dynamically the height and make content in center
showCupertinoModalBottomSheet(
expand: false,
enableDrag: true,
isDismissible: true,
barrierColor: ColorUtils.disableBackground.withAlpha(128),
backgroundColor: ColorUtils.enableBackground,
topRadius: Radius.circular(SizeUtils.minBlock * 4),
context: globalKey.currentState!.context,
builder: (builder) {
return Padding(
padding: EdgeInsets.all(SizeUtils.minBlock * 8),
child: Container(
constraints: BoxConstraints(
minHeight: SizeUtils.blockHeight * 30,
maxHeight: SizeUtils.blockHeight * 60),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [SingleChildScrollView(child: widget)])));
});