如何在SliverAppBar内创建菜单?

时间:2020-08-14 10:21:37

标签: flutter dart flutter-layout

在滚动时,我想将SliverAppBar固定在TabBar上,但是在标签栏之前,我希望在它们之间有一个菜单。

    @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomPadding: false,
      body: NestedScrollView(
        controller: _scrollViewController,
        headerSliverBuilder: (BuildContext context, bool boxIsScrolled) {
          return <Widget>[
            SliverAppBar(
              backgroundColor: Colors.green,
              pinned: true,
              floating: true,
              expandedHeight: 60,
              forceElevated: boxIsScrolled,
              flexibleSpace: Conatainer(//All my buttons and stuff were supposed go in here);

                
  }
}

出于说明目的,当我滚动时,选项卡栏应该向上移动。 如您所见here,我认为flexibleSpace不适合用于承载大量上下文(两个图像和中间的文本)。当我尝试使用一些示例代码来填充flexibleSpace中的所有内容时,正如您看到的here

那样,我溢出了

1 个答案:

答案 0 :(得分:0)

为flexibleSpace创建自定义小部件,然后在其中添加tabview。 enter image description here

import 'dart:math' as math;

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  TabController controller;

  List<Tab> tabs = [
    Tab(
      icon: Icon(Icons.directions_car),
      iconMargin: EdgeInsets.only(
        bottom: 20,
      ),
    ),
    Tab(
      icon: Icon(Icons.directions_transit),
      iconMargin: EdgeInsets.only(
        bottom: 20,
      ),
    ),
    Tab(
      icon: Icon(Icons.directions_bike),
      iconMargin: EdgeInsets.only(
        bottom: 20,
      ),
    ),
    Tab(
      icon: Icon(Icons.directions_bike),
      iconMargin: EdgeInsets.only(
        bottom: 20,
      ),
    ),
  ];
  @override
  void initState() {
    controller = TabController(vsync: this, length: tabs.length);

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.yellow,
      resizeToAvoidBottomPadding: false,
      body: NestedScrollView(
        body: TabBarView(
          controller: controller,
          children: [
            ListView.builder(
              itemBuilder: (_, i) {
                return Card(
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Text('Text $i'),
                  ),
                );
              },
              itemCount: 200,
            ),
            Text('two'),
            Text('three'),
            Text('four'),
          ],
        ),
        headerSliverBuilder: (_, boxIsScrolled) {
          return ([
            SliverAppBar(
              collapsedHeight: 60,
              expandedHeight: 300,
              pinned: true,
              floating: true,
              flexibleSpace: _MyAppSpace(
                hasShadow: boxIsScrolled,
                controller: controller,
                tabs: tabs,
              ),
            ),
          ]);
        },
      ),
    );
  }
}

class _MyAppSpace extends StatelessWidget {
  const _MyAppSpace({Key key, this.controller, this.tabs, this.hasShadow})
      : super(key: key);

  final TabController controller;
  final List<Tab> tabs;
  final bool hasShadow;
  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, c) {
        final settings = context
            .dependOnInheritedWidgetOfExactType<FlexibleSpaceBarSettings>();
        final deltaExtent = settings.maxExtent - settings.minExtent;
        final t =
            (1.0 - (settings.currentExtent - settings.minExtent) / deltaExtent)
                .clamp(0.0, 1.0) as double;
        final fadeStart = math.max(0.0, 1.0 - kToolbarHeight / deltaExtent);
        const fadeEnd = 1.0;
        final opacity = 1.0 - Interval(fadeStart, fadeEnd).transform(t);

        return Material(
          elevation: hasShadow ? 2 : 0,
          color: Colors.amber,
          child: Stack(
            fit: StackFit.expand,
            overflow: Overflow.clip,
            children: [
              Positioned(
                top: 0,
                child: Opacity(
                  opacity: opacity,
                  child: Column(
                    children: [
                      Placeholder(
                        fallbackHeight: 100,
                      ),
                      Text('hi'),
                      Placeholder(
                        fallbackHeight: 100,
                      ),
                    ],
                  ),
                ),
              ),
              Positioned(
                bottom: 0,
                left: 0,
                right: 0,
                child: Container(
                  height: settings.minExtent,
                  color: Colors.deepOrangeAccent,
                  alignment: Alignment.bottomCenter,
                  child: TabBar(
                    controller: controller,
                    tabs: tabs,
                  ),
                ),
              ),
            ],
          ),
        );
      },
    );
  }
}