• This packages is no longer maintenance,Use free_scroll_listview instead.
  • 因为ListView中存在不可调和的位置问题(比如从头部添加大高度数据时/手势滚动时无法精准定位位置而不导致闪烁,无法在---滚动的过程中/非滚动结束---流畅加载更多的头部数据),所以此库已经废弃,请使用free_scroll_listview替代。
  • free_scroll_listview 将提供更流畅的加载方式和滚动动画。

///animated addition test page
class AnimatedAdditionTest extends StatefulWidget {
  const AnimatedAdditionTest({super.key});

  @override
  State<StatefulWidget> createState() {
    return _AnimatedAdditionTestState();
  }
}

///animated addition test page state
class _AnimatedAdditionTestState extends State<AnimatedAdditionTest> {
  ///controller
  late AnimatedAdditionListViewController<String> _controller;

  @override
  void initState() {
    ///init controller
    _controller = AnimatedAdditionListViewController<String>(
      ///provide head data
      tailDataProvider: (String? current, int count) async {
        int number = (current != null ? int.parse(current) : 0) + 1;
        List<String> dataList = [];
        for (int s = number; s < number + count; s++) {
          dataList.add(s.toString());
        }
        return dataList;
      },

      ///provide current data
      headDataProvider: (String? current, int count) async {
        int number = (current != null ? int.parse(current) : 0);
        List<String> dataList = [];
        for (int s = number - count; s < number; s++) {
          dataList.add(s.toString());
        }
        dataList.removeWhere((e) => int.parse(e) <= 0);
        return dataList;
      },

      ///data list
      dataList: ["81", "82", "83", "84", "85", "86", "87", "88", "89", "90"],

      ///delta offset
      anchorOffset: 85 * 3,
    );

    ///load next items
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _controller.loadHeadItems();
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      color: Colors.red,
      child: SafeArea(
        top: true,
        bottom: true,
        child: Stack(
          children: [
            _buildTestPage(),
            _buildButton(),
          ],
        ),
      ),
    );
  }

  Widget _buildButton() {
    return Align(
      alignment: Alignment.bottomCenter,
      child: GestureDetector(
        behavior: HitTestBehavior.translucent,
        onTap: () {
          _controller.animateToItem("100");
        },
        child: Container(
          width: double.infinity,
          margin: const EdgeInsets.fromLTRB(30, 10, 30, 50),
          height: 30,
          decoration: BoxDecoration(
            color: Colors.blue,
            borderRadius: BorderRadius.circular(16),
          ),
        ),
      ),
    );
  }

  ///build test page
  Widget _buildTestPage() {
    return AnimatedAdditionListView(
      controller: _controller,
      padding: EdgeInsets.zero,
      reverse: true,
      physics: const BouncingScrollPhysics(),
      itemBuilder:
          (BuildContext context, int index, Animation<double> animation) {
        return SlideTransition(
          position: animation.drive(
            Tween<Offset>(
              begin: const Offset(-1, 0),
              end: const Offset(0, 0),
            ),
          ),
          child: Container(
            alignment: Alignment.center,
            width: double.infinity,
            decoration: const BoxDecoration(
              color: Colors.white,
              border: Border(
                bottom: BorderSide(color: Colors.black12, width: 0.3),
              ),
            ),
            height: 85,
            child: Text(
              _controller.dataList[index],
              style: const TextStyle(
                fontSize: 15,
                color: Colors.black,
                fontWeight: FontWeight.w500,
              ),
            ),
          ),
        );
      },
      onItemShow: (List<String> dataList) {
        print(dataList.join(","));
      },
    );
  }
}