具有水平滚动和粘性的 Flutter SliverList header

Flutter SliverList with horizontal scrolling and sticky header

我已经尝试了一段时间,但我无法让它工作。

我想在 CustomScrollViewCupertinoSliverNavigationBar 中创建列表视图。 SliverList 必须可以水平滚动。此外,它应该有一个 header 行粘在视图的顶部。

请在此处查看示例:https://dartpad.dev/?id=38c0825f27c1b3395dd22794a2567e64。请注意 body 可以水平滚动。

我想将红色 header 行设置为粘性,以便在滚动蓝色内容时始终保持可见。

问题是 header 行必须在 SingleChildScrollViewSizedBox 内,否则它不会有所需的宽度。但是一旦它在里面,我就不能再让它变粘了。

非常感谢任何指点。

解决方法^^ 使用 SliverPersistentHeader 使红色 header 行变粘,并使用 SliverList 而不是 ListView。

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'dart:math' as math;

class HomePage extends StatelessWidget {
   const HomePage({Key? key}) : super(key: key);


 @override
   Widget build(BuildContext context) {
final scrollController = ScrollController();
return MaterialApp(
  home: Scaffold(
    body: CustomScrollView(
      slivers: [
        const CupertinoSliverNavigationBar(
          largeTitle: Text('Search'),
        ),
        //CupertinoSliverRefreshControl(),
        SliverPersistentHeader(
          pinned: true,
          delegate: _SliverAppBarDelegate(
            minHeight: 20.0,
            maxHeight: 30.0,
            child: Container(
                color: Colors.red, child: Center(child:
            Text("red header "))),
          ),
        ),

        SliverList(
          delegate: SliverChildListDelegate(
            List.generate(80, (index) => Container(
              padding: const EdgeInsets.all(5),
              color: Colors.blueAccent.shade100,
              child: const Text('bar'),
            )),
          ),
        ),

       ],
    ),
  ),
);
   }
}

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
   _SliverAppBarDelegate({
       required this.minHeight,
      required this.maxHeight,
      required this.child,
    });

    final double minHeight;
    final double maxHeight;
    final Widget child;

    @override
     double get minExtent => minHeight;

    @override
     double get maxExtent => math.max(maxHeight, minHeight);

    @override
     Widget build(BuildContext context,
      double shrinkOffset,
      bool overlapsContent) {
     return new SizedBox.expand(child: child);
      }

    @override
    bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
      return maxHeight != oldDelegate.maxHeight ||
      minHeight != oldDelegate.minHeight ||
       child != oldDelegate.child;
    }
   }