这是 ListView.builder 小部件,其中 ui 实现调用尝试将 ListView.builder 移动到特定索引,但它仅在我没有手动交互滚动时才有效,否则它不会滚动到该索引
Container(
height: 70,
margin:
EdgeInsets.only(left: 0, top: 20),
child: ListView.builder(
controller: _scrollController,
// physics: const ClampingScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: lotsData.length,
itemBuilder: (BuildContext context,
int index) {
// var price = "";
// var title = "";
// if (lotsData[index].lotState == "CLOSED") {
// title = "Closed";
// price = "Lot No: ${lotsData[index].lotNo}";
// } else if (lotsData[index].lotState == "AUCTION") {
// title = "Auction";
// price = "Lot No: ${lotsData[index].lotNo}";
// } else {
// if (lotsData[index].bidInfo.isNotEmpty) {
// if (lotsData[index].bidInfo.first.maxBidderId ==
// Provider.of<ModelTheme>(context, listen: false).userId.toString()) {
// title = "You Win";
// price = "${themeNotifier.currencyCode} ${(lotsData[index].bidInfo.first.maxBidAmount * themeNotifier.currencyRate).toStringAsFixed(2)} ";
// } else {
// title = "Sold";
// price = "${themeNotifier.currencyCode} ${(lotsData[index].bidInfo.first.maxBidAmount * themeNotifier.currencyRate).toStringAsFixed(2)} ";
// }
// }
// }
return GestureDetector(
onTap: () {},
child: ClosingLotCard(
closingUi: true,
lotStatus: lotsData[index]
.lotState,
price:
"Lot No: ${lotsData[index].lotNo}",
border:
lotsData[index].id ==
data?.id,
title: lotsData[index]
.price
.toString(),
image: lotsData[index]
.photos
.isNotEmpty
? "${imageUrl}${lotsData[index].photos.first}"
: '',
));
}),
),
我在滚动到特定索引时遇到问题,如果我没有使用手势滚动,它工作正常,但是当我通过手势滚动列表到任何其他索引时,_scrollController.animateTo 无法正常工作,我如何解决此问题
void _scrollToIndex(int index) async {
if (_scrollController.hasClients) {
_scrollController.animateTo(
index * 100,
duration: Duration(seconds: 1),
curve: Curves.easeInOut);
}
}
出现此问题的原因是,当您滚动
ListView
用手指滑动时,它会停止或取消animateTo
功能。
这是因为控制滚动的
ScrollController
被您的手动滚动打断了。
我们可以做一些改变来解决这个问题,
在addListener
上使用
ScrollController
添加监听器来检测
当用户手动与 ListView
交互时。一旦
交互结束,允许 animateTo 恢复工作。
确保正确的索引定位验证您所在的索引 根据项目的大小正确计算滚动到 在你的
ListView
。对于水平滚动,您可能需要考虑
每个项目的宽度,包括填充或边距。
看下面的代码并尝试一下,
late ScrollController _scrollController;
@override
void initState() {
super.initState();
_scrollController = ScrollController();
_scrollController.addListener(_onScroll);
}
@override
void dispose() {
_scrollController.removeListener(_onScroll);
_scrollController.dispose();
super.dispose();
}
bool _isUserScrolling = false;
void _onScroll() {
if (_scrollController.position.isScrollingNotifier.value) {
_isUserScrolling = true;
} else {
_isUserScrolling = false;
}
}
void _scrollToIndex(int index) async {
if (_scrollController.hasClients && !_isUserScrolling) {
final double targetPosition = index * 100; item width + padding/margin
_scrollController.animateTo(
targetPosition,
duration: const Duration(seconds: 1),
curve: Curves.easeInOut,
);
} else {
Future.delayed(const Duration(milliseconds: 500), () {
_isUserScrolling = false;
_scrollToIndex(index);
});
}
}
在此我改变了要点,
ListView
进行交互。这
有助于避免通话时发生冲突 animateTo
。targetPosition
计算以匹配您的项目 dimensions
,
包括填充或边距,确保精确滚动。