Flutter Stack not aligning floating action button - flutter

I'm making a listview with a few buttons. I've used a stack widget to place two floating action buttons on top of Listview. However, I want to align them to the bottom right and bottom left of the listview. I'm not able to do this we Align widget although I don't understand why. Note that I understand I could've used a scaffold widget here but that is not an option given Listview is a child of Scaffold. Also, I've tried using the alignment property of Stack, but it didn't work. I was hoping you guys could help solve this problem :D
This is the code here:
#override
Widget build(BuildContext context) {
#override
void initState() {
super.initState();
written = [];
read = [];
}
return Stack(
//fit: StackFit.expand,
alignment: AlignmentDirectional.bottomEnd,
children: [
ListView.separated(
reverse: true,
shrinkWrap: true,
separatorBuilder: (context, i) => Container(
//color: Colors.greenAccent,
width: double.infinity,
height: 8,
),
itemCount: savedhistory.length,
itemBuilder: (context, i) => Dismissible(
key: UniqueKey(),
onDismissed: (direction) {
setState(() {
savedhistory.removeAt(i);
updateString(i);
});
},
child: Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.all(Radius.circular(20))),
child: savedhistory[i],
//padding: EdgeInsets.all(8.0),
),
/* read == null
? []
: read.map((e) => ExpansionTile(
title: Text(e),
subtitle: Text(e),
)), */
)),
Positioned(
//alignment: Alignment.bottomRight,
// child: GestureDetector(
// onLongPress: () => getString(),
bottom: 50,
right: 0,
child: FloatingActionButton(
child: Icon(Icons.replay_outlined),
onPressed: getString,
backgroundColor: Colors.green[200])),
Align(
alignment: Alignment.bottomLeft,
child: Container(
child: FloatingActionButton(
child: Icon(Icons.download),
onPressed: addString,
backgroundColor: Colors.green[200]),
),
)
]);
}
}
After using positioned there seems to be some space beyond which button gets clipped, I don't understand why though.
[1]: https://i.stack.imgur.com/bjrnL.png

try to use Positioned widget :
stack(
children[
Positoned(
bottom : 0
left :1
child: Container(
/// YOUR CODE ///
)
)
]
)

first set stack widget's alignment to bottomcenter and then use Positoned() for first button widget with left: 0 and with second button right:0

Related

how to give expanded height to listview while it is used inside single child scrollview in flutter?

Here is a demo where I have taken some container, textfield and listview builder,
I have wrapped all in SingleChildScrollView to avoid pixel error while opening keypad,
Here I want to give possible height to listview ,depend on item count and spacer between listview and save button
Here is my code:
List<String> paybylist=[
'A','B','C','D','E','F','G',
'H','I','J','K','L','M','N',
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(children: [
Container(
height: 100,
color: Colors.red,
child: Center(child: Text('Container1')),
),
Container(
height: 50,
//color: Colors.green,
child: Center(
child: CustomTextField(),
),
),
Text('Select Payment Mode'),
Container(
height: 400,//height should be based on available space
color: Colors.grey,
child:ListView.builder(
itemCount: paybylist.length,
itemBuilder: (context,index){
return ListTile(
title: Text(paybylist[index]),
);
}) ,
),
//want to add available space between listview and save button
Padding(
padding: const EdgeInsets.all(8.0),
child: MaterialButton(
color: Colors.blue,
onPressed: (){},child: Center(child: Text('Save')),),
)
],),
),
);
}
}
You can add shrinkWrap:true in your ListView.builder() and add physics: NeverScrollableScrollPhysics() to it otherwise your list won't scroll.
Here's an example
#override
Widget build(BuildContext context) {
List<String> paybylist = [
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
];
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
Container(
height: 100,
color: Colors.red,
child: Center(child: Text('Container1')),
),
Container(
height: 50,
//color: Colors.green,
child: Center(
child: TextField(),
),
),
Text('Select Payment Mode'),
Container(
// height: 400,
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: paybylist.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(paybylist[index]),
);
}),
),
//want to add available space between listview and save button
Padding(
padding: const EdgeInsets.all(8.0),
child: MaterialButton(
color: Colors.blue,
onPressed: () {},
child: Center(child: Text('Save')),
),
)
],
),
),
);
}
Also you can add your save button either in Stack or BottomNavigationBar, that way the button will be always visible.
You cannot add Expanded inside the Scrollable Widget in flutter,
To fill the available gap, place the save button in bottomNavigationBar
So now the ListView doesn't need fixed height of 400 and it can span to have the full height. In fact it will span only the height of children
Make sure you add shrinkWrap :true and physics: NeverScrollableScrollPhysics() inside the ListView.builder()
Your present structure
Scaffold
|_body:
|_SingleChildScrollView
|_Column
|_Container
|_Container
|_Continaer (400 height)
|_ListView
|_Container (Save Button)
Change it to :
Scaffold
|_body:
|_SingleChildScrollView
|_Column
|_Container
|_Container
|_ListView
|shrinkWrap:true
|physics: NeverScrollableScrollPhysics()
|_bottomNavigationBar
|_Container (Save Button)

How to make whole screen scrollable in flutter

This is my Code for Body of Scaffold of the Screen
Container(
child: Column(
children: <Widget>[
Expanded(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
VideoPlay(widget: widget),
TitleVideo(widget: widget),
Padding(
padding: const EdgeInsets.only(top: 1.0, left: 10),
child: Opacity(
opacity: 0.5,
child: Row(
children: <Widget>[
Text(widget.video.viewCount + " views "),
SizedBox(
width: 5,
child: Text("|"),
),
Text(" ${timeago.format(widget.video.timestamp)}"),
],
),
),
),
SizedBox(
height: 15,
),
IconRow(
video: widget.video,
),
//User Panel
subscribe_panel(),
SizedBox(
height: 310,
child: suggestedVideo(),
),
// Suggestions list
],
),
),
),
],
),
);
}
The "suggestion list" Contains This Code
class suggestedVideo extends StatelessWidget {
const suggestedVideo({Key? key,}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: suggestedVideos.length,
itemBuilder: (context, index) => VideoCard(
video: suggestedVideos[index],
press: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
VideoScreen(video: suggestedVideos[index])));
},
),
);
}
}
but The Screen is only scrolling the ListView Builder part rather than the whole screen,
I am trying to recreate youtube UI and for the VideoScrolling screen , I want to scroll the screen , by keeping the video at top and Every other widget being scrollable.
You can wrap your top-most Container with SingleChildScrollView, this will make all of your Widget scrollable, also you can replace SingleChildScrollView(child: Column(... with ListView(...), it will give you same result
This happens because when you try to scroll, it scrolls the ListView and not the SingleChildScrollView.
In order to solve that, add
physics: const NeverScrollableScrollPhysics()
to your ListView.
You can also remove the SizedBox that wraps suggestedVideo() and add
shrinkWrap: true,
scrollDirection: Axis.vertical,
to your ListView.

Listview.builder not showing my images when implementing in Flutter

I am trying to implement a horizontal Listview which shows my images pulled from the Flutter image_picker plugin.
its work fine if I do not use a Listview and only display a single image. however I am trying to use multiple images and as soon as I place within the Listview the widgets just shows up as black. my code for the Listview is as follows:
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
Navigator.pushReplacementNamed(context, 'inventory');
return false;
},
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.green[700],
title: Text(
'MyApp',
textAlign: TextAlign.center,
),
leading: new IconButton(
icon: new Icon(Icons.arrow_back),
onPressed: () {
Navigator.pushReplacementNamed(
context,
'inventory');
},
),
actions: <Widget>[
Padding(
padding: EdgeInsets.only(right: 10.0),
child: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white, //remove this when you add image.
),
child: GestureDetector(
onTap: (){
Navigator.pushNamed(context,'profile');
},
child: Image(
image:NetworkImage("imageUrl goes here"),
width: 120,
height: 120,
fit: BoxFit.cover,
),
),
),
)
],
),
body: SafeArea(
child: Column(
children: [
pickedFile == null ?
GestureDetector(
onTap: () {
_showMyDialog();
setState(() {
});
},
child: Container(
width: 200,
height: 200,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Click to add a Photo',textAlign:
TextAlign.center,style: TextStyle(fontSize: 24),),
SizedBox(height: 20,),
Icon(
Icons.add_circle_outline,
color: Colors.grey[700],
size: 30,
),
],
),
margin: EdgeInsets.all(20.0),
decoration: BoxDecoration(
border: Border.all(width: 2,color: Colors.grey),
shape: BoxShape.circle
),
),
)
:
GestureDetector(
onTap: () {
_showMyDialog();
setState(() {
});
},
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: _imageFileList!.length,
itemBuilder: (BuildContext context, int index) {
return kIsWeb
? Image.network(_imageFileList![index].path)
: Image.file(File(_imageFileList!
[index].path));
}
)
],
),
),),
);
}
}
I am not showing the whole code as the page is too long however the rest of the page works fine. if i remove the Listview builder and instead test using just the below it works fine. what am i doing wrong?
child: Row(
children: [
kIsWeb
? Container(
child: Image.network(_imageFileList![index].path))
: Container(
child: Image.file(File(_imageFileList![index].path)));
}
),
],
),
Please help.
**Edited the above code with my full widget
Either use Row or use ListView, not both.
You can use Row with List.generate:
Row(
children: List.generate(_imageFileList!.length,
(i) => kIsWeb
? Container(child: Image.network(_imageFileList![index].path))
: Container(child: Image.file(File(_imageFileList![index].path))
),
Or ListView exactly how you have it without the Row. ListView is probably the widget you’re wanting to use. Row will overflow if the content is larger than the width while ListView will act as its own ScrollView in that situation.
I’d also double-check that you need that Expanded widget. That’s typically for use inside a Row (or similar widgets).
Managed to solve my issue. it was related to a height constraint which needed to be added. found the solution in this link
How to add a ListView to a Column in Flutter?

Why is expanded container not visible within list view?

I have a widget that displays a 100x100 image and a blue container next to it which fills the rest of the Row.
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Scaffold.of(context).showSnackBar(SnackBar(content: Text(title)));
},
child: Container(
padding: EdgeInsets.all(24),
child: Row(
children: [
SizedBox(
child: Image.asset("assets/img_small.png"),
width: 100,
height: 100),
Expanded(
child: Container(margin: EdgeInsets.only(left: 12), color: Colors.blue)
)
],
),
));
}
This works fine but as soon as I use it within a list view, the blue container is not visible:
#override
Widget build(BuildContext context) {
return ListView.separated(
itemCount: list.length,
separatorBuilder: (context, index) =>
Divider(color: Colors.grey, thickness: 2, height: 0, indent: 8),
itemBuilder: (context, position) {
return BlueBoxWidget(title: list[position]);
});
}
What am I doing wrong?
I am mostly interested why inside a listview the blue container doesn't try to expand its height as much as possible.
The blue Container is there, but with 0 height.
Try adding some height, like this, to get the container visible
Expanded(
Container(
height: 50,
margin: EdgeInsets.only(left: 12),
color: Colors.blue
),
)
try to remove the Expanded widget that wrapped the Container it maybe work.

How to put a Stack as a child of CustomScrollView

I am using a CustomScrollView. I have added a few slivers in it but one of my children has to be a stack which has a list as on of its two children. I tried using SliverToBoxAdapter but that makes the list in the stack non scrollable which is the obvious behaviour. Is there a way to to write some kind of SliverToSliverAdapter? I tried reading the SliverPadding but its looks too complicated for me to understand. Below is my code:
CustomScrollView(
key: PageStorageKey<String>(name),
slivers: <Widget>[
SliverOverlapInjector(
handle:
NestedScrollView.sliverOverlapAbsorberHandleFor(context)),
SliverToBoxAdapter(
child: Stack(
children: <Widget>[
Container(
width: double.infinity,
height: 50,
decoration: BoxDecoration(color: pink),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: ListView.builder(
padding: const EdgeInsets.all(0),
shrinkWrap: true,
itemBuilder: (context, index) {
return buildSongRow(songs[index]);
},
itemCount: songs.length,
),
)
],
)),
],
);
Stack widget use parent's size by default. While parent widget is CustomScrollView that decide it's size mean, it will get infinite height. To solve this issue, we can wrap Stack with SizedBox(height:x).
Next issue comes on Stack about scrolling and widget visibility. Widget render prioritize bottom to top and same for the scroll event. While Container(height:50) is the first child of Stack, it will be paint behind ListView and in this case we can have full-scroll event on ListView.
We can move Container<height:50> at the bottom to paint it over ListView. In this case, scroll-event won't work on Container<h:50> portion.
We can wrap Container<h:50> and ListView with SizedBox by providing height and use Align or Positioned widget to place them on Stack. Also, we can increase itemCount+1 and use an empty SizedBox(height:50)(on index 0) that will take same amount of height as Container(height:50) and help to view only for 1st time on Stack.
I am using LayoutBuilder to get the size/constraints of screen.
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) => CustomScrollView(
slivers: [
const SliverAppBar(
title: Text("Stack On CustomScrollView"),
),
SliverToBoxAdapter(
child: SizedBox(
height: constraints.maxHeight * .3, // used by stack
child: Stack(
children: [
Align(
alignment: Alignment.topCenter,
child: Container(
// dont need to use sizedBox here, height is fixed by container's height:50
height: 50,
color: Colors.pink,
alignment: Alignment.center,
child: const Text("Stack Child: Container<height: 50>"),
),
),
Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
height: constraints.maxHeight * .3 - 50,
child: ListView.builder(
itemCount: 4,
itemBuilder: (context, index) => Container(
alignment: Alignment.center,
height: 50,
color: index.isEven
? Colors.deepOrange
: Colors.deepPurple,
child: Text("ListViewItem:$index"),
),
),
),
),
],
),
),
),
SliverList(
delegate: SliverChildListDelegate(
[
...List.generate(
44,
(index) => Container(
height: 100,
alignment: Alignment.center,
color: index.isEven ? Colors.cyanAccent : Colors.blueGrey,
child: Text("SliverList $index"),
),
),
],
),
),
],
),
),
);