fluttercandies / extended_nested_scroll_view

extended nested scroll view to fix following issues. 1.pinned sliver header issue 2.inner scrollables in tabview sync issue 3.pull to refresh is not work. 4.do without ScrollController in NestedScrollView's body
MIT License
592 stars 119 forks source link

似乎并没有解决 issue 2 滚动问题 #43

Closed janjandev closed 4 years ago

janjandev commented 4 years ago

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  final List<String> _tabs = [
    "AAA",
    "BBB",
    "CCC",
    "DDD",
    "EEE",
    "FFF",
  ];

  TabController tcl;

  @override
  void initState() {
    super.initState();
    tcl = TabController(length: _tabs.length, vsync: this);
  }

  @override
  void dispose() {
    tcl.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final double statusBarHeight = MediaQuery.of(context).padding.top;
    final double pinnedHeaderHeight = statusBarHeight + kToolbarHeight;

    return extended.NestedScrollView(
      pinnedHeaderSliverHeightBuilder: () {
        return pinnedHeaderHeight;
      },
      innerScrollPositionKeyBuilder: () => Key('${_tabs[tcl.index]}'),
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
          // These are the slivers that show up in the "outer" scroll view.
          return <Widget>[
//            SliverOverlapAbsorber(
              // This widget takes the overlapping behavior of the SliverAppBar,
              // and redirects it to the SliverOverlapInjector below. If it is
              // missing, then it is possible for the nested "inner" scroll view
              // below to end up under the SliverAppBar even when the inner
              // scroll view thinks it has not been scrolled.
              // This is not necessary if the "headerSliverBuilder" only builds
              // widgets that do not overlap the next sliver.
//              handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
//              sliver:
          SliverAppBar(
                title: const Text('Books'), // This is the title in the app bar.
                pinned: true,
                floating: true,
                snap: true,
                // The "forceElevated" property causes the SliverAppBar to show
                // a shadow. The "innerBoxIsScrolled" parameter is true when the
                // inner scroll view is scrolled beyond its "zero" point, i.e.
                // when it appears to be scrolled below the SliverAppBar.
                // Without this, there are cases where the shadow would appear
                // or not appear inappropriately, because the SliverAppBar is
                // not actually aware of the precise position of the inner
                // scroll views.
                forceElevated: innerBoxIsScrolled,
                bottom: TabBar(
                  controller: tcl,
                  isScrollable: true,
                  // These are the widgets to put in each tab in the tab bar.
                  tabs: _tabs.map((String name) => Tab(text: name)).toList(),
                ),
              ),
//            ),
          ];
        },
        body: TabBarView(
          controller: tcl,
          // These are the contents of the tab views, below the tabs.
          children: _tabs.map((String name) {
            return SafeArea(
              top: false,
              bottom: false,
              child: Builder(
                // This Builder is needed to provide a BuildContext that is
                // "inside" the NestedScrollView, so that
                // sliverOverlapAbsorberHandleFor() can find the
                // NestedScrollView.
                builder: (BuildContext context) {
                  return RefreshIndicator(child: CustomScrollView(
                    // The "controller" and "primary" members should be left
                    // unset, so that the NestedScrollView can control this
                    // inner scroll view.
                    // If the "controller" property is set, then this scroll
                    // view will not be associated with the NestedScrollView.
                    // The PageStorageKey should be unique to this ScrollView;
                    // it allows the list to remember its scroll position when
                    // the tab view is not on the screen.
                    key: PageStorageKey<String>(name),
                    slivers: <Widget>[
//                      SliverOverlapInjector(
//                        // This is the flip side of the SliverOverlapAbsorber
//                        // above.
//                        handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
//                      ),
                      SliverPadding(
                        padding: const EdgeInsets.all(0),
                        // In this example, the inner scroll view has
                        // fixed-height list items, hence the use of
                        // SliverFixedExtentList. However, one could use any
                        // sliver widget here, e.g. SliverList or SliverGrid.
                        sliver: TabPage(key: Key(name)),
                      ),
                    ],
                  ), onRefresh: () => Future.delayed(Duration(seconds: 5)));
                },
              ),
            );
          }).toList(),
        ),
      );
  }
}

class TabPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _TabPageState();
  }

  TabPage({Key key}) : super(key: key);
}

class _TabPageState extends State<TabPage> with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return extended.NestedScrollViewInnerScrollPositionKeyWidget(
        widget.key,
        SliverFixedExtentList(
          // The items in this example are fixed to 48 pixels
          // high. This matches the Material Design spec for
          // ListTile widgets.
          itemExtent: 48.0,
          delegate: SliverChildBuilderDelegate(
            (BuildContext context, int index) {
              // This builder is called for each child.
              // In this example, we just number each list item.
              return Material(
                  child: ListTile(
                title: Text('Item $index'),
              ));
            },
            // The childCount of the SliverChildBuilderDelegate
            // specifies how many children this inner list
            // has. In this example, each tab has a list of
            // exactly 30 items, but this is arbitrary.
            childCount: 30,
          ),
        ));
  }
}
zmtzawqlp commented 4 years ago

https://github.com/fluttercandies/extended_nested_scroll_view/issues/40 1.17 情况有变化,还在研究

janjandev commented 4 years ago

并且网格列表数据多了滑动很卡顿,代码太侵入官方了。

zmtzawqlp commented 4 years ago

??对于官方的代码没有太多处理。大部分代码还是跟官方一样的。。你觉得卡顿,需要自己找下原因。我实际项目2层tab,8个列表。没压力

janjandev commented 4 years ago

网格 3 列形式 ,每个列表项是一个卡片里面是图文,加载更多越滑越卡顿

janjandev commented 4 years ago

和列表里面的东西没关系,就是列表数据量大了本身卡顿。

zmtzawqlp commented 4 years ago

图片自己优化下吧,别列表搞一些高清图片