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.