尝试将 listview.builder 移动到 flutter 中的特定索引时遇到问题

问题描述 投票:0回答:1

这是 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);
    }
  }
flutter dart scroll controller flutter-listview
1个回答
0
投票

出现此问题的原因是,当您滚动

ListView
用手指滑动时,它会停止或取消
animateTo
功能。

这是因为控制滚动的

ScrollController
被您的手动滚动打断了。

我们可以做一些改变来解决这个问题,

  1. addListener

    上使用
    ScrollController
    添加监听器来检测 当用户手动与
    ListView
    交互时。一旦 交互结束,允许 animateTo 恢复工作。

  2. 确保正确的索引定位验证您所在的索引 根据项目的大小正确计算滚动到 在你的

    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
    , 包括填充或边距,确保精确滚动。
© www.soinside.com 2019 - 2024. All rights reserved.