How to make whole screen scrollable in flutter - 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.

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)

Text overflow ellipsis in Listview only on item that actually overflow

I have a horizontal ListView which is in the Column in which I want to show ellipsis on the last Text widget, if that list overflow. How I can achieve this? I added TextOverflow.ellipsis on Text widget but it still doesn't work. So I want for that last item in that horizontal list (Obstetrics & Gynae in this case) to have ... at the end.
class Card extends StatelessWidget {
#override
Widget build(BuildContext context) {
return FutureBuilder<DoctorData?>(
future: _bloc.getData(id: id, context: context),
builder: (context, snapshot) {
if (snapshot.hasData) {
final data = snapshot.data;
if (data != null) {
return GestureDetector(
onTap: () => (),
child: Container(
padding: const EdgeInsets.all(16),
child: Container(
padding: const EdgeInsets.all(8),
child: Row(
children: [
Image(data: data),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(data.name),
SizedBox(
height: 18,
child: ListView.separated(
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) => Text(
data.relations[index].code,
overflow: TextOverflow.ellipsis,
),
separatorBuilder: (_, __) => const Text(' ยท '),
itemCount: data.relations.length,
scrollDirection: Axis.horizontal,
),
),
],
),
),
const SizedBox(width: 8),
const ChevronRightIcon(),
],
),
),
),
);
}
}
return Container();
},
);
}
}
If you want to use ellipsis it should overflow, but in listView it just expands to take space, So you can wrap you subTitle in the sized box.
SizedBox(
width: context.width * 0.9, // we are letting the text to take 90% of screen width
child: Text(
data.relations[index].code,
overflow: TextOverflow.ellipsis,
),
);
If you have any questions please free to drop it in comments I will try to address those. Thanks ๐Ÿ™‚
UPDATE:
Here is the UI implemented in the dartpad.
And gist link

Column/SingleChildScrollView not scrolling

I'm learning flutter to make an app. Here I'm trying to make a page to show the full post. The problem is that the page isn't scrolling as a single unit.
class SinglePostPage extends StatefulWidget {
final Post? post;
const SinglePostPage({Key? key, this.post}) : super(key: key);
#override
State<SinglePostPage> createState() => _SinglePostPageState();
}
class _SinglePostPageState extends State<SinglePostPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
margin: const EdgeInsets.only(top: 22.5),
padding: const EdgeInsets.fromLTRB(0, 5, 0, 6),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const BackButton(),
Row(
children: [
InkWell(
onTap: () {
showDialog(...);
},
child: CircleAvatar(...),
Container(
padding: const EdgeInsets.only(left: 5.4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
GestureDetector(
onTap: () {
showDialog(...);
},
child: Text(
widget.post!.author[0].profileName,
),
),
const SizedBox(height: 4),
Text(
showTimeAgo(widget.post!.postTime).toString(),
),
],
),
),
],
),
PopupMenuButton(
icon: const Icon(Icons.more_vert),
itemBuilder: (context) => [...],
),
Container(
margin: const EdgeInsets.fromLTRB(12, 9, 12, 3),
// when the text is longer than the screen height it showed RenderFlex overflowed error so I put constraints. how to show it full and make this scroll
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.54,
minHeight: 50),
child: SingleChildScrollView(
child: Text(
widget.post!.postText,
textAlign: TextAlign.start,
),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (widget.post!.postMedia.isNotEmpty)
CarouselSlider.builder(...),
const SizedBox(height: 4.5),
if (widget.post!.postMedia.length > 1)
buildDotIndicator(widget.post!.postMedia),
],
),
],
),
),
Container(
// post reactions row
),
CommentBodyWidget(
postId: widget.post!.postId,
),
],
),
);
}
}
I looked up for other answers and tried wrapping it with SingleChildScrollView, but it didn't work , and ListView with shrinkWrap: true also gave 'Incorrect use of ParentDataWidget' error.
CommentBodyWidget has a listview builder. It's scrolling on its own but the widget above isn't scrolling along with it.
How can I show this whole page and scroll together without having to limit the long post in a constrained container? Please help.
You can wrap body Column with SingleChildScrollView and use shrinkWrap: true, and use physics: NeverScrollableScrollPhysics(),. This will solve the issue.
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
//...
ListView.builder(
itemCount: itemlength,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return Text("item $index");
},
),
/// instead of listView
...List.generate(itemlength, (index) => Text("itemWidget"))
],
),
),
);
But I will encourage you to check CustomScrollView.
In order for the SingleChildScrollView to work, its parent's height should be defined.
You can achieve this by wrapping the SingleChildScrollView in a Container/SizedBox with defined height, or by wrapping it with the Expanded widget.
Pass SingleChildScrollView as body of your scaffold. Also shrinkwrap: true for the ListView is recommended so that it only takes up as much space as required, which will avoid unbounded height errors.
So instead of
...
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
...
Do this
...
Widget build(BuildContext context)
return Scaffold(
body: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(...
I recommend you to use CustomScrollView.
Try this:
CustomScrollView(
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Column("""HERE PUT YOUR CODE""")
)]
),

Flutter Stack not aligning floating action button

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

flutter: How to achieve the gradually fading text in a ListView?

I want to achieve the style like the picture.
A ListView containing a few Container, and each container has some text. When scrolling the ListView, I want to gradually faded part of the content of the last Container. The last means the one displayed in the bottom of the ListView.
this is what I have done. Some explanation: timeTable is a widget in front of the ListView, and statisticItem is exactly the Container that I mentioned above.
body: Column(
children: <Widget>[
timeTable(),
SizedBox(height: 18,),
Expanded(
child: ListView.separated(
itemCount: 5,
separatorBuilder: (context, index) => SizedBox(height: 24.0,),
itemBuilder: (context, index) => statisticItem(),
),
)
],
)
Also, I have made some effort in shaderMask, but I can only change the background color. Any idea I'll we very appreciative.
It could be something like:
body: Column(
children: <Widget>[
timeTable(),
SizedBox(
height: 18,
),
Expanded(
child: Stack(
child: ListView.separated(
itemCount: 5,
separatorBuilder: (context, index) => SizedBox(
height: 24.0,
),
itemBuilder: (context, index) => statisticItem(),
),
FadeEndListView(),
),
)
],
),
Where FadeEndListView is:
class FadeEndListView extends StatelessWidget {
const FadeEndListView({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Positioned(
bottom: 0,
left: 0,
right: 0,
height: 70,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: [0.0, 1.0],
colors: [
Theme.of(context).scaffoldBackgroundColor.withOpacity(0.0),
Theme.of(context).scaffoldBackgroundColor,
],
),
),
),
);
}
}
My answer is from: Fading Edge ListView - Flutter
The answer of Yariv.A. with small changes.
You can use flutter pub package.
fading_edge_scrollview
Sliver can be used. SliverList, SliverAppbar. It is used for custom scroll effects. Custom Scroll view can also be tried.
I found this question similar.
How to fade in/out a widget from SliverAppBar while scrolling?
As mentioned before by #Salim Murshed https://pub.dev/packages/fading_edge_scrollview worked for me, but I thought I'd add some of the changes you may want to make.
I altered two values within the package to achieve the desired strength of fade at the top and bottom of the list:
double gradientFractionOnStart = 0.0,
double gradientFractionOnEnd = 1.0,
Here is my test code page for this:
final _controller = ScrollController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
height: 190,
width: 200,
child: Column(
children: <Widget>[
Expanded(
child: FadingEdgeScrollView.fromScrollView(
child: ListView.separated(
controller: _controller,
itemCount: 50,
separatorBuilder: (context, index) => SizedBox(
height: 14.0,
),
itemBuilder: (context, index) => Text(
'${index+1} Item ${index+1}) - Test',
style: TextStyle(color: Colors.black, fontSize: 17,
fontWeight: FontWeight.w900),
),
),
),
)
],
),
),
));
}
Output display of the code