Static Widgets with a PageView - flutter

Is there a way to make a few widgets static upon a PageView change?
I know I can make one widget static by wrapping the Scaffold within a Container, and have that Container have something like a decoration, but I don't know how to add more widgets that do not change when a page changes.
I have a few widgets that change when the page view changes, but then I want to have, say a Button below those widgets that stay still, but
if I put the same Button in every widget, it will swipe through and show two buttons when I change the page momentarily.

I just figured it out, I thought the PageView can only be assigned to the body property of a Scaffold, but wrapping it within a Column like this works. So just add the static widgets within the Column!
return Container(
decoration: BoxDecoration(), // For background.
),
child: Scaffold(
backgroundColor: Colors.transparent,
body: Column(
children: [
Flexible(child: pageView),
// Static Widgets here!
],
),
),
);

Related

How to make GestureDetector blocked by child in Flutter

I have found that GestureDetector can have different hit test behaviours:
deferToChild to work on non-empty space
opaque and translucent to work on all space
But how can I make GestureDetector work only on empty space?
GestureDetector(
onTap: fallbackHandler, // called only when no children hit
child: Stack(
children: manyOtherGestureDetectors, // should keep working, not blocked by the parent
),
)
One solution could be putting the GestureDetector at the bottom layer of a Stack:
Stack(
children: [
GestureDetector(
onTap: fallbackHandler,
),
...manyOtherGestureDetectors,
],
)
But it becomes hard to size (shrink) the backgourd GestureDetector as it is no longer a parent. One way to shrink it is to use IntrinsicHeight, but IntrinsicHeight does not work with TextField.
So is it possible to create a GestureDetector that:
Is behind (blocked by) all other GestureDetectors;
Shrinks its size to exactly wrap all other GestureDetectors?
Not sure on this, make a try.
You can use the IgnorePointer widget to block any gesture for it's child.
Wrap the child with IgnorePointer and make ignoring: true,
Ex: GestureDetector(
onTap: fallbackHandler, // called only when no children hit
child: IgnorePointer(
Stack(
children: manyOtherGestureDetectors, // should keep working, not blocked by the parent
),
`ignoring: true,`
),
)

Flutter - Bottom Overflowed Issue when Keyboard is Presented

I have a view that contains a Column of Widgets. One of the Widgets contains a button that will open a bottom sheet. Within that bottom sheet, a user can tap a TextField and open the keyboard which will keep the bottom sheet above the keyboard.
When I do this as-is, I get Bottom Overflowed by XXX Pixels. The yellow box is behind my bottom sheet, right above the keyboard.
I have tried wrapping the Column in a SingleChildScrollView but when I do that all of the Widgets in my Column disappear.
I have also tried wrapping in a Scaffold & that did not work either:
example:
Scaffold(
resizeToAvoidBottomInset: false, // tried setting to true as well
body: Column...
Any suggestions?
Here's some of the base setup:
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildWidget1(),
_buildWidget2(),
_buildWidget3(),
// When wrapped in a SingleChildScrollView
// this seems to be making everything in the column
// disappear...
Expanded(child: Container()),
etc.
],
);
}
void _bottomSheetButtonPressed(context) {
showModalBottomSheet(
barrierColor: Colors.transparent,
backgroundColor: Colors.transparent,
context: context,
isScrollControlled: true,
builder: (context) {
return Padding(
padding:
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(24),
topRight: const Radius.circular(24),
),
),
child: _showBottomSheetItemsWidget(),
),
);
},
);
}
The colors are transparent just so I can see what is happening behind the bottom sheet.
So, with this I am getting the Bottom Overflowed issue... and that is what I am trying to resolve.
Update:
After further debugging, I do see what I believe is making all my Widgets disappear. I have an Expanded Widget that has a child of Container to separate some of my Widgets.
The correct solution is indeed to wrap what you see into a scrollable widget such as SingleChildScrollView. But this can happen if and only if the contents of your scrollable widgets aren't infinite.
Indeed, the reason your widget simply "disappear" is an internal widget that forces infinite height (in this case, the Expanded widget), while the parent do not force a maximum height (the SingleChildScrollView), since it expects any number of widgets to be displayed. This causes an intrinsic / conceptual error (if you think about it) and therefore the framework throws an error.
It kinda depends on what you want to achieve, but as a rule of thumb in cases like this chances are that you want to wrap your scrollable widgets inside a SizedBox / Container / ConstrainedBox, so that you specify a height and therefore you force it to be not infinite.
In that case, your child widgets can use the Expanded logic with no issues.
Let me know if that helps.

Flutter Inherited Custom AppBar disappear on TextField tap

I'm using a custom appBar and a bottomNavigationBar in a Scaffold, per below code:
return Scaffold(
appBar: LogoAppBar(),
drawer: topDrawer(),
body: _pageOptions[_selectedTab],
bottomNavigationBar: BottomNavigationBar(...)
When I navigate via the BottomNavigationBar the custom AppBar sticks at the top of the new screen, just like I want it to.
However, when I navigate and thereafter tap on a TextField on the new screen to enter some text, the inherited AppBar automatically disappear (when the keyboard shows up).
The full code for this screen is rather long and therefore rather impractical to post here, but it basically boils down to the following:
return Scaffold(
backgroundColor: Colors.white,
body: Column(
children: [
Container(
Column(
children: [
DropDownButton(...),
TextField(...), // with a textSearchController
],
Expanded(
child: ListViewBuilder(...) // showing a list based on the search
Is there any way to make the AppBar from the inherited class stick without putting a new appBar in the Scaffold in the class I navigated to?
Try removing Scaffold as you are already calling it once in the main screen.
return Column(
children: [
Container(
Column(
children: [
DropDownButton(...),
TextField(...), // with a textSearchController
],
Expanded(
child: ListViewBuilder(...)
Ujjwal's suggestion was incredibly helpful. I removed the Scaffold and unfortunately the problem persisted, but it made me realize that I had also wrapped the LogoAppBar() code in a Scaffold. Once I removed the Scaffold from the LogoAppBar() it all worked!

how to resize or move all the child widgets of stack when one of it's grandchild is input TextField in flutter

I have positioned(using Align) two child widgets within stack widget and one of it contains form TextField to take input. When I clicked to enter data, only it's parent widget is moved up on Keypad entered as in the below picture.
Is there any way to move/resize the child widgets of stack while entering data from keypad.
Source code:
return Scaffold(
body: Stack(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/playingboard2.jpg'),
fit: BoxFit.cover)),
child: null,
),
_buildSelfPlayer(), // Returns the widget with form input and other widgets
_buildBank(), // top center, shows two pictures of bank
],
),
);
I don't see another fix for this, while also making use of Stack widget.
So instead I'd suggest you to use Column widget wrapped inside a SingleChildScrollView. I tried it and it works as intended. The other children move up too along with the TextField, so maintaining the distance between them and not overlapping.
For the background image, you can wrap the Scaffold in a Container, use that image in the Column decoration and make the Scaffold's backgroundColor to Colors.transparent.

How to make Hero animation for two widgets

I need to make animation like Hero in two different widgets. Is that possible?
Widget a with image a and widget b with image a but widget a is inside a listview and widget b is full screen image(it hide listview)
It's very simple. You just need to wrap both widgets in a Hero widget using the same TAG property value. The snippet below is assuming you've a Image in a ListTile and after user clicks you show a new page with the same image but that image will be animated by Hero widget.
In list page the list items can be
ListTile(
leading: Hero(
tag: IMAGE_TAG, // must be the same in different pages
child: Image(image: AssetImage('you_asset_dir/yourImage.png')),
),
title: Text('Anything'),
onTap: () => // Just go to full screen page
);
In full screen page
Scaffold(
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Hero(
tag: 'IMAGE_TAG', // must be the SAME VALUE DEFINED IN list tile hero child widget.
child: Image(image: AssetImage('you_asset_dir/yourImage.png')),
),
),
);
OBS: The Hero tag property must be the same in different contexts but if you have a list with many items using Hero widget each Hero int the same context/page must have different tag values.
To deep dive concepts about Hero animations check the official doc