ListView.builder with Wrap widget duplicates data - flutter

I have a list which contains days. I displayed this list of days using Wrap widget in a ListView.builder, the data displays but it duplicates...
How can I remove the duplications?
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: days == null ? 0 : days.length,
itemBuilder: (BuildContext context, int index) {
return Wrap(
children: <Widget>[
...days.map((date) {
return Container(
width: MediaQuery.of(context).size.width / 2.4,
decoration: const BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(20.0)),
color: Colors.white,
),
child: ListTile(
onTap: () {
Navigator.pushNamed(context, '/logEntry');
},
title: const DefaultText(
size: 18,
text: "Day 1",
color: Colors.green,
weight: FontWeight.w500,
),
subtitle: DefaultText(
size: 15,
text: "${date.day}/${date.month}/${date.year}"
.toString(),
color: Colors.green,
weight: FontWeight.w500,
),
trailing: const Icon(Icons.arrow_forward_ios),
),
);
}).toList(),
],
);
},
),

You don't need to use ListView.builder like with wrap like this. You can shift to ListView just to handle height-overflow.
ListView(
children: [
Wrap(),
],
),

Related

Flutter: Make all screen scrollable with GridView.builder inside

In my home screen my app shows carousel first then a vertical list of challenges cards retrieved from Cloud Firestore using GridView.builder as follows:
GridView.builder(
scrollDirection: Axis.vertical,
itemCount: _challenges.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 4),
),
itemBuilder: (context, index) {
return InkWell(
onTap: () {
if (_challenges[index]["isLocked"] == "true") {
showLockedDialog();
} else {
checkParticipation(index);
if (checkPart == true) {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) =>
ChallengeDetails(_challenges[index])));
}
checkPart = true;
}
},
child: Stack(
children: [
Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image(
image: NetworkImage(_challenges[index]["image-path"]),
fit: BoxFit.cover,
height: 150,
width: 350,
opacity: _challenges[index]["isLocked"] == "true"
? AlwaysStoppedAnimation(.4)
: null,
),
),
),
Center(
child: Text(
"${_challenges[index]["name"]}\n",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
),
),
Center(
child: Text(
"\n${_challenges[index]["date"]}",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
textDirection: TextDirection.ltr,
)),
Center(
child: SizedBox(
height: 130,
width: 130,
child: _challenges[index]["isLocked"] == "true"
? Image.asset("assets/lock-icon.jpg")
: null,
),
)
],
),
);
});
Everything retrieving fine and it is rendered in my home_screen as follows:
body: Column(
children: [
AdsBanner(),
SizedBox(
height: 30,
),
Padding(
padding: const EdgeInsets.only(right: 8, left: 8, bottom: 5),
child: Row(
children: [
Text(
AppLocalizations.of(context)!.challenges + " ",
style: TextStyle(fontSize: 20),
),
Text(
AppLocalizations.of(context)!.clickToParticipate,
style: TextStyle(fontSize: 15),
)
],
),
),
Expanded(child: ChallengeCard()),
],
),
The problem is that only the GridView area is scrolling and what am seeking for is to scroll the whole screen with the GridView area, I was trying to use the CustomScrollView() but its not working properly.
I'll be thankful for any help.
First in your GridView.builder add these:
GridView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
...
)
then in your home_screen wrap your column with SingleChildScrollView:
SingleChildScrollView(
child: Column(
children: [
AdsBanner(),
SizedBox(
height: 30,
),
Padding(
...
),
),
You can provide physics: NeverScrollableScrollPhysics() on GridView to disable scroll effect. If you want scrollable as secondary widget use primary: false, to have Full Page scrollable, you can use body:SingleChildScrollView(..) or better using body:CustomScrollView(..)

Prevent ExpansionTile from expanding beyond viewport/screen

I'm trying to build a screen where there are two lists containing items fetched from an API. I want to use an ExpansionTile for each list to present the data to the user so that the user can decide which data he wants to access.
As the data comes from an API it might be that the data present in a list is more than what fits on the screen, thus I'd like the ExpansionTile to be scrollable inside (I don't want the page to be scrollable but the ExpansionTile Widget!!!)
Currently if I expand the ExpansionTile this is the problem I'm facing if there's too much data to display within the ExpansionTile:
However, I'd like the UI to look something like this:
How can I limit the ExpansionTiles to the boundaries of the screen and force them to be scrollable if they overflow? Currently I use a ListView.builder and also tried nesting it inside a SingleChildScrollView but that didn't help.
This is how my code for this screen looks right now (which is only the inner part wrapped between the AppBar and BottomNavigationBar because they belong to the screen providing the PageView):
class MembershipScreen extends StatefulWidget {
const MembershipScreen({Key? key}) : super(key: key);
#override
_MembershipScreenState createState() => _MembershipScreenState();
}
class _MembershipScreenState extends State<MembershipScreen> {
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Center(
child: Container(
constraints: BoxConstraints(maxWidth: 500),
padding: EdgeInsets.symmetric(horizontal: 40, vertical: 40),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Clubs',
style: kHeadingStyle,
),
SizedBox(
height: 20,
),
_buildMyClubs(),
SizedBox(
height: 20,
),
_buildAllClubs(),
],
),
),
),
);
}
Widget _buildMyClubs() {
return Container(
decoration: BoxDecoration(
color: kPrimarySwatch,
border: Border.all(
color: kSecondarySwatch,
width: 2,
),
borderRadius: BorderRadius.circular(25)
),
child: Theme(
data: ThemeData().copyWith(dividerColor: Colors.transparent),
child: ExpansionTile(
initiallyExpanded: false,
title: Text("My Clubs", style: kLabelStyle,),
children: [
SingleChildScrollView(
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
itemCount: 4,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text("Test", style: kHintTextStyle,),
);
},
),
)
],
),
),
);
}
Widget _buildAllClubs() {
return Container(
decoration: BoxDecoration(
color: kPrimarySwatch,
border: Border.all(
color: kSecondarySwatch,
width: 2,
),
borderRadius: BorderRadius.circular(25)
),
child: Theme(
data: ThemeData().copyWith(dividerColor: Colors.transparent),
child: ExpansionTile(
initiallyExpanded: false,
title: Text("All Clubs", style: kLabelStyle,),
children: [
SingleChildScrollView(
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
itemCount: 8,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text("Test", style: kHintTextStyle,),
);
},
),
)
],
),
),
);
}
}
I'd really appreciate any help as I don't have any idea what I could try to solve this issue now. If anything is still unclear please let me know and I will try to provide the missing information asap.

how to style the Horizontal scroll bar according to this UI flutter

This is my code for the horizontal scrollbar. how to style this according to given UI. where and how I should add styles on this code. the code is showing how I placed the scroll bar in my home. dart. need suggestions to add styles.
home.dart.
body: ListView(
children: [
buildSearchInput(),
Padding(
padding: const EdgeInsets.only(top: 40, left: 20, right: 20),
child: Column(
children: [
SizedBox(
height: kToolbarHeight,
child: ListView(
scrollDirection: Axis.horizontal,
children: List.generate(4, (index) => Text("item $index")),
),
),
],
),
)
,
You can use Container with StadiumBorder to decorate them and using ListView.separated to have space between items.
final List<String> data = ["item A", "Item Number 2", "new One"];
Widget itemW({
required String text,
required Color bgcolor,
required Color textColor,
}) {
return Container(
padding: const EdgeInsets.all(16),
alignment: Alignment.center,
decoration: ShapeDecoration(
shape: const StadiumBorder(),
color: bgcolor,
),
child: Text(
text,
style: TextStyle(color: textColor),
),
);
}
....
ListView.separated(
itemCount: data.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) =>
itemW(color: Colors.cyanAccent,
bgcolor: Colors.cyanAccent,
text: data[index]),
separatorBuilder: (context, index) {
return const SizedBox(
width: 10,
);
},
),

Extra "Space" In ListView and Card Flutter

I'm having this "extra space" on my first listview item that is a card being encapsulated in a container.
How do I remove it?
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(15.0),
height: 300,
child: Column(children: [
Row(children: [
Expanded(
child: Text("Lowest Fuel Price",
style: TextStyle(
fontWeight: FontWeight.w500,
color: Theme.orange3,
fontSize: 16.0)))
]),
Container(
height: 250,
child: Card(
elevation: 3,
child: ListView.builder(
itemCount: cheapest.length,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
final item = cheapest[index];
return Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text(
item.petrolType,
style: TextStyle(
color: Theme.gray1, fontSize: 18),
),
Text(
"\$" + item.petrolPrice,
style: TextStyle(
color: Theme.gray1, fontSize: 25),
),
Image(
fit: BoxFit.fill,
image: new AssetImage(
'assets/images/fuel_station/' +
item.petrolStation.toLowerCase() +
'.png')),
]),
index != cheapest.length - 1
? Divider(
color: Colors.grey,
)
: Divider(color: Colors.white)
],
);
})),
)
]));
}
https://api.flutter.dev/flutter/widgets/ListView-class.html
By default, ListView will automatically pad the list's scrollable extremities to avoid partial obstructions indicated by MediaQuery's padding. To avoid this behaviour, override with a zero-padding property.
Card(
elevation: 3,
child: MediaQuery.removePadding(
context: context,
removeTop: true,
child: ListView.builder(),
),
),

Adding Json Image to ListTile

I have a simple json parser and listing the news and their categories
now I am trying to do some optimisations on ListTile because I would like to use the news Images bigger and put the news title under but ListTile provide only trailing which it is unusable for me. But I can't add any styling in whole code (new child, Row, etc gives error.) Is it possible to do that in this structure or should I make a customListTile on another page and link the current mechanism to new page?
any help would be really nice
body: Container(
padding: const EdgeInsets.all(
10.0,
),
child: FutureBuilder<Articles>(
future: _futureArticles,
builder: (BuildContext context, AsyncSnapshot<Articles> snapshot) {
if (snapshot.hasData) {
final articles = snapshot.data?.data;
return ListView.builder(
padding: const EdgeInsets.all(
10.0,
),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: articles!.length,
itemBuilder: (BuildContext context, int index) {
return Card(
elevation: 4.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: ListTile(
title: Text(
'Title: ${articles[index].title}',
),
subtitle:
Text('Category: ${articles[index].category?.name}'),
trailing: Image.network(articles[index].imageUrl!),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NewsViewDetail(
id: articles[index].id!,
),
fullscreenDialog: true,
),
);
},
),
);
},
);
} else if (snapshot.hasError) {
return NewsError(
errorMessage: '${snapshot.hasError}',
);
} else {
return const NewsLoading(
text: 'Loading...',
);
}
},
),
),
);
}
}
Try below answer hope its help to you ,use GridView.builder() instead of ListView.builder()
Container(
padding: EdgeInsets.all(10),
child: GridView.builder(
itemCount: 5,//use your length here(articles!.length)
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 1),
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade200),
),
margin: EdgeInsets.all(5),
padding: EdgeInsets.all(5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: Image.network(
'your network image here',
fit: BoxFit.fill,
),
),
SizedBox(
height: 15,
),
Text(
'Your headline here',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
],
),
);
},
),
);
your screen look like ->