Flutter add bottom margin to Stack - flutter

I am trying to extend Stack a little bit down to create room for "All caught up" text.
Here is my code;
return Stack(
children: [
buildListView(scrollController),
buildBackToTop(scrollController, backtoTop),
buildBottomReached(isLastIndex),
],
);
Widget buildBackToTop(ScrollController scrollController, bool backtoTop) {
if (backtoTop) {
return Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: FloatingActionButton.extended(
onPressed: () {
scrollController.animateTo(0,
duration: const Duration(milliseconds: 200),
curve: Curves.linear);
},
label: const Text("Back to Top"),
),
),
);
} else {
return const SizedBox();
}
}
Widget buildBottomReached(bool isLastIndex) {
if (isLastIndex) {
return const Align(
alignment: Alignment.bottomCenter,
child: Text(
"All caught up 🎉",
style: TextStyle(
color: Colors.blue, fontWeight: FontWeight.bold, fontSize: 20.00),
),
);
} else {
return const SizedBox();
}
}
Widget buildListView(ScrollController scrollController) {
return ListView.builder(
controller: scrollController,
itemCount: 50,
itemBuilder: (context, index) {
return SizedBox(
width: 20,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 20,
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
color: Colors.grey[100],
),
child: Center(
child: Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Index $index"),
),
),
),
),
),
);
},
physics: const BouncingScrollPhysics());
}
When I do following,
return Stack(
children: [
Padding(
padding: const EdgeInsets.only(bottom: 30),
child: buildListView(scrollController),
),
buildBackToTop(scrollController, backtoTop),
buildBottomReached(isLastIndex),
],
);
This is desired but it adds whitespace to bottom all the time,
Is there a way to do this?

another valid solution for your case is to expand the Stack to the screen size, then align your widgets with the Align widget like this:
final mq = MediaQuery.of(context);
return ConstrainedBox(
constraints: BoxConstraints(
maxHeight: mq.size.height,
minHeight: mq.size.height,
maxWidth: mq.size.width,
minWidth: mq.size.width,
),
child: Stack(
fit: StackFit.expand,
children: [
buildListView(scrollController),
Align(
alignment: Alignment.bottomCenter,
child: buildBackToTop(scrollController, backtoTop),
),
buildBottomReached(isLastIndex),
],
),
);

Based on your UI. try Column widget instead of Stack.
return Column(
children: [
Expaneded(child: buildListView(scrollController)),
buildBackToTop(scrollController, backtoTop),
buildBottomReached(isLastIndex),
],
);
If it needs overlay, use Stack by combining listView and Text with Column.
Wrap the widget with Positioned and add bottom.
return Stack(
children: [
.....
Positioned(
bottom: yourValue,
child:

First, wrap Stack with ListView widget
Then, move buildBottomReached helper as a sibling of the Stack widget
return ListView(//this
children: [
Stack(
children: [
buildListView(),
buildBackToTop(backtoTop),
//buildBottomReached(isLastIndex),//move this a sibling of the Stack
],
),
buildBottomReached(isLastIndex),//moved here
],
);
Then, on buildListView helper, set ListView.builder property shrinkWrap to true.
Widget buildListView(ScrollController scrollController) {
return ListView.builder(
shrinkWrap: true,//this
controller: scrollController,
itemCount: 50,
itemBuilder: (context, index) {
return SizedBox(
width: 20,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 20,
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
color: Colors.grey[100],
),
child: Center(
child: Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Index $index"),
),
),
),
),
),
);
},
physics: const BouncingScrollPhysics());
}

Related

how to control the slidingUpPanel draggable

i want a slidingUpPanel similar to YouTube comments section. that not open with the scrolling of the content but open and close only from the drag handle by tap or by swipe up/down).
the drag handle is the top section of the slidingUpPanel :
so the draggable should happen only from this drag handle not from the whole body. (you can try the code below to know what i mean)
it means if i scroll the body(the listView builder) the slidingUpPanel keep its place (either open or closed) until i swip it from the drag handle.
my current code:
PanelController panelController = PanelController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
children: [
SlidingUpPanel(
controller: panelController,
maxHeight: MediaQuery.of(context).size.height * .9,
minHeight: MediaQuery.of(context).size.height * .7,
borderRadius: BorderRadius.vertical(top: Radius.circular(40.0)),
panelBuilder: (controller) => Stack(
alignment: Alignment.topCenter,
children: [
GestureDetector(
onTap: () {
panelController.isPanelOpen
? panelController.close()
: panelController.open();
},
child: Container(
color: Colors.transparent,
height: 36.0,
width: MediaQuery.of(context).size.width,
child: Center(
child: Container(
width: 46.77,
height: 4.0,
decoration: BoxDecoration(color: Colors.grey),
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 40.0),
child: ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
controller: controller,
padding: EdgeInsets.zero,
itemCount: 20,
itemBuilder: (context, index) {
return Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 70.0,
color: Colors.red,
),
),
],
);
}),
),
],
)),
],
),
));
}

it's possible to make listview in expand and fill parent without overflow?

it's possible to make listview in expand and fill the container without overflow the container, and shrink when listview is short of content without declare manual min or max height?
Code
Flexible(
fit: FlexFit.loose,
child: Container(
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(kBoxRadius),
boxShadow: [kBoxShadow]),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
DText(
"Aug 2021",
size: 12,
weight: FontWeight.bold,
),
SizedBox(height: 10),
Row(
children: dates,
),
SizedBox(height: 15),
Container(
height: 1,
color: Color(0xFFE7E7E7),
),
Container(
constraints:
BoxConstraints(minHeight: 0, maxHeight: 600),
child: ListView.separated(
shrinkWrap: true,
itemBuilder: (context, index) {
return DText("Asd");
},
separatorBuilder: (_, __) {
return SizedBox(height: 10);
},
itemCount: 20,
),
)
],
),
),
)
Expectation
when the content is big
because i set manually max height.
Yes, it is possible using shrinkWrap: true. The code will be something like below,
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Center(
child: Container(
color: Colors.red,
child: ListView(
shrinkWrap: true,
children: <Widget>[
ListTile(title: Text('Apple')),
ListTile(title: Text('Orange')),
ListTile(title: Text('Banana')),
],
),
),
),
),
);
}
}

Flutter: Horizontal Stepper - auto scrolling

As you may know, the Stepper widget puts step items into a row until it overflows the screen, with no way to make it scroll.
However, I found a way found in this link - https://github.com/flutter/flutter/issues/40601
Here is the code:
Widget _buildHorizontal() {
final List children = [
for (int i = 0; i < widget.steps.length; i += 1) ...[
InkResponse(
onTap: widget.steps[i].state != StepState.disabled
? () {
if (widget.onStepTapped != null) widget.onStepTapped(i);
}
: null,
canRequestFocus: widget.steps[i].state != StepState.disabled,
child: Row(
children: [
Container(
height: 72.0,
child: Center(
child: _buildIcon(i),
),
),
Container(
margin: const EdgeInsetsDirectional.only(start: 12.0),
child: _buildHeaderText(i),
),
],
),
),
if (!_isLast(i))
Container(
margin: const EdgeInsets.symmetric(horizontal: 8.0),
height: 1.0,
color: Colors.grey.shade400,
),
],
];
return Column(
children: <Widget>[
Material(
elevation: 2.0,
child: Container(
height: 65,
margin: const EdgeInsets.symmetric(horizontal: 24.0),
child: ListView(
scrollDirection: Axis.horizontal,
children: children,
),
),
),
Expanded(
child: ListView(
padding: const EdgeInsets.all(24.0),
children: <Widget>[
AnimatedSize(
curve: Curves.fastOutSlowIn,
duration: kThemeAnimationDuration,
vsync: this,
child: widget.steps[widget.currentStep].content,
),
_buildVerticalControls(),
],
),
),
],
);
}`
My issue right now is that I cannot make the ListView autoscrollable.
I have tried to use _scrollController = ItemScrollController but did not help.

Flutter ListView not scrolling (I feel like I've tried every solution on the internet)

If I drag and hold my finger down I can see a few items that are below the cutoff of the screen but as soon as I let go, it just bounces back to the top. I tried using SingleChildScrollView places, tried setting primary = true, and a bunch of other stuff that didn't help. I'm fairly new to flutter so any help would be appreciated!! Let me know if any more info is needed.
Here is my code:
import 'package:flutter/material.dart';
import 'package:drink_specials/models/restaurant.dart';
import 'package:drink_specials/screens/home/restaurant_list.dart';
class RestaurantNameTextStyle {
static TextStyle display5(BuildContext context) {
return Theme.of(context).textTheme.headline2.copyWith(color: Colors.white);
}
}
class RestaurantTypeTextStyle {
static TextStyle display5(BuildContext context) {
return Theme.of(context).textTheme.headline6.copyWith(color: Colors.white);
}
}
class RestaurantDetail extends StatelessWidget {
final Restaurant restaurant;
RestaurantDetail({Key key, #required this.restaurant}) : super(key: key);
#override
Widget build(BuildContext context) {
final topContentText = Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: 100.0),
Text(
restaurant.name,
style: RestaurantNameTextStyle.display5(context),
),
SizedBox(height: 10.0),
Expanded(
flex: 6,
child: Padding(
padding: EdgeInsets.only(left: 10.0),
child: Text(
restaurant.restaurant_type,
style: RestaurantTypeTextStyle.display5(context),
))),
],
);
final topContent = Stack(
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 10.0),
height: MediaQuery.of(context).size.height * 0.5,
decoration: new BoxDecoration(
image: new DecorationImage(
image: NetworkImage(restaurant.photo),
fit: BoxFit.cover,
),
)),
Container(
height: MediaQuery.of(context).size.height * 0.5,
padding: EdgeInsets.all(40.0),
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(color: Color.fromRGBO(58, 66, 86, .9)),
child: Center(
child: topContentText,
),
),
Positioned(
left: 8.0,
top: 60.0,
child: InkWell(
onTap: () {
Navigator.pop(context);
},
child: Icon(Icons.arrow_back, color: Colors.white),
),
)
],
);
final bottomContent = Container(
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(8.0),
child: Center(
child: ListView.builder(
scrollDirection: Axis.vertical,
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
itemCount: restaurant.specials.length,
itemBuilder: (context, index) {
final item = restaurant.specials[index];
return Card(
elevation: 8.0,
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: Container(
decoration: BoxDecoration(color: Color.fromRGBO(58, 66, 86, 1.0)),
child: ListTile(
contentPadding: EdgeInsets.symmetric(horizontal:20, vertical:10),
title: Text(item, style: TextStyle(color: Colors.white)),
)
),
);
}
),
),
);
return Scaffold(
body: Column(
children: <Widget>[
topContent,
Expanded(
child: bottomContent,
),
],
),
);
}
}
There is a ListView inside a SingleChildScrollView and both of them are scrollable. Scrolling on one of them should be disabled.
As they already explained. If you have a ListView.builder, you don't need SingleChildScrollView.
Try removing SingleChildScrollView. The code should look like this:
Scaffold(
body: Column(
children: <Widget>[
topContent,
Expanded(
child: bottomContent,
),
],
),
);
ListView already have scroll behavior so you won't need some SingleChildScrollView

Why every time I add a ListView to my Column all widgets disappear?

I'm making a Flutter Web App and I have something like this
class _HomeViewState extends State<HomeView> {
#override
Widget build(BuildContext context) {
var posts = Provider.of<List<Post>>(context);
List<int> l =[1,2,3,4];
return Scaffold(
backgroundColor: Colors.white,
appBar: TheAppBaar,
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Container(child: Padding(
padding: EdgeInsets.all(20.0),
child: Column(
children: [
CreatePost(connUserUid: widget.user.uid, connUserImage:
userFetched.get('profileImage').toString(),
connUserFullname: userFetched.get('fullName').toString(),),
SizedBox(height: 10,),
ListView.separated(itemBuilder: (BuildContext context, int
index) {
return Container(
height: 150,
child: Text('${l[index]}'),
);
},
separatorBuilder:
(BuildContext context, int index) => Divider(),
itemCount: l.length)
],
),
),
),
),
);
}
}
Every time I want to display a ListView with those posts fetched or anything, the method Create Post and that Sized Box disappear and the list is not displayed either.
#override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.center,
child: Container(
width: 400,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(10)),
boxShadow: [BoxShadow(
color:kPrimaryColor.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 3,
offset: Offset(0,3)
)]
),
child: Padding(
padding: EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Align(
alignment: Alignment.center,
child: Container(
height: 50,
child: Image.network(widget.connUserImage),
),
),
Align(
alignment: Alignment.center,
child: Container(width: 30,child: Divider(
color: kPrimaryColor,
thickness: 2,
),),
),
SizedBox(height: 8,),
TextField(
maxLines: 5,
decoration: InputDecoration(
errorText: errorTextMessage,
border: OutlineInputBorder(
borderSide: BorderSide(color: kPrimaryColor)
),
labelText: 'Yadda, Yadda, Yadda...'
),
onChanged: (String value) {
setState(() {
postDescription = value;
errorTextMessage = null;
spinner = false;
});
},
),
SizedBox(height: 12,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
IconButton(
icon: Icon(Icons.add_a_photo_rounded, color: Color
(0xFFE53E00),
size:
25,),
onPressed: () {
imagePicker();
},
),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: imageInfo == null ? Container() : Text(imageInfo.fileName),
)
],
),
Icon(Icons.pin_drop_rounded, color: Color(0xFF0077e5),
size:
25,),
Icon(Icons.map_rounded, color: Color(0xFF26c118),
size: 25,),
spinner? Padding(
padding: EdgeInsets.all(15.0),
child: CircularProgressIndicator(backgroundColor: kPrimaryColor,),
) :
IconButton(icon:
Icon(Icons
.arrow_forward_ios_outlined,
color:
kPrimaryColor,size: 25,), onPressed: () {
},),
],
)
],
),
),
),
);
}
This is the CreatePost method, just a " card ",
If I make a ListView all disappear, but if in my Column from the first code, I add 1 PostView by 1, they are displayed. I don't understand what's wrong. Should I remove those Align or I don't know. In my console I do not have any errors.
Thank you in advance!