I have this design, The first section in the red box is fixed height size, and The second section is the dynamic height (ListviewBuilder) which changed the content based on the tabBar.
My question is How can I use the TabBar view inside the scrollable widget (custom scroll view/listview etc..)
the solution That I currently found is to use a customScrollView and use SliverFillRemaining like that
SliverFillRemaining(
child: TabBarView(
children: [],
),
),
but that adds extra white space at the bottom of the list and I can't remove it by
making hasScrollBody property false
You could probably achieve what you want with this kind of template :
Scaffold(
body: Column(
children: [
Container(
height: MediaQuery.of(context).size.height * .33,
child: Container(/* Content of the first section */),
),
Expanded(
child: DefaultTabController(
length: 2,
child: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Container(
height: 50,
child: TabBar(
tabs: [Text("Guest"), Text("Service")],
),
),
),
SliverFillRemaining(
child: TabBarView(
children: [
// Your ListView Builder here
],
),
),
],
),
),
),
],
),
);
Seeing the bit of code you posted, it is probably close to what you already have but after test it doesn't adds extra white space at the bottom.
If it continue to display the same behavior, adding a little more context could help us provide a more accurate answer.
Related
I am rendering a standard Table inside a GridView, inside a Flex inside a Row. The 2nd row of the table includes a Button.
When the contents of the first row of the table are above a certain size the clickable region of the button begins to cut off, missing entirely over a certain size.
Note: this is using Flutter Web, I have not tested on Mobile/Desktop.
I have created a minimal reproducible example in an attempt to isolate all logic.
Widget _render() {
return Row(mainAxisSize: MainAxisSize.max, children: [
SizedBox(
width: 900,
height: 900,
child: GridView.count(
crossAxisCount: 2,
children: <Widget>[
Table(border: TableBorder.all(), children: <TableRow>[
TableRow(
children: <Widget>[
TableCell(
child: Text(''),
),
TableCell(
child: SizedBox(
height:
440, //The clickable region of the button begins to be cut off around 430, and stops altogether by 450
))
],
),
TableRow(children: <Widget>[
TableCell(
child: Text(""),
),
TableCell(
child: TextButton(
onPressed: () => {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Hi Button"))),
},
child: Text("Hi"))),
])
]),
],
),
),
]);
}
What is causing this effect? I am assuming it is some interaction between the visible container and the Table.
Edit: as suggested by #pskink rendered with debugPaintSizEnabled flag which highlights the problem perfectly. However; how would you fix?
as you can see at the image above, I have a red container stick on the top (right below the app bar). here is the code I use
CustomScrollView(
slivers: [
SliverAppBar(),
_buildStack(),
]
),
Widget _buildStack() {
return SliverStack(
children: [
// I have other widgets here ..
SliverPositioned(
bottom: 0, // <-- I have set the bottom to be zero
child: SliverToBoxAdapter(
child: _buildRedBox(),
),
],
)
}
Widget _buildRedBox() {
return Container(
width: double.infinity,
height: 50,
color: Colors.red,
);
}
I am using sliver tool package so I can access SliverStack and SliverPositioned.
as you can see, I have set the bottom to be zero. but the red box is still on the top. I need to make the red box at the bottom of the screen inside my SliverStack. how to do that ?
Use SliverFillRemaining widget instead of SliverPositioned widget.
SliverFillRemaining will automatically size itself to fill the space between the bottom of the last list item and the bottom of the viewport
SliverFillRemaining(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
_buildRedBox(),
],
),
),
I have a image slider in flutter where I want to vertically center the carousel. I'm using carousel_slider. And this here is my code:
Widget _buildItems(BuildContext context) {
return Column(
children: <Widget>[
appBar(context),
Center(
child: CarouselSlider(
options: CarouselOptions(
enlargeCenterPage: true,
enableInfiniteScroll: false,
autoPlay: false,
),
items: widget.recipeStepsList!
.map(
(e) => ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Container(
child: Text(
e.name!,
style: TextStyle(color: Colors.red),
),
),
Image.network(
e.stepThumbnailLink!,
width: 1000,
height: 200,
fit: BoxFit.cover,
),
],
),
),
)
.toList(),
),
),
],
);
}
As you can see, I've already wrapped everything inside a Center but this is the outcome of my code:
The only reason the back button is in place because it has a padding of 10. But since I'm building this application for all types of screens I need to keep the image slider exactly in the center.
The carousel is not coming in the center, since your Center widget is not actually taking up the full space and this is because it is inside a Column.
For widget like Row and Column, you can use Expanded widget to make any child take up the remaining space.
So, for your case, just wrap your Center inside an Expanded.
Here is the linkk to full working code.
Result,
Ignore the overflow warning, since that is happening because the carousel package is squishing view while scrolling.
I need to fix a minimum width to my Column Widgets. Inside each of them, I have Text Widgets which can be very short or very long. I need to fix a minimum width to them in order to have an acceptable size of Column even if the text is short. The other Column need obviously to adapt himself.
Row(children: [
Column(
children: [
Container(
constraints: BoxConstraints(minWidth: 80), // do not work
child: Text("short text"),
),
],
),
Column(
children: [
Container(
constraints: BoxConstraints(minWidth: 110), // do not work
child: RichText(
text: TextSpan(
text:"very very longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg text")),
),
],
),
],
)
There's probably a dozen ways to do what you want. And likely none of them straightforward or easy to understand. (The subject of constraints & sizes is quite complicated. See this constraints page for more examples & explanations.)
Here's one potential solution.
This will set a minimum width for the blue column (based on stepWidth), but will expand/grow if the text (child) inside wants to.
The yellow column will resize to accommodate the blue column.
class ExpandedRowPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Expanded Row Page'),
),
body: SafeArea(
child: Center(
child: Row(
children: [
IntrinsicWidth(
stepWidth: 100,
// BLUE Column
child: Container(
color: Colors.lightBlueAccent,
child: Column(
children: [
//Text('Short'),
Text('shrt')
],
)
),
),
// YELLOW Column
Flexible(
child: Container(
alignment: Alignment.center,
color: Colors.yellow,
child: Column(
children: [
Text('Very lonnnnnnnnnnnnnnnnnnnnnnnnnnnng texttttttttttttt'),
],
)
),
)
],
)
),
),
);
}
}
You could do the above without a Flexible yellow column, but a very long text child would cause an Overflow warning without a Flexible or Expanded wrapping widget.
A Row widget by itself has an infinite width constraint. So if a child wants to be bigger than screen width, it can, and will cause an overflow. (Try removing Flexible above and rebuild to see.)
Flexible and Expanded, used only inside Row & Column (or Flex, their superclass), checks screen width and other widgets inside a Row, and provides its children with a defined constraint size instead of infinite. Children (inside Flexible/Expanded) can now look up to parent for a constraint and size themselves accordingly.
A Text widget for example, will wrap its text when it's too wide for constraints given by Flexible/Expanded.
use FittedBox();
suppose Example:
Row(
children: [
Column(
children: [
Container(
constraints: BoxConstraints(minWidth: 80), // do not work
child: Text("short text"),
),
],
),
Column(
children: [
Container(
constraints: BoxConstraints(minWidth: 110), // do not work
child:
FittedBox(
child: RichText(
text: TextSpan(
text:
"very very longggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg text")),
),
),
],
),
],
);
What is the best way to build a "nested bottom sheet" which behaves like this:
https://dribbble.com/shots/14139422-Mobile-banking-app-interactions?
Do I have to use NestedScrollView or CustomScrollView, or a completely different approach?
Update :
This is my result using SlidingUpPanel, but I still have two problems:
When sliding up the panel, the green and red containers stay behind the panel and do not scroll out of view at the top.
In landscape mode the containers are higher than the device, so this approach does not work. I need the panel to be attached to the bottom of the containers, so it is only visible when scrolling down.
Code:
SafeArea(
child: Scaffold(
body: SlidingUpPanel(
minHeight: MediaQuery.of(context).size.height - 479,
maxHeight: MediaQuery.of(context).size.height - 79,
panel: SingleChildScrollView(
child: Column(
children: [Text('Sliding Panel')],
),
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 100,
color: Colors.green,
),
Container(
height: 300,
color: Colors.red,
)
],
),
),
),
),
);
Result:
I believe there is a Widget for what you want to do, since there is a widget for everything in Flutter. here is the link of the package
NOTE : you can also set minimum height of the widget when collapsed in order to control how much of the widget you can show when it is collapsed.
And here is the demo :