Flutter 是否有相当于 Bootstrap Scrollspy 的工具?

Kar*_*eem 2 listview widget flutter flutter-web singlechildscrollview

我正在寻找一个与 Bootstrap\xe2\x80\x99s Scrollspy 等效的 flutter 包:

\n

https://getbootstrap.com/docs/4.0/components/scrollspy/

\n

预期的功能是有一个垂直可滚动的项目列表,其顶部有一个粘性水平可滚动 \xe2\x80\x9cheader/navbar 菜单\xe2\x80\x9d。当用户滚动垂直列表并到达新的 \xe2\x80\x9csection\xe2\x80\x9d 时,这会通过在导航栏中突出显示 \xe2\x80\x9csection name\xe2\x80\x9d 来反映在水平导航栏中并在必要时滚动到它。当用户按下水平导航栏中的部分名称时,它应该滚动到垂直列表中该部分的开头。

\n

前任:

\n

第 1 节!!!第 2 节!!!第 3 节 第 4 节\n\xe2\x80\x94\xe2\x80\x94\xe2\x80\x94\xe2\x80\x94\xe2\x80\x94\xe2\x80\x94\xe2\x80\x94\xe2\x80 \x94\xe2\x80\x94\xe2\x80\x94\xe2\x80\x94\xe2\x80\x94\xe2\x80\x94\xe2\x80\x94\xe2\x80\x94\xe2\x80\x94 \xe2\x80\x94\xe2\x80\x94\xe2\x80\x94\xe2\x80\x94\xe2\x80\x94\xe2\x80\x94\n(Section1 不可见)

\n

!!!第2节!!!

\n
Item3\n\nItem4\n
Run Code Online (Sandbox Code Playgroud)\n

第三节

\n
Item1\n\nItem2\n
Run Code Online (Sandbox Code Playgroud)\n

第四节

\n
Item5\n\nItem6\n
Run Code Online (Sandbox Code Playgroud)\n

Thi*_*rry 5

我认为你可以使用Google Fuchsia Authors 制作的rollable_positioned_list 包来实现这一点。

在此输入图像描述

提供ScrollablePositionedListItemPositionsListener

_itemPositionsListener.itemPositions.addListener(() {
  final positions = _itemPositionsListener.itemPositions.value;
  setState(() {
    _topItem = positions.isNotEmpty ? positions.first.index : null;
  });
});
Run Code Online (Sandbox Code Playgroud)

完整源代码

import 'package:flutter/material.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';

void main() {
  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      home: HomePage(),
    ),
  );
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final _nbItems = 6;
  final _itemHeight = 200.0;
  final _itemPositionsListener = ItemPositionsListener.create();

  int _topItem = 0;

  @override
  void initState() {
    super.initState();
    _itemPositionsListener.itemPositions.addListener(() {
      final positions = _itemPositionsListener.itemPositions.value;
      setState(() {
        _topItem = positions.isNotEmpty ? positions.first.index : null;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: List.generate(
              _nbItems,
              (index) => Padding(
                padding: const EdgeInsets.all(8.0),
                child: Container(
                  padding: EdgeInsets.all(4.0),
                  decoration: _topItem == index
                      ? BoxDecoration(
                          color: Colors.black26,
                          border: Border.all(color: Colors.black54),
                        )
                      : BoxDecoration(),
                  child: Text(
                    'S$index',
                    style: TextStyle(
                      fontWeight: _topItem == index
                          ? FontWeight.bold
                          : FontWeight.normal,
                    ),
                  ),
                ),
              ),
            ),
          ),
          Expanded(
            child: ScrollablePositionedList.builder(
              itemCount: _nbItems,
              itemBuilder: (context, index) => SizedBox(
                height: _itemHeight,
                child: Card(
                  child: Text('Item $index'),
                ),
              ),
              itemPositionsListener: _itemPositionsListener,
            ),
          ),
        ],
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)