Newbie here. I have managed to implement a ListView that simply displays images. However the ListView isn't scrollable. I have attempted to wrap it in SingleChildScrollView, have added physics to AlwaysScrollableScrollPhysics and also tried removing Expand widgets from the layout. What am I missing?
LAYOUT
return Scaffold(
body: SingleChildScrollView(
child: Column(children: [
SizedBox(
height: 6,
),
StreamBuilder(
stream: ref.onValue,
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData &&
!snapshot.hasError &&
snapshot.data.snapshot.value != null) {
lists.clear();
DataSnapshot dataValues = snapshot.data.snapshot;
Map<dynamic, dynamic> values = dataValues.value as Map;
values.forEach((key, values) {
lists.add(values);
});
return new ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: lists.length,
itemBuilder: (BuildContext context, int index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Card(
margin: EdgeInsets.fromLTRB(2, 2, 2, 2),
elevation: 20,
child: GestureDetector(
onTap: () {
String imageurl = lists[index]["image"];
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FullScreenImageViewer(
imagurl: imageurl,
),
));
},
child: Padding(
padding: EdgeInsets.all(5),
child: Container(
width: 400,
child: Image(
image:
NetworkImage(lists[index]["image"]),
),
),
),
),
),
],
);
},
);
}
return Container();
},
),
]),
),
);
You can remove the single child scroll view, i believ the problem here is because you are using a column and the listview is not expanding to the whole screen. If you want to make sure the listview occupy the all the space remaining you can use the Flex and expanded widget.
Flex can work like a column or row depending on which direction you are providing it with. anything that is placed here behave exactly like when they is placed in the column or row except for Expanded, as they fill the remainning space.
I've changed your code a bit here to accomodate the Flex and Expanded widget (you just need to readd your logic and the streambuilder to make it work)
return Scaffold(
body: Flex(direction: Axis.vertical, children: [
const SizedBox(
height: 6,
),
Expanded(
// Change the children to stream builder if neccesary
child: ListView.builder(
shrinkWrap: true,
itemCount: 5,
itemBuilder: (BuildContext context, int index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Card(
margin: const EdgeInsets.all(2),
elevation: 20,
child: GestureDetector(
onTap: () {
// ACTION HERE
},
child: const Padding(
padding: EdgeInsets.all(5),
child: Image(
image: NetworkImage("https://picsum.photos/200/300"),
),
),
),
),
],
);
},
),
)
]),
);
There's a property within listView() that tells it which irection the overflow is so as to scroll. Set it to
scrollDirection: Axis.horizontal
Related
After many attempts and trying different things, I get the same error ( throw constraintsError ) as soon as I add Expanded, while the error disappears by deleting it,, i I want the upper part to be fixed and the other part to be Scrollable
thanks
SingleChildScrollView(
child: Column(
children: [
Column(
children: [
Container(), // fixed
Row(), // fixed
**Expanded**(
child: Container(
color: constants.kLightGrayColor,
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
controller: controller.scrollController,
itemCount: data.posts.length,
itemBuilder: (context, index) {
firstly cannot used Expanded inside SingleChildScrollView.
to work normally pls remove SingleChildScrollView widget and remove outer Column,
used one of Column in green box.
it is small example
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
Container(
height: 200,
width: MediaQuery.of(context).size.width,
color: Colors.red,
child: const Center(child: Text("Fixed Box")),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: 20,
itemBuilder: (context, index) {
return ListTile(
title: Text("$index"),
);
},
),
),
],
),
);
}
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
I am trying to create a horizontally scrollable list of cards but it breaks each. I am just not sure where I am going wrong. I tried adding Expandable in several places and I still get errors.
I am hoping this is resolvable or do I need to separate each element within the Container/Column (2nd one).
It is definitely some sort of sizing I am missing but just not able to pinpoint where.
body: SafeArea(
child: Column(
children: [
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(...),
Padding(...),
Padding(...),
SizedBox(...),
Padding(...),
SizedBox(...),
Padding(...),
SizedBox(...),
Container(
height: 200,
color: Colors.blue[200],
child: ListView(
shrinkWrap: true,
physics: ScrollPhysics(),
scrollDirection: Axis.vertical,
children: [
FutureBuilder(
future: getAudioList(),
builder: (context, data) {
if (data.hasError) {
return Center(child: Text("${data.error}"));
} else if (data.hasData) {
var items = data.data as List<MyOtherFunc>;
var categories;
//Split into categories
if (items != null) {
categories = groupBy(
items, (MyOtherFunc ma) => ma.category);
Map<String, List<MindfulAudio>> catMap =
categories;
return new ListView.builder(
padding:
const EdgeInsets.fromLTRB(8, 0, 8, 0),
itemCount: catMap.length,
physics:
const AlwaysScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, index) {
String key = catMap.keys.elementAt(index);
return Card(
child: ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
MyFunc(
catMap[key], key),
),
);
},
leading: Icon(icons[index],
size: 25, color: colour[index]),
title: new Text("$key"),
trailing: new IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
MyFunc(
catMap[key], key),
),
);
},
icon: Icon(
FontAwesomeIcons.chevronRight,
color: PINK,
)),
),
);
},
);
}
return Center(
child: CircularProgressIndicator(),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
],
),
),
],
),
),
],
),
),
Try this layout
SizedBox(
height: MediaQuery.of(context).size.height,
width : MediaQuery.of(context).size.width,
child: SingleChildScrollView (
child: Column(
children: [
//Other widgets which will scroll vertically in the column
SingleChildScrollView (
scrollDirection: Axis.horizontal,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
//Items you wish to scroll horizontally
]
)
),
//Some more widgets if you wish to add below the horizontal scroll
]
)
)
)
I am trying to learn how to create complex UI elements in flutter and faced this problem. Suppose I want to put a pageview in my listView and display the same items as in the horizontal scrolling list. Is there any way to do this?
Here is my code of build method with listview:
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: _catList.length,
itemBuilder: (context, index) {
return Card(
child: Column(
children: [
Card(
child: ListTile(
title: Text(_catList[index].name),
),
),
IntrinsicWidth(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: Column (
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text ('ID: ${_catList[index].id}'),
Text ('Country code: ${_catList[index].countryCodes}'),
Text ('Temperament: ${_catList[index].temperament}'),
Text ('Origin: ${_catList[index].origin}')
],
)
),
Expanded(
child: Card(
child: Text(_catList[index].description),
),
)
],
),
),
Container (
child: PageView.builder (itemBuilder: (context, index) {
} ),
)
],
),
);
},
);
}
As i under stand you want to add PageView in side ListView. So your ListView scroll in vertical direction and your PageView scroll in horizontal direction. If i am not wrong then below is my code to do the same things.
I have made my List which contain multiple List like below.
var modelListOne = ["model_1_1.png", "model_1_2.png",];
var modelListTwo = ["model_2_1.png", "model_2_2.png",];
var modelList = [modelListOne, modelListTwo,];
return ListView.builder(
itemCount: modelList.length,
itemBuilder: (context, index) {
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => YOURPAGE());
},
child: Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Container(
height: 350,
width: double.maxFinite,
child: PageView.builder(
itemCount: modelList[index].length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, pageIndex) {
return Container(
height: 300,
width: double.maxFinite,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
"assets/images/${modelList[index][pageIndex]}",
),
fit: BoxFit.cover)),
);
}),
)),
),
);
});
Make changes regarding to your requirements. Thanks.
I cannot seem to get my screen to scroll. I have tried a few variations of the following code but I have not been able to get it to work. I also tried it with a ListView that did not work very well either. Admittedly, I did not try to troubleshoot the ListView for very long because I was assuming the issue was being caused by something else. I have looked on SO and seen a few questions about this topic and they helped me fix some issues, but I cannot seem to get it to work. I do not get any error messages or anything, my screen simply does not scroll. Below you will see the general layout of my code. What am I doing wrong?
class _TripPackagesState extends State<TripPackages> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Container(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(...),
GestureDetector(...),
],
),
),
),
Container(
margin: EdgeInsets.only(top: 1.0),
child: SingleChildScrollView(
child: StreamBuilder<QuerySnapshot>(
stream:
Firestore.instance.collection('trip_package').snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> docSnapshot) {
if (!docSnapshot.hasData) return const Text('Loading...');
final int docCount = docSnapshot.data.documents.length;
return GridView.builder(
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: docCount,
itemBuilder: (_, int index) {
DocumentSnapshot document =
docSnapshot.data.documents[index];
return GestureDetector(
child: Container(
margin: EdgeInsets.all(3.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(...),
Row(...),
],
),
),
);
},
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(...),
);
},
),
),
),
],
),
);
}
}
Try using primary: false in your GridView.builder