How to make list view builder scrollable and set its height space as much as it can take? - flutter

I have a problem with ListView. I need to make it scrollable and set its size to max space it can take. Below listView I have a button that should be visible, but the ListView covers it.
I tried solutions from similar topics:
put ListView into SingleChildScrollView
make ListView Expanded
So the problem is:
how to make this listView scrollable?
how can I set its size to max as it can take (I mean it should be between 'List of participants' and Leave button)
how can I attach this button to be always on the bottom of screen, no matter what size of screen I have?
I hope pictures help you to understand what I mean. I also add the code but it is formatted weird, so sorry about that.
Screenshoot from device with above problem:
How it looks on another device and how it should look:
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: const Text('Flutter SDK'),
centerTitle: true),
body: Padding(
padding: const EdgeInsets.all(16),
child: !isInitializedList
? Column(
children: [
TextField(
controller: usernameController,
readOnly: true),
const SizedBox(height: 12),
TextField(
decoration: const InputDecoration(hintText: 'Conference name'),
controller: conferenceNameController),
const SizedBox(height: 12),
ElevatedButton(
onPressed: () async {
// Step 5: Call joinConference()
await joinConference();
},
child: isJoining
? const Text('Joining...')
: const Text('Join the conference')),
const Divider(thickness: 2),
const Text("Join the conference to see the list of participants.")
],
)
: Column(
children: [
Text(
'Conference name: ${conferenceNameController.text}',
style: const TextStyle(fontWeight: FontWeight.w400, fontSize: 16)),
const SizedBox(height: 16),
Column(
children: [
const Align(
alignment: Alignment.centerLeft,
child: Text(
'List of participants:',
style: TextStyle(color: Colors.blue, fontWeight: FontWeight.w600))),
const SizedBox(height: 16),
// Step 7: Display the list of participants
ListView.separated(
separatorBuilder: (BuildContext context, int index) {
return const SizedBox(height: 5);
},
shrinkWrap: true,
itemCount: participants.length,
itemBuilder: (context, index) {
var participant = participants[index];
return Padding(
padding: const EdgeInsets.all(4),
child: Row(children: [
Expanded(
flex: 1,
child: SizedBox(
height: 150,
width: 150,
child: VideoView.withMediaStream(
participant: participant,
mediaStream: participant.streams?.firstWhereOrNull((s) =>
s.type == MediaStreamType.camera),
key: ValueKey('video_view_tile_${participant.id}'))),
),
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Text(
"${participant.info?.name.toString()}"),
Text(
"status: ${participant.status?.name}")
]),
),
)
]),
);
}),
]),
const SizedBox(height: 16),
ElevatedButton(
style: ElevatedButton.styleFrom(primary: Colors.red),
onPressed: () async {
// Step 6: Call leaveConference()
await leaveConference();
},
child: isJoining
? const Text('Leaving...')
: const Text('Leave the conference'))
])
)
);
}

When you want to make list view expand as much as available, you need to wrap it with Expanded widget, by that you tell to column give it space as much as you have, also you need to do this for inside column agin, like this:
Column(
children: [
Text('Conference name: ${conferenceNameController.text}',
style: const TextStyle(fontWeight: FontWeight.w400, fontSize: 16)),
const SizedBox(height: 16),
Expanded(// <--- add this
child: Column(
children: [
const Align(
alignment: Alignment.centerLeft,
child: Text('List of participants:',
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.w600))),
const SizedBox(height: 16),
Expanded( // <--- add this
child: ListView.separated(
separatorBuilder:
...
)

You can make listview scrollable with shrinkwrap parameter inside Listview.builder()

Related

flutter Specify height of card in listview.builder

I want the cards built in a listview.builder, to have a height of 150.
What currently happens:
Currently, with my code, here's what gets built. Instead of the default height, I want to explicitly set my own card height, say, 150
What I have tried:
Isn't using SizedBox enough to get the height I want in a listview?
class GamesListState extends State<GamesList> {
#override
Widget build(BuildContext context) {
return MyScaffold(
body: Container(
padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 32),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 32),
const MyHeaderTitle(title: 'Games'),
const SizedBox(height: 40),
Flexible(
child: ListView.builder(
itemCount: list.length,
prototypeItem: ListTile(
title: Text(list.first.values.first),
),
itemBuilder: (context, index) {
return Card(
elevation: 5,
child: SizedBox(
height: 150,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Image.asset('assets/images/logo.png'),
const Text(
'Game name',
style: TextStyle(
fontSize: 10, fontWeight: FontWeight.w700),
),
const Icon(Icons.keyboard_arrow_right)
],
),
),
);
},
)),
],
),
),
);
}
}
Will appreciate any insights as to what I'm doing wrong.
Specify the height of prototypeItem of listView.builder by wrapping it with SizedBox
prototypeItem: ListTile(
title: SizedBox(height: 150, child: Text(list.first.values.first)),
),

not able to return elements with nested gridview builder - fluttter

my case is that I am retrieving values images and text for challenges (like products ...etc), the challenges should appear one by one vertically first the image appears then the text appears over the image in the centre so I used stack and padding and I was able to retrieve one challenge information only, now I want to retrieve all challenges vertically using gridview builder, so I have did this :
Widget build(BuildContext context) {
return GridView.builder(
scrollDirection: Axis.vertical,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: _challenges.length),
itemBuilder: (_, index) {
return InkWell(
onTap: () {},
child: Stack(
children: [
Padding(
padding: EdgeInsets.all(10.0),
child: Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image(
image:
NetworkImage(_challenges[index]["image-path"][0]),
fit: BoxFit.cover,
height: 150,
width: 350,
opacity: AlwaysStoppedAnimation(.4),
),
),
),
),
Padding(
padding: const EdgeInsets.all(60.0),
child: Center(
child: Text(
"${_challenges[index]["name"]}\n${_challenges[index]["date"]}",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
),
),
),
],
),
);
});
every time i hot reload the app i get this error:
'package:flutter/src/rendering/sliver_grid.dart': Failed assertion: line 319 pos 15: 'crossAxisCount != null && crossAxisCount > 0': is not true.
and in just in case this is how i retrieved the data from Firestore:
List _challenges = [];
fetchChallengeData() async {
var _fireStoreInstance = FirebaseFirestore.instance;
QuerySnapshot qn = await _fireStoreInstance.collection("challenges").get();
setState(() {
for (int i = 0; i < qn.docs.length; i++) {
_challenges.add({
"image-path": qn.docs[i]["image-path"],
"name": qn.docs[i]["name"],
"date": qn.docs[i]["date"],
});
}
});
}
#override
void initState() {
fetchChallengeData();
super.initState();
}
the home screen where i use to display the element looks like:
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.purple,
title: Text(
"أتحداك",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
centerTitle: true,
),
body: SingleChildScrollView(
child: Column(
children: [
AdsBanner(),
SizedBox(
height: 50,
),
Directionality(
textDirection: TextDirection.rtl,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text(
"التحديات",
style: TextStyle(fontSize: 20),
),
Text(
" (إضغط على التحدي للإشتراك به)",
style: TextStyle(fontSize: 15),
)
],
),
),
),
ChallengeCard(),
],
),
),
endDrawer: NavigationDrawer());
so basically the parent is a column and the parent of the column is singleChildScrollView,
any help I would be grateful, Thanks.
We are getting data from future fetchChallengeData, So it will be null initially, Try returning another widget on null or empty cases
Widget build(BuildContext context) {
return _challenges!=null && _challenges.isNotEmpty? GridView.builder(...): SizedBox.shrink();
Though _challenges.isNotEmpty enough while we've List _challenges = [];
I think we are seeking somthing like this
Widget myGridView() {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4, //number of items on single Row
),
itemCount: _challenges.length, // number of item will render
itemBuilder: (context, index) => Text("Your item Builder"),
);
}
Widget placement
body: Column(
children: [
AdsBanner(),
SizedBox(
height: 50,
),
Directionality(
textDirection: TextDirection.rtl,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text(
"التحديات",
style: TextStyle(fontSize: 20),
),
Text(
" (إضغط على التحدي للإشتراك به)",
style: TextStyle(fontSize: 15),
)
],
),
),
),
Expanded(child: ChallengeCard()),
],
),

Flutter Column with ListView and more Widgets above it

i'm trying a simple title -> search box -> listview thing, but can;t figure out how to fill the screen without tripping the horrible overflow error.
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text('title', textAlign: TextAlign.center, style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),),
......
TextField(textfield_settings),
SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height * 0.6, // the part i want to get rid of and have a flexible height, based on the total screen size and the other widgets
child: ListView.builder(itemBuilder: (ctx, index) {})
)
)
I Basically want the SingleChildScrollView containing the ListView.builder to take up the rest of the space left in the body.
thanks!
Use Expanded on ListView
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text(
'title',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
TextField(),
Expanded(
child: ListView.builder(
itemBuilder: (ctx, index) {
return Text("sds");
},
),
),
],
),
),

Columns shift when SingleChildScrollView is added Flutter

Need help. I have created a column on the page inside which there are 2 more columns, so I moved the buttons that are at the bottom to the very bottom so that they are always at the bottom of the screen. But when I add a SingleChildScrollView to make the page scroll, the space between the columns disappears and the bottom buttons move under other widgets. How can I solve the problem so that when adding a SingleChildScrollView, there is an empty space and the buttons remain at the very bottom of the screen?
body
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
const SizedBox(height: 121.0),
BackStepWidget(
text: 'Balance: $coins',
textStyle: constants.Styles.largeHeavyTextStyleWhite,
),
const Text(
'Buy JoinCoins',
style: constants.Styles.bigHeavyTextStyleWhite,
),
const Image(
image: AssetImage('assets/images/image.png'),
),
const Text('I Want To Buy',
style: constants.Styles.smallBoldTextStyleWhite),
const SizedBox(height: 10),
const CoinsCounterWidget(),
const SizedBox(height: 10),
const Text('JoynCoins',
style: constants.Styles.smallBoldTextStyleWhite),
],
),
Column(
children: [
Padding(
padding: const EdgeInsets.only(bottom: 24),
child: DefaultButtonGlow(
text: 'Buy me JoynCoins for 100% battery.',
color: constants.Colors.greyLight.withOpacity(0.4),
textStyle: constants.Styles.buttonTextStyle,
shadowColor: Colors.transparent,
borderColor: constants.Colors.purpleMain,
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return const DefaultAlertDialog(
text:
'Please set a payment method for buying JoynCoins.',
);
},
);
},
),
),
Padding(
padding: const EdgeInsets.only(bottom: 47),
child: DefaultButtonGlow(
text: 'Buy Now ',
color: constants.Colors.purpleMain,
textStyle: constants.Styles.buttonTextStyle,
shadowColor: constants.Colors.purpleMain,
borderColor: constants.Colors.purpleMain,
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return const DefaultAlertDialog(
text: "You'r about to buy",
isText2: true,
text2: '2500 JoynCoins',
);
});
},
),
)
],
)
],
),
));
Added SingleChildScrollView
Without SingleChildScrollView
You can simplify this code to understand the issue. MainAxisAlignment.spaceBetween will provide maximum spaces between widgets.
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("top"),
Text("bottom"),
],
),
Once you wrapped with SingleChildScrollView, Column takes minimum height for its children and become,
You can use SizedBox to provide space between items. You can use LayoutBuidler that I've posted on your previous question. For this I am using MediaQuery
body: SingleChildScrollView(
child: Column(
children: [
Text("top"),
SizedBox(
height: MediaQuery.of(context).size.height * .4,
), // you custom height
Text("bottom"),
],
),
),
Use SizedBox in between Columns or use the following inside Singlechildscrollview
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,

set left widget as focused one in flutter

I am using card_swiper widget in my project. It is a good library, but there is a problem: the focused widget always stays on centre but I want the focused item to be the one on the left. How can I accomplish this with this library?
In the below picture, focused item is on centre, but yellow item, in my case, should be on the left.
I found the answer which could be useful for others. The example is for 4 items on view but you can customise it to as many as you want:
Scaffold(
backgroundColor: AppColors.purpleDark,
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Flexible(
child: Swiper(
index: chosenIndex,
layout: SwiperLayout.CUSTOM,
physics: BouncingScrollPhysics(),
customLayoutOption: CustomLayoutOption(
startIndex: 0,
stateCount: math.min(4, listSize),
).addScale(
[3, 1, 1, 1], // there should be 4 widgets in view with the first 3 times larger
Alignment.topRight,
).addTranslate( // place the 4 items as I want
[
Offset(-35.toResizableWidth(), 0),
Offset(30.toResizableWidth(), 0.0),
Offset(118.toResizableWidth(), 0.0),
Offset(200.toResizableWidth(), 0.0),
],
),
itemWidth: 51.toResizableWidth(),
itemHeight: 51.toResizableHeight(),
controller: controller,
itemCount: listSize,
onIndexChanged: (newIndex) => setState(() => chosenIndex = newIndex),
itemBuilder: (context, index) {
return GestureDetector(
onTap: () => controller.next(),
child: Container(
width: 51.toResizableWidth(),
height: 51.toResizableHeight(),
color: Colors.grey,
child: Center(
child: Text(
'$index',
style: AppTextStyles.styleS16W600.copyWith(color: Colors.white),
),
),
),
);
},
),
),
Padding(
padding: EdgeInsets.symmetric(
vertical: 10.toResizableHeight(),
horizontal: 20.toResizableWidth(),
),
child: Text(
LocaleKeys.rewards_day.tr(args: <String>[chosenIndex.toString()]),
style: AppTextStyles.styleS20W600
.copyWith(color: true ? AppColors.greenPositive : AppColors.redNegative),
),
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: 20.toResizableWidth(),
),
child: Text(
longText,
style: AppTextStyles.styleS16W400.copyWith(color: AppColors.white100),
),
),
Expanded(child: Container()),
],
),
);