如何在 Flutter 中自定义 SliverAppBar?

How to make custom SliverAppBar in Flutter?

Sliver App Bar

大家好,我正在开发 Sliver Appbar,但我想要这种类型的自定义 SliverAppbar,我该如何实现?

试试这个并根据您的要求进行自定义

class MyWidget extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return CustomScrollView(
      slivers: [
        SliverAppBar(
          expandedHeight: 300,
          pinned: true,
          flexibleSpace: FlexibleSpaceBar(
            title: const FittedBox(
              child: Text("loadedServices.title"),
            ),
            background: Image.network(
              "https://picsum.photos/250?image=9",
              fit: BoxFit.fill,
            ),
          ),
        ),
        SliverList(
          delegate: SliverChildListDelegate(
            [
              const SizedBox(height: 30.0),
              Padding(
                padding: const EdgeInsets.only(left: 8.0, right: 8.0),
                child: Column(
                  children: [
                    const Text(
                      "loadedServices.description",
                      textAlign: TextAlign.justify,
                      style: TextStyle(
                        fontFamily: 'OpenSans',
                        fontSize: 18,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    const SizedBox(height: 20),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                         Card(
                                elevation: 8,
                                shape: const RoundedRectangleBorder(
                                  borderRadius: BorderRadius.only(
                                    bottomLeft: Radius.circular(30),
                                    topRight: Radius.circular(30),
                                  ),
                                ),
                                child: Padding(
                                  padding: const EdgeInsets.symmetric(
                                    horizontal: 12.0,
                                    vertical: 8,
                                  ),
                                  child: Column(
                                    children: const [
                                       Text(
                                        "loadedServices.totalClass",
                                        style: TextStyle(fontSize: 14),
                                      ),
                                      Text(
                                        "Total Class",
                                        style: TextStyle(fontSize: 12),
                                      ),
                                    ],
                                  ),
                                ),
                              ),
                        Card(
                                elevation: 8,
                                shape: const RoundedRectangleBorder(
                                  borderRadius: BorderRadius.only(
                                    bottomLeft: Radius.circular(30),
                                    topRight: Radius.circular(30),
                                  ),
                                ),
                                child: Padding(
                                  padding: const EdgeInsets.symmetric(
                                    horizontal: 12.0,
                                    vertical: 8,
                                  ),
                                  child: Column(
                                    children: const [
                                      Text(
                                        "loadedServices.classDuration",
                                        style: TextStyle(fontSize: 14),
                                      ),
                                      Text(
                                        "Class Duration",
                                        style: TextStyle(fontSize: 12),
                                      ),
                                    ],
                                  ),
                                ),
                              ),
                        Card(
                                elevation: 8,
                                shape: const RoundedRectangleBorder(
                                  borderRadius: BorderRadius.only(
                                    bottomLeft: Radius.circular(30),
                                    topRight: Radius.circular(30),
                                  ),
                                ),
                                child: Padding(
                                  padding: const EdgeInsets.symmetric(
                                    horizontal: 12.0,
                                    vertical: 8,
                                  ),
                                  child: Column(
                                    children: const [
                                      Text(
                                        "loadedServices.courseDuration",
                                        style: TextStyle(fontSize: 14),
                                      ),
                                      Text(
                                        "Course Duration",
                                        style: TextStyle(fontSize: 12),
                                      ),
                                    ],
                                  ),
                                ),
                              ),
                      ],
                    ),
                    const SizedBox(height: 20),
                    const Text(
                      'For further Information make a phone call or contact our WhatsApp Number',
                      textAlign: TextAlign.justify,
                      style: TextStyle(
                        fontSize: 20.0,
                        color: Colors.green,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                    
                        const SizedBox(width: 10),
                        const Text(
                          'Or',
                          style: TextStyle(
                            fontSize: 20.0,
                            //color: Colors.green,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                        IconButton(
                          color: Colors.green,
                          icon: const Icon(
                            Icons.favorite,
                            size: 35,
                          ),
                          onPressed: (){
                          },
                        ),
                      ],
                    ),
                    const SizedBox(height: 20),
                    const Text(
                      'Visit Our WebSite',
                      textAlign: TextAlign.center,
                      style: TextStyle(
                        fontSize: 20.0,
                        color: Colors.green,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    const SizedBox(height: 10),
                    
                    const SizedBox(height: 20),
                    const Text(
                      'Visit Our Social Platform',
                      textAlign: TextAlign.center,
                      style: TextStyle(
                        fontSize: 20.0,
                        color: Colors.green,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        IconButton(
                          color: Colors.greenAccent,
                          icon: const Icon(
                            Icons.favorite,
                            size: 35,
                          ),
                          onPressed: (){},
                        ),
                        IconButton(
                          color: Colors.red,
                          icon: const Icon(
                            Icons.favorite,
                            size: 35,
                          ),
                          onPressed: (){},
                        ),
                      ],
                    ),
                  ],
                ),
              ),
              const SizedBox(height: 260),
            ],
          ),
        ),
      ],
    );
  }
}

您可以尝试使用 SliverPersistentHeader 小部件和 CustomScrollView 中包含的一堆条子来模拟相同的情况。您需要做的就是给 AppBarSliverPersistentHeader 和第一个 Sliver 相同的背景颜色。

看看下面的代码(抱歉格式不正确)。最后我还附上了一张 gif 动图(抱歉设计不佳)。

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

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: _title,
      home: MyStatefulWidget(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class MyStatefulWidget extends StatefulWidget {
  const MyStatefulWidget({Key? key}) : super(key: key);

  @override
  State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(backgroundColor:  const Color(0xff222222),
                     title: const Text("JazzCash"),
                     elevation: 0,
                    actions: const [Icon(Icons.info), Icon(Icons.notifications)]),
      body: CustomScrollView(
        slivers: <Widget>[
          
          // persistent header
          SliverPersistentHeader(
            pinned: true,
            delegate: SliverAppBarDelegate(
        minHeight: 60.0,
        maxHeight: 60.0,
        child: Container(
            color: const Color(0xff222222), child:Row(children:
                const [SizedBox(width: 10), CircleAvatar(), SizedBox(width: 10), Text("Muhammad", style: TextStyle(fontSize: 20, color: Colors.white)),
                ])),
      ),
         ),
          SliverList(
          delegate: SliverChildListDelegate(
            [
              
              // first sliver
              Container(color: const Color(0xff222222), 
                  padding: const EdgeInsets.all(10),
                  child: Column(crossAxisAlignment: CrossAxisAlignment.start,
                                                                children: [const Text("Login -->", style: TextStyle(color: Colors.amber, fontSize: 25, fontWeight: FontWeight.bold)),
                                                                           const Text("to Make Payments", style: TextStyle(color: Colors.white, fontSize: 25, fontWeight: FontWeight.bold)),
                                                                           const SizedBox(height: 10),
                                                                           Row(children: [ElevatedButton(onPressed: (){}, child: const Text("Add money")), const SizedBox(width: 20), ElevatedButton(onPressed: (){}, child: const Text("Add account"))])
                                                                          ])),
              Container(color: Colors.purple, height: 150.0),
              Container(color: Colors.green, height: 150.0),
        ],
        ),
        ),
        ],
      ),
    );
  }
}

// defining delegate for sliverpersistendheader
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 SizedBox.expand(child: child);
  }
  @override
  bool shouldRebuild(SliverAppBarDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxHeight ||
        minHeight != oldDelegate.minHeight ||
        child != oldDelegate.child;
  }
}