Flutter:在列表视图中停止滚动时更改顶部列表第一项的颜色
Flutter: change color for first item of the list in the top when stop scrolling in listview
我有下面的示例代码。
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),
),
),
);
},
),
),
);
}
}
截图:
如果看到上面的截图,I stop the scrolling 3x times
。
- 首先,初始时(打开此屏幕),顶部列表的第一项是
index 0
- 其次,当我停下来时,顶部列表的第一项是
index 13
- 第三,当我停下来时,顶部列表的第一项是
index 17
。
所以当我滚动列表并停止时,first item of the list in the top
应该更改为green
,其他的是white
。
对于上面的屏幕截图(示例)我停止了 3 次并且 first item of the list in the top
在索引 0, 13, 17
中,所以它变成了绿色。
我不确定我是否理解你的意思。但试试这个:
class ExampleScroll extends StatefulWidget {
const ExampleScroll({Key? key}) : super(key: key);
@override
_ExampleScrollState createState() => _ExampleScrollState();
}
class _ExampleScrollState extends State<ExampleScroll> {
Timer? timer;
ScrollController controller = ScrollController();
@override
void initState() {
controller.addListener(() {
if (timer != null) {
timer!.cancel();
timer = Timer(Duration(milliseconds: 300), () {
setState(() {
timer = null;
});
});
} else {
timer = Timer(Duration(milliseconds: 300), () {
setState(() {
timer = null;
});
});
}
setState(() {});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: ListView.builder(
itemCount: 20,
controller: controller,
itemBuilder: (context, index) {
return Card(
child: Container(
height: 100,
color: timer == null
? Colors.black
: Colors
.green, // I want change this color only for first item
alignment: Alignment.center,
child: Text(
index.toString(),
style: const TextStyle(
fontSize: 36.0, fontWeight: FontWeight.bold),
),
),
);
},
),
),
);
}
}
在此代码中。所有瓷砖都会变色。仅更改顶部瓷砖。我建议使用 VisibilityDetector
1.使用 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),
),
),
);
},
),
),
);
}
}
参考文献:
2。使用 Area
我有下面的示例代码。
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),
),
),
);
},
),
),
);
}
}
截图:
如果看到上面的截图,I stop the scrolling 3x times
。
- 首先,初始时(打开此屏幕),顶部列表的第一项是
index 0
- 其次,当我停下来时,顶部列表的第一项是
index 13
- 第三,当我停下来时,顶部列表的第一项是
index 17
。
所以当我滚动列表并停止时,first item of the list in the top
应该更改为green
,其他的是white
。
对于上面的屏幕截图(示例)我停止了 3 次并且 first item of the list in the top
在索引 0, 13, 17
中,所以它变成了绿色。
我不确定我是否理解你的意思。但试试这个:
class ExampleScroll extends StatefulWidget {
const ExampleScroll({Key? key}) : super(key: key);
@override
_ExampleScrollState createState() => _ExampleScrollState();
}
class _ExampleScrollState extends State<ExampleScroll> {
Timer? timer;
ScrollController controller = ScrollController();
@override
void initState() {
controller.addListener(() {
if (timer != null) {
timer!.cancel();
timer = Timer(Duration(milliseconds: 300), () {
setState(() {
timer = null;
});
});
} else {
timer = Timer(Duration(milliseconds: 300), () {
setState(() {
timer = null;
});
});
}
setState(() {});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: ListView.builder(
itemCount: 20,
controller: controller,
itemBuilder: (context, index) {
return Card(
child: Container(
height: 100,
color: timer == null
? Colors.black
: Colors
.green, // I want change this color only for first item
alignment: Alignment.center,
child: Text(
index.toString(),
style: const TextStyle(
fontSize: 36.0, fontWeight: FontWeight.bold),
),
),
);
},
),
),
);
}
}
在此代码中。所有瓷砖都会变色。仅更改顶部瓷砖。我建议使用 VisibilityDetector
1.使用 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),
),
),
);
},
),
),
);
}
}
参考文献:
2。使用 Area