📜  sliver 持久标签栏 (1)

📅  最后修改于: 2023-12-03 15:05:13.666000             🧑  作者: Mango

Sliver 持久标签栏

Sliver 持久标签栏是 Flutter 中一个非常有用的控件,用于实现具有固定标签栏的滚动视图。它使得在页面上下滑动时标签栏总是保持在页面的顶部,同时也能够在不同的标签页之间进行切换。

核心特性
  1. 滑动时,标签栏持久不变,总是在屏幕上方呈现。
  2. 允许在标签栏中添加自定义小部件,如搜索框、通知提示等。
  3. 支持单个或多个标签页,用户可以自行添加或删除标签页。
  4. Sliver 持久标签栏是一个实时响应的控件,可以随着用户上下滑动而动态更新。
代码示例

以下是一个使用 Sliver 持久标签栏实现的简单的 Flutter 页面。该页面有两个标签页,其中第一个标签页包含一个文本框和一个按钮。

import 'package:flutter/material.dart';

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 {
  TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(vsync: this, length: 2, initialIndex: 0);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: NestedScrollView(
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
          return <Widget>[
            SliverPersistentHeader(
              delegate: _MySliverAppBar(
                expandedHeight: 200.0,
                title: Text(widget.title),
                tabBar: TabBar(
                  indicatorColor: Colors.white,
                  controller: _tabController,
                  tabs: [
                    Tab(text: 'Tab 1'),
                    Tab(text: 'Tab 2'),
                  ],
                ),
              ),
              pinned: true,
            ),
          ];
        },
        body: TabBarView(
          controller: _tabController,
          children: [
            Container(
              color: Colors.purple[100],
              child: Column(
                children: [
                  SizedBox(height: 20),
                  TextField(
                      decoration: InputDecoration(
                          hintText: 'Type Something Here'
                      ),
                  ),
                  SizedBox(height: 20),
                  ElevatedButton(
                    style: ElevatedButton.styleFrom(
                      primary: Colors.purple,
                      textStyle: TextStyle(
                        fontSize: 20,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    onPressed: () {},
                    child: Text('Submit'),
                  ),
                ],
              ),
            ),
            Container(
              color: Colors.blue[100],
              child: Center(
                child: Text(
                  'This is Tab 2',
                  style: TextStyle(
                    fontSize: 24,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class _MySliverAppBar extends SliverPersistentHeaderDelegate {
  _MySliverAppBar({
    @required this.expandedHeight,
    @required this.title,
    @required this.tabBar,
  });

  final double expandedHeight;
  final Widget title;
  final TabBar tabBar;

  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    final double minExtent = kToolbarHeight + this.tabBar.preferredSize.height;
    final double maxExtent = this.expandedHeight;
    final double currentExtent = minExtent + shrinkOffset;

    final double alpha = (1.0 - (currentExtent - minExtent) / (maxExtent - minExtent)).clamp(0.0, 1.0);

    return Stack(
      children: [
        Positioned.fill(
          child: Image.network(
            'https://picsum.photos/600/300',
            fit: BoxFit.cover,
          ),
        ),
        Positioned(
          top: 30,
          left: 10,
          right: 10,
          bottom: 10,
          child: Opacity(
            opacity: alpha,
            child: Card(
              color: Colors.white,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Padding(
                    padding: const EdgeInsets.all(4.0),
                    child: title,
                  ),
                  tabBar,
                ],
              ),
            ),
          ),
        ),
      ],
    );
  }

  @override
  double get maxExtent => this.expandedHeight + this.tabBar.preferredSize.height + kToolbarHeight;

  @override
  double get minExtent => kToolbarHeight + this.tabBar.preferredSize.height;

  @override
  bool shouldRebuild(_MySliverAppBar oldDelegate) {
    return expandedHeight != oldDelegate.expandedHeight || title != oldDelegate.title;
  }
}
总结

通过上面的代码示例,我们可以看到如何使用 Sliver 持久标签栏来实现一个带有固定标签栏的 Flutter 页面。这个页面不仅可以在多个标签页之间进行切换,还可以添加自定义的小部件,如搜索框和通知提示。此外,Sliver 持久标签栏是一个动态响应的控件,能够实时地随着用户的上下滑动而变化。使用 Sliver 持久标签栏能够使得我们的应用程序更加美观、易用和实用。