Make the ListView.builder() show a fraction of the next (or previous) element - flutter

How can Make the ListView.builder() show a fraction of the next (or previous) element.
I have a ListView.builder() and it works fine but I want the user to know that there is a scrolling functionality and that they need to scroll.
How can achieve that?
My output:-
Expected output:-
How can achieve that?
Here is my code
return FutureBuilder(
future: categories,
builder: (BuildContext context, AsyncSnapshot snapshot) {
return ListView.builder(
itemCount: snapshot.data.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return GestureDetector(
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Container(
child: Padding(
padding:
const EdgeInsets.fromLTRB(16.0, 7.0, 16.0, 10.0),
child: Text(
snapshot.data[index].name,
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
fontWeight: FontWeight.bold),
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
color: colors[index],
),
),
),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Posts(
type: PostsFetchByType.categories,
categoryOrTagIds: [snapshot.data[index].id],
))),
);
});
});

Create a scrollcontroller with an initial offfset:
scrollController = ScrollController(
initialScrollOffset: 10 // put your value here
);
then add it to your ListViewBuilder:
return ListView.builder(
...
controller: scrollController,
...
)
But since you want to show that it is scrollable, you can also have a look at adding scrolling bar by wrapping ListViewBuilder as follows:
Scrollbar(
child: ListView.builder(...),
)

Related

Working with Tap function within LIstView

I was testing the "tap function" for items within a ListView, but it does not seem to work. The print function does not work when I tap upon the list.
return Scaffold(
appBar: AppBar(
// App Bar
title: Text(
"ListView On-Click Event",
style: TextStyle(color: Colors.grey),
),
elevation: 0,
backgroundColor: Colors.white,
),
// Main List View With Builder
body: ListView.builder(
itemCount: imgList.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
print("button pressed");
print(index);
},
child: Container(
margin: const EdgeInsets.symmetric(
vertical: 2.0,
horizontal: 8.0,
),
child: Stack(
children: <Widget>[
cardDesign,
cardImage,
],
),
),
); // gesturedetector
}));
Where am I going wrong?
Try to used Column instead of Stack
ListView.builder(
shrinkWrap: true,
itemCount: 10,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
print("button pressed");
print(index);
},
child: Container(
margin: const EdgeInsets.symmetric(
vertical: 2.0,
horizontal: 8.0,
),
child: Column(
children: <Widget>[
Text(index.toString()),//put your widgets here
],
),
),
); // gesturedetector
}),
you can use ListTile inside ListView,because ListTile have onTap function, same here :
ListView.builder(
itemCount: data.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: ListTile(
title: Text('TextHere'),
onTap: () {
log('on tap');
},
),
);
});

Flutter HiveDB deleting from database

In documentation of Hive we have delete method for deleting something from database, but this method don't delete from database and it only do null on index of found data and it cause some problem when we want to listen to database changes or making ListView with null data,
another problem is .values that return non-nullable data and when we try to make a ListView we get null error
late Box<Sal> _sal;
useEffect((){
_sal = Hive.box<Sal>('sal') ;
});
// ...
ValueListenableBuilder(
valueListenable: _sal.listenable(),
builder: (_, Box<Sal> sal, __) => ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: EdgeInsets.zero,
itemBuilder: (context, index) {
return Container(
height: 50.0,
margin: EdgeInsets.symmetric(vertical: 0.0),
child: Card(
color: DefaultColors.$lightBrown,
child: Row(
children: [
CText(
text: _sal.get(index)!.salName,
color: Colors.white,
style: AppTheme.of(context).thinCaption(),
).pOnly(right: 16.0),
const Spacer(),
IconButton(
icon: Icon(
Icons.edit,
color: Colors.yellow,
),
onPressed: () => showGeneralDialog(
//...
),
),
IconButton(
icon: Icon(
Icons.delete,
color: Colors.white,
),
onPressed: () => showGeneralDialog(
//...
),
),
],
),
),
);
},
itemCount: _sal.values.length,
),
).pSymmetric(
h: 16,
),
//...
}
I found solution for this problem
late Box<Sal> _sal;
late List<Sal> _data;
useEffect(() {
_sal = Hive.box<Sal>('sal');
_data = _sal.values.toList();
});
//...
ValueListenableBuilder(
valueListenable: Hive.box<Sal>('sal').listenable(),
builder: (_, Box<Sal> sal, __) {
_data = _sal.values.toList();
return ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: EdgeInsets.zero,
itemBuilder: (context, index) {
return Container(
height: 50.0,
margin: EdgeInsets.symmetric(vertical: 0.0),
);
},
itemCount: _data.length,
);
},
),
//...

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 ->

FutureBuilder is not detecting no data

I need to show a message when no data is found in the response.I get the response like this [] when there is not data.How to handle when the future is empty.I went through many post and tried but when i try them either the error message is displayed or the data is displayed.\
future: _future,
builder: (BuildContext context, AsyncSnapshot snapshot) {
debugPrint("HAs data");
return ListView.builder(
itemExtent: 80,
itemCount: myList.length,
itemBuilder: (BuildContext context, int i) {
return Card(
child: ListTile(
onTap: () {Navigator.push(context, MaterialPageRoute(builder: (context) =>DisplayReports(appointmentDetail:myList[i])));},
contentPadding: EdgeInsets.symmetric(
horizontal: 10.0, vertical:5.0),
leading: Container(
padding: EdgeInsets.only(right: 8.0),
decoration: new BoxDecoration(),
child: Icon(Icons.date_range,color: Colors.blueGrey,)
),
title: Text(
myList[i].doctorName,
style: TextStyle(fontSize: 20.0,
color: Colors.black, fontWeight: FontWeight.bold),
),
subtitle: Row(
children: <Widget>[
Text(
myList[i].apptDateTime != null ?
formatDate(DateTime.parse(myList[i].apptDateTime), [
dd, '/', M,'/',yyyy]) : " ",
overflow: TextOverflow.ellipsis,
maxLines: 1,
softWrap: false,
style: TextStyle(fontSize: 12, color: Colors.black54,),
),
],
),
trailing: IconButton(icon: Icon(Icons.more_vert),onPressed: (){},),
),
);
return LinearProgressIndicator();
});
},
You can achieve by checking how much elements is in list.
i hope following code help you.
future: _future,
builder: (BuildContext context, AsyncSnapshot snapshot) {
debugPrint("HAs data");
// here check is length of data is 0 then return specific widget which you want to return as i demonstrate with text widget.
if(myList.length==0){
return Text("You have not data");
}
return ListView.builder(
itemExtent: 80,
itemCount: myList.length,
itemBuilder: (BuildContext context, int i) {

Scroll through Flutter Bottom Sheet

I'm using a Flutter modal bottom sheet to display some options for the user to select.
I have a Column with a list of ListTiles as the content of the bottom sheet.
My problem is that if I have more than 6 ListTiles, some are cut off and not displayed.
Is there a way to make the bottom Sheet scrollable?
Just change your Column into a ListView, like so:
return ListView(
children: <Widget>[
...
]
);
What if I don't want the content of the sheet to be scrolled, but the sheet itself?
If you want the user to be able to swipe up the bottom sheet to fill the screen, I'm afraid this isn't possible in the current implementation of the modular bottom sheet.
I've found a solution implementing the code below
void _showBottomSheet(BuildContext context) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) {
return GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Container(
color: Color.fromRGBO(0, 0, 0, 0.001),
child: GestureDetector(
onTap: () {},
child: DraggableScrollableSheet(
initialChildSize: 0.4,
minChildSize: 0.2,
maxChildSize: 0.75,
builder: (_, controller) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(25.0),
topRight: const Radius.circular(25.0),
),
),
child: Column(
children: [
Icon(
Icons.remove,
color: Colors.grey[600],
),
Expanded(
child: ListView.builder(
controller: controller,
itemCount: 100,
itemBuilder: (_, index) {
return Card(
child: Padding(
padding: EdgeInsets.all(8),
child: Text("Element at index($index)"),
),
);
},
),
),
],
),
);
},
),
),
),
);
},
);
}
If you want a model bottom sheet that can be scrolled.
You can use the isScrollControlled attribute of showModalBottomSheet to achieve the effect.
If you want a persistent bottom sheet that can be scrolled.
You can use the DraggableScrollableSheet
Example:
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('DraggableScrollableSheet'),
),
body: SizedBox.expand(
child: DraggableScrollableSheet(
builder: (BuildContext context, ScrollController scrollController) {
return Container(
color: Colors.blue[100],
child: ListView.builder(
controller: scrollController,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text('Item $index'));
},
),
);
},
),
),
);
}
}
Here is the official video from the Flutter team.
A live demo on DartPad can be found here.
Almost the same solution like this one but without the unnecessary layers of gesture detectors etc.
The important part is the expand: false, in DraggableScrollableSheet, because it defaults to true. This causes the bottom sheet to expand to full height in default config. With this set to false there is no need to wrap the bottom sheet with two gesture detectors to detect the outside tap.
Also in this case only one shape is required.
showModalBottomSheet(
context: context,
isScrollControlled: true,
isDismissible: true,
shape: const RoundedRectangleBorder(
borderRadius:
BorderRadius.vertical(top: Radius.circular(16))),
builder: (context) => DraggableScrollableSheet(
initialChildSize: 0.4,
minChildSize: 0.2,
maxChildSize: 0.75,
expand: false,
builder: (_, controller) => Column(
children: [
Icon(
Icons.remove,
color: Colors.grey[600],
),
Expanded(
child: ListView.builder(
controller: controller,
itemCount: 100,
itemBuilder: (_, index) {
return Card(
child: Padding(
padding: EdgeInsets.all(8),
child: Text("Element at index($index)"),
),
);
},
),
),
],
),
),
);