Issue
I have the example code below.
class ExampleScroll extends StatefulWidget {
const ExampleScroll({Key? key}) : super(key: key);
@override
_ExampleScrollState createState() => _ExampleScrollState();
}
class _ExampleScrollState extends State<ExampleScroll> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: ListView.builder(
itemCount: 20,
itemBuilder: (context, index) {
return Card(
child: Container(
height: 100,
color: //TODO: change the color only first item of the list when stoping the scroll
alignment: Alignment.center,
child: Text(
index.toString(),
style:
const TextStyle(fontSize: 36.0, fontWeight: FontWeight.bold),
),
),
);
},
),
),
);
}
}
If see the above screenshot, I stop the scrolling 3x times.
- First, when the initial (open this screen), the first item of the list in the top is
index 0 - Second, when I stop and the first item of the list in the top is
index 13 - Third, when I stop and the first item of the list in the top is
index 17.
So when I scroll the list and stop, first item of the list in the top should be change to green, and the others is white.
For above screenshot (example) I stop 3x times and the first item of the list in the top is in the index 0, 13, 17, so it's change to green.
Solution
1. Using ScrollController
class ExampleScroll extends StatefulWidget {
const ExampleScroll({Key? key}) : super(key: key);
@override
_ExampleScrollState createState() => _ExampleScrollState();
}
class _ExampleScrollState extends State<ExampleScroll> {
late ScrollController _scrollController;
final int _itemCount = 20;
int _cardPosition = 0;
void _scrollListenerWithItemCount() {
int itemCount = _itemCount;
double scrollOffset = _scrollController.position.pixels;
double viewportHeight = _scrollController.position.viewportDimension;
double scrollRange = _scrollController.position.maxScrollExtent -
_scrollController.position.minScrollExtent;
int firstVisibleItemIndex =
(scrollOffset / (scrollRange + viewportHeight) * itemCount).floor();
if (_scrollController.position.atEdge) {
bool isTop = _scrollController.position.pixels == 0;
if (isTop) {
_cardPosition = 0;
} else {
_cardPosition = firstVisibleItemIndex + 1;
}
} else {
_cardPosition = firstVisibleItemIndex + 1;
}
setState(() {});
}
@override
void initState() {
super.initState();
_scrollController = ScrollController();
_scrollController.addListener(_scrollListenerWithItemCount);
}
@override
void dispose() {
super.dispose();
_scrollController.removeListener(_scrollListenerWithItemCount);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: ListView.builder(
controller: _scrollController,
itemCount: _itemCount,
itemBuilder: (context, index) {
return Card(
child: Container(
height: 100,
color: _cardPosition == index ? Colors.green : Colors.white,
alignment: Alignment.center,
child: Text(
index.toString(),
style: const TextStyle(
fontSize: 36.0, fontWeight: FontWeight.bold),
),
),
);
},
),
),
);
}
}
References:
- https://github.com/flutter/flutter/issues/19941#issuecomment-522587489
- https://stackoverflow.com/a/54539182/8291686
2. Using Area
package: https://pub.dev/packages/inview_notifier_list
Answered By - R Rifa Fauzi Komara



0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.