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

所以当我滚动列表并停止时,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),
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}

参考文献:

  1. https://github.com/flutter/flutter/issues/19941#issuecomment-522587489

2。使用 Area

包:https://pub.dev/packages/inview_notifier_list