when i add container / listview in mobile resolution there is no bottom overflowed problem. (and the content can still be scrolled).enter image description here
however when i add container in chrome/desktop resolution
enter image description here
I've been looking for ways to solve this problem on the internet, such as adding
Expanded()
or
resizeToAvoidBottomPadding: false
and so on.
but still can't solve this problem.
here's my code:
`
import 'package:flutter/material.dart';
class MyDesktopBody extends StatelessWidget {
const MyDesktopBody({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black54,
appBar: AppBar(
title: const Text('D E S K T O P'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
// First Column
Expanded(
child: Column(
children: [
// Youtube Video
Padding(
padding: const EdgeInsets.all(8.0),
child: AspectRatio(
aspectRatio: 16 / 9,
child: Container(
height: 250,
color: Colors.redAccent,
),
),
),
// Comment Section & Recommended Videos
Expanded(
flex: 8,
child: ListView.builder(
shrinkWrap: true,
itemCount: 8,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.black54,
height: 120,
),
);
}),
)
],
),
),
// Second Column
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 200,
color: Colors.black54,
),
)
],
),
),
);
}
}
`
change the first Column into a Listview and remove the second Expanded and it should work properly
import 'package:flutter/material.dart';
class MyDesktopBody extends StatelessWidget {
const MyDesktopBody({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black54,
appBar: AppBar(
title: const Text('D E S K T O P'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
// First Column
Expanded(
child: ListView( //<---- here
children: [
// Youtube Video
Padding(
padding: const EdgeInsets.all(8.0),
child: AspectRatio(
aspectRatio: 16 / 9,
child: Container(
height: 20,
color: Colors.redAccent,
),
),
),
// Comment Section & Recommended Videos
ListView.builder( //<--here
shrinkWrap: true,
itemCount: 8,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.black54,
height: 120,
),
);
})
],
),
),
// Second Column
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 200,
color: Colors.black54,
),
)
],
),
),
);
}
}
Related
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')),
],
),
),
),
),
);
}
}
My UI use case is similar to an Instagram user profile.
I have multiple widget on top and an infinite ListView.builder bellow with item.
I would like to scroll everything like within a ScrollView but the scrollview can not contain an infinite list.
How can I handle this situation in Flutter ?
Using CustomScrollView is the Solution
Here i have done Basic Implementation for you :
class MainBody extends StatefulWidget {
MainBody({Key key}) : super(key: key);
#override
_MainBodyState createState() => _MainBodyState();
}
class _MainBodyState extends State<MainBody> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: CustomScrollView(
slivers: <Widget>[
SliverToBoxAdapter(
child: Container(
padding:
const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Container(
height: 100,
width: 100,
decoration: BoxDecoration(
shape: BoxShape.circle, color: Colors.green),
child: Center(child: Text("ProfileImage")),
),
flex: 1,
),
Expanded(flex: 2, child: Text("Profile Statistics"))
],
),
Text("Bio"),
Text("Some Buttons"),
Text("Story Highlights"),
])),
),
SliverToBoxAdapter(
child: Container(
height: 150,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (context, index) {
return Container(
margin: const EdgeInsets.all(10),
height: 100,
width: 100,
decoration: BoxDecoration(
shape: BoxShape.circle, color: Colors.red),
child: Center(child: Text((index + 1).toString())),
);
})),
),
SliverAppBar(
centerTitle: false,
pinned: true,
flexibleSpace: DefaultTabController(
initialIndex: 0,
length: 2,
child: TabBar(tabs: [
Center(child: Text("Icon1")),
Center(child: Text("Icon2")),
]),
),
),
SliverPadding(
padding: const EdgeInsets.all(8),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => Container(
height: 30,
child: Center(child: Text("Hey" + index.toString()))),
childCount: 20)),
)
],
),
);
}
}
Futher Enhancements can be done
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
I would like to find a solution to create countdowns from a date and put them in a ListView. I hope this does not slow down the application too much when using it.
I already have a code I want to keep, it's a RecyclerView with images and text.
Here's the code, if you need anything else I'll send it to you.
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import '../recyclerview/data.dart';
import 'package:watch/constants.dart';
class ListViewExample extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return new ListViewExampleState(
);
}
}
class ListViewExampleState extends State<ListViewExample>{
List<Container> _buildListItemsFromItems(){
int index = 0;
return item.map((item){
var container = Container(
decoration: index % 2 == 0?
new BoxDecoration(color: const Color(0xFFFFFFFF)):
new BoxDecoration(
color: const Color(0xFFFAFAF5)
),
child: new Row(
children: <Widget>[
new Container(
margin: new EdgeInsets.all(5.0),
child: new CachedNetworkImage(
imageUrl: item.imageURL,
width: 200.0,
height: 100.0,
fit: BoxFit.cover,
),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: const EdgeInsets.only(bottom: 75.0 ),
child: Text(
item.title,
style: kItemTitle,
),
),
Container(
padding: const EdgeInsets.only(left: 15.0),
child:Text(
item.description,
style: kItemDescription,
),
),
]),
)
],
)
);
index = index + 1;
return container;
}).toList();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Accueil', style: kAppBarStyle,),
backgroundColor: Colors.white,
elevation: 0,
),
body: ListView(
children: _buildListItemsFromItems(),
),
);
}
}
Thank you!
Update : to add the countdown look this post :Date Countdown Timer
and for the lazy loading, I have changed my ListView to a ListView.builder
Is is suggested to use Listview.builder and not just put a list into ListView if you need lazy loading.
https://flutter.dev/docs/cookbook/lists/long-lists
Replace the ListView to ListView.builder.
ListView.builder(
itemCount: // items.length
itemBuilder: (buildContext, index) {}, // define what Widget for each index
)
Here is the sample code from yours. index is already exist in itemBuilder function.
...
body: ListView.builder(
itemCount: items.length,
itemBuilder: (buildContext, index) {
return Container(
decoration: index % 2 == 0
? new BoxDecoration(color: const Color(0xFFFFFFFF))
: new BoxDecoration(color: const Color(0xFFFAFAF5)),
child: new Row(
children: <Widget>[
new Container(
margin: new EdgeInsets.all(5.0),
child: new CachedNetworkImage(
imageUrl: item.imageURL,
width: 200.0,
height: 100.0,
fit: BoxFit.cover,
),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: const EdgeInsets.only(bottom: 75.0),
child: Text(
items[index].title,
),
),
Container(
padding: const EdgeInsets.only(left: 15.0),
child: Text(
items[index].description,
),
),
],
),
)
],
),
);
},
),
...
I want to get effect like this - when scrolled up, appbar is transparent with listview visible below it:
And scrolled down, only white color - first item below appbar:
My window layout:
return Container(
color: AppTheme.nearlyWhite,
child: SafeArea(
top: false,
bottom: false,
child: Scaffold(
backgroundColor: AppTheme.nearlyWhite,
body: Stack(
children: <Widget>[
DrawerUserController(
screenIndex: _drawerIndex,
drawerWidth: MediaQuery.of(context).size.width * 0.75,
animationController: (AnimationController animationController) => _sliderAnimationController = animationController,
onDrawerCall: (DrawerIndex drawerIndexdata) => _onDrawerCall(drawerIndexdata, _forceRefresh),
onDrawerTap:(DrawerIndex drawerIndexdata) => _onDrawerTap(drawerIndexdata),
screenView: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(8, MediaQuery.of(context).padding.top + 8, 8, 8),
child: _createAppBar(),
),
Expanded(
child:
Container(
color: Colors.white,
child: _screenView,
)
),
],
),
),
new FabDialer(_fabMiniMenuItemList, Colors.blue, new Icon(Icons.add))
],
),
),
),
);
}
_screenView is simple Listview().builder() and it shows InkWell widget for each item. My appbar is custom, defined like this:
_createAppBar() {
return SizedBox(
height: AppBar().preferredSize.height,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 8, left: 8),
child: Container(
width: AppBar().preferredSize.height - 8,
height: AppBar().preferredSize.height - 8,
),
),
Expanded(
child: Center(
child: Padding(
padding: const EdgeInsets.only(top: 4),
child: Column(
children: <Widget>[
Text(
_menuSelected,
style: TextStyle(
fontSize: 22,
color: AppTheme.darkText,
fontWeight: FontWeight.w400,
),
),
Text(
globals.cityName,
style: TextStyle(
fontSize: 15,
color: AppTheme.darkerText,
fontWeight: FontWeight.w400,
),
),
],
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 8, right: 8),
child: Container(
width: AppBar().preferredSize.height - 8,
height: AppBar().preferredSize.height - 8,
color: Colors.white,
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius:
BorderRadius.circular(AppBar().preferredSize.height),
child: Icon(Icons.refresh, color: AppTheme.dark_grey,),
onTap: () => setState(() => _forceRefresh = true),
),
),
),
),
],
),
);
}
That's how it looks now with first list item visible:
So, almost there, but when scrolled down, appbar won't be transparent:
I tried to mess around with setting my appbar backround to color with transparency, without success. Also I need to get my widgets actually overlapped (ListView needs to overlap my appbar) and it generates error messages from Flutter.
Any ideas how to do that properly?
set extendBodyBehindAppBar: true in Scaffold widget. Then use Opacity widget like this,
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: Home()));
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: PreferredSize(
preferredSize: const Size.fromHeight(kToolbarHeight),
child: Opacity( //Wrap your `AppBar`
opacity: 0.8,
child: AppBar(
title: Text("Demo"),
),
),
),
body: ListView.builder(
itemCount: 30,
itemBuilder: (context, index) {
return ListTile(
title: Text("Tile: $index"),
);
},
),
);
}
}
#override
Widget build(BuildContext context) {
return Container(
child: Stack(
children:[
Container(
color:Colors.white,
padding:EdgeInsets.all(10),
child:ListView.builder(
itemCount:25+1,
//length + 1 is beacause to show 1st item at the beginning
shrinkWrap:true,
itemBuilder:(con,ind){
return ind==0 ?
Container(height:70)
:ListTile(
title:Text('Item $ind',
style:TextStyle(color:Colors.black,))
);
}
)
),
Container(
height:70,
color:Colors.transparent,
child:Card(
color:Colors.white.withAlpha(80),
child: Row(
children:[
Expanded(
flex:1,
child: IconButton(
icon:Icon(Icons.list,color:Colors.black,size:25),
onPressed:(){
//todo
}
),
),
Expanded(
flex:3,
child: Text('Title',
style:TextStyle(color:Colors.black,)),
),
Expanded(
flex:1,
child: IconButton(
icon:Icon(Icons.search,color:Colors.black,size:25),
onPressed:(){
//todo
}
),
),
Expanded(
flex:1,
child: IconButton(
icon:Icon(Icons.more_vert,color:Colors.black,size:25),
onPressed:(){
//todo
}
),
)
]
),
)
)
]
)
);
}