home.dart 7.18 KB
Newer Older
1 2 3 4 5 6 7 8
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

import 'drawer.dart';
9
import 'item.dart';
10

11 12
const double _kFlexibleSpaceMaxHeight = 256.0;

13 14 15 16 17 18 19 20
List<GalleryItem> _itemsWithCategory(String category) {
  return kAllGalleryItems.where((GalleryItem item) => item.category == category).toList();
}

final List<GalleryItem> _demoItems = _itemsWithCategory('Demos');
final List<GalleryItem> _componentItems = _itemsWithCategory('Components');
final List<GalleryItem> _styleItems = _itemsWithCategory('Style');

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
class _BackgroundLayer {
  _BackgroundLayer({ int level, double parallax })
    : assetName = 'packages/flutter_gallery_assets/appbar/appbar_background_layer$level.png',
      parallaxTween = new Tween<double>(begin: 0.0, end: parallax);
  final String assetName;
  final Tween<double> parallaxTween;
}

final List<_BackgroundLayer> _kBackgroundLayers = <_BackgroundLayer>[
  new _BackgroundLayer(level: 0, parallax: _kFlexibleSpaceMaxHeight),
  new _BackgroundLayer(level: 1, parallax: _kFlexibleSpaceMaxHeight),
  new _BackgroundLayer(level: 2, parallax: _kFlexibleSpaceMaxHeight / 2.0),
  new _BackgroundLayer(level: 3, parallax: _kFlexibleSpaceMaxHeight / 4.0),
  new _BackgroundLayer(level: 4, parallax: _kFlexibleSpaceMaxHeight / 2.0),
  new _BackgroundLayer(level: 5, parallax: _kFlexibleSpaceMaxHeight)
];

class _AppBarBackground extends StatelessWidget {
  _AppBarBackground({ Key key, this.animation }) : super(key: key);

  final Animation<double> animation;

  @override
  Widget build(BuildContext context) {
45 46 47
    // TODO(abarth): Wire up to the parallax of the FlexibleSpaceBar in a way
    // that doesn't pop during hero transition.
    Animation<double> effectiveAnimation = kAlwaysDismissedAnimation;
48
    return new AnimatedBuilder(
49
      animation: effectiveAnimation,
50 51 52 53
      builder: (BuildContext context, Widget child) {
        return new Stack(
          children: _kBackgroundLayers.map((_BackgroundLayer layer) {
            return new Positioned(
54
              top: -layer.parallaxTween.evaluate(effectiveAnimation),
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
              left: 0.0,
              right: 0.0,
              bottom: 0.0,
              child: new Image.asset(
                layer.assetName,
                fit: ImageFit.cover,
                height: _kFlexibleSpaceMaxHeight
              )
            );
          }).toList()
        );
      }
    );
  }
}

71
class GalleryHome extends StatefulWidget {
72 73
  GalleryHome({
    Key key,
Eric Seidel's avatar
Eric Seidel committed
74
    this.useLightTheme,
75 76
    this.onThemeChanged,
    this.timeDilation,
Eric Seidel's avatar
Eric Seidel committed
77 78
    this.onTimeDilationChanged,
    this.showPerformanceOverlay,
79
    this.onShowPerformanceOverlayChanged,
80 81
    this.checkerboardRasterCacheImages,
    this.onCheckerboardRasterCacheImagesChanged,
82
    this.onPlatformChanged,
83 84 85 86 87
  }) : super(key: key) {
    assert(onThemeChanged != null);
    assert(onTimeDilationChanged != null);
  }

Eric Seidel's avatar
Eric Seidel committed
88
  final bool useLightTheme;
89 90 91 92
  final ValueChanged<bool> onThemeChanged;

  final double timeDilation;
  final ValueChanged<double> onTimeDilationChanged;
93

Eric Seidel's avatar
Eric Seidel committed
94 95 96
  final bool showPerformanceOverlay;
  final ValueChanged<bool> onShowPerformanceOverlayChanged;

97 98 99
  final bool checkerboardRasterCacheImages;
  final ValueChanged<bool> onCheckerboardRasterCacheImagesChanged;

100 101
  final ValueChanged<TargetPlatform> onPlatformChanged;

102
  @override
103 104 105
  GalleryHomeState createState() => new GalleryHomeState();
}

106
class GalleryHomeState extends State<GalleryHome> with SingleTickerProviderStateMixin {
107
  static final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
108
  static final GlobalKey<ScrollableState> _scrollableKey = new GlobalKey<ScrollableState>();
109

110
  AnimationController _controller;
111 112 113 114

  @override
  void initState() {
    super.initState();
115 116 117 118 119
    _controller = new AnimationController(
      duration: const Duration(milliseconds: 600),
      debugLabel: 'preview banner',
      vsync: this,
    )..forward();
120 121 122 123 124 125 126 127
  }

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

128 129
  List<Widget> _galleryListItems() {
    final List<Widget> listItems = <Widget>[];
130
    final ThemeData themeData = Theme.of(context);
131
    final TextStyle headerStyle = themeData.textTheme.body2.copyWith(color: themeData.accentColor);
132 133 134 135
    String category;
    for (GalleryItem galleryItem in kAllGalleryItems) {
      if (category != galleryItem.category) {
        if (category != null)
136 137
          listItems.add(new Divider());
        listItems.add(
138 139 140
          new Container(
            height: 48.0,
            padding: const EdgeInsets.only(left: 16.0),
141
            alignment: FractionalOffset.centerLeft,
142
            child: new Text(galleryItem.category, style: headerStyle)
143 144 145 146
          )
        );
        category = galleryItem.category;
      }
147
      listItems.add(galleryItem);
148
    }
149
    return listItems;
150
  }
151

152 153
  @override
  Widget build(BuildContext context) {
154
    final double statusBarHeight = MediaQuery.of(context).padding.top;
155
    Widget home = new Scaffold(
156
      key: _scaffoldKey,
157
      scrollableKey: _scrollableKey,
158
      drawer: new GalleryDrawer(
Eric Seidel's avatar
Eric Seidel committed
159
        useLightTheme: config.useLightTheme,
160 161
        onThemeChanged: config.onThemeChanged,
        timeDilation: config.timeDilation,
Eric Seidel's avatar
Eric Seidel committed
162 163
        onTimeDilationChanged: config.onTimeDilationChanged,
        showPerformanceOverlay: config.showPerformanceOverlay,
164
        onShowPerformanceOverlayChanged: config.onShowPerformanceOverlayChanged,
165 166
        checkerboardRasterCacheImages: config.checkerboardRasterCacheImages,
        onCheckerboardRasterCacheImagesChanged: config.onCheckerboardRasterCacheImagesChanged,
167
        onPlatformChanged: config.onPlatformChanged,
168
      ),
169
      appBar: new AppBar(
170
        expandedHeight: _kFlexibleSpaceMaxHeight,
171
        flexibleSpace: new FlexibleSpaceBar(
172 173 174 175
          title: new Text('Flutter Gallery'),
          background: new Builder(
            builder: (BuildContext context) {
              return new _AppBarBackground(
176
                animation: _scaffoldKey.currentState.appBarAnimation
177 178 179
              );
            }
          )
180
        )
181
      ),
182
      appBarBehavior: AppBarBehavior.under,
183 184 185
      // The block's padding just exists to occupy the space behind the flexible app bar.
      // As the block's padded region is scrolled upwards, the app bar's height will
      // shrink keep it above the block content's and over the padded region.
186 187
      body: new Block(
       scrollableKey: _scrollableKey,
188
       padding: new EdgeInsets.only(top: _kFlexibleSpaceMaxHeight + statusBarHeight),
189
       children: _galleryListItems()
190
      )
191
    );
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216

    // In checked mode our MaterialApp will show the default "slow mode" banner.
    // Otherwise show the "preview" banner.
    bool showPreviewBanner = true;
    assert(() {
      showPreviewBanner = false;
      return true;
    });

    if (showPreviewBanner) {
      home = new Stack(
        children: <Widget>[
          home,
          new FadeTransition(
            opacity: new CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
            child: new Banner(
              message: 'PREVIEW',
              location: BannerLocation.topRight,
            )
          ),
        ]
      );
    }

    return home;
217 218
  }
}