flexible_space_bar.dart 3.51 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
// 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 'dart:math' as math;

import 'package:flutter/widgets.dart';

import 'debug.dart';
import 'constants.dart';
import 'scaffold.dart';
import 'theme.dart';

class FlexibleSpaceBar extends StatefulComponent {
  FlexibleSpaceBar({ Key key, this.title, this.image }) : super(key: key);

  final Widget title;
  final Widget image;

  _FlexibleSpaceBarState createState() => new _FlexibleSpaceBarState();
}

class _FlexibleSpaceBarState extends State<FlexibleSpaceBar> {

  Widget build(BuildContext context) {
    assert(debugCheckHasScaffold(context));
    final double appBarHeight = Scaffold.of(context).appBarHeight;
    final Animation<double> animation = Scaffold.of(context).appBarAnimation;
    final EdgeDims toolBarPadding = MediaQuery.of(context)?.padding ?? EdgeDims.zero;
    final double toolBarHeight = kToolBarHeight + toolBarPadding.top;
    final List<Widget> children = <Widget>[];

    // background image
    if (config.image != null) {
      final double fadeStart = (appBarHeight - toolBarHeight * 2.0) / appBarHeight;
      final double fadeEnd = (appBarHeight - toolBarHeight) / appBarHeight;
      final CurvedAnimation opacityCurve = new CurvedAnimation(
        parent: animation,
        curve: new Interval(math.max(0.0, fadeStart), math.min(fadeEnd, 1.0))
      );
      final double parallax = new Tween<double>(begin: 0.0, end: appBarHeight / 4.0).evaluate(animation);
      children.add(new Positioned(
        top: -parallax,
        left: 0.0,
        right: 0.0,
        child: new Opacity(
          opacity: new Tween<double>(begin: 1.0, end: 0.0).evaluate(opacityCurve),
          child: config.image
        )
       ));
    }

    // title
    if (config.title != null) {
      final double fadeStart = (appBarHeight - toolBarHeight) / appBarHeight;
      final double fadeEnd = (appBarHeight - toolBarHeight / 2.0) / appBarHeight;
      final CurvedAnimation opacityCurve = new CurvedAnimation(
        parent: animation,
        curve: new Interval(fadeStart, fadeEnd)
      );
      TextStyle titleStyle = Theme.of(context).primaryTextTheme.title;
      titleStyle = titleStyle.copyWith(
        color: titleStyle.color.withAlpha(new Tween<double>(begin: 255.0, end: 0.0).evaluate(opacityCurve).toInt())
      );
      final double yAlignStart = 1.0;
      final double yAlignEnd = (toolBarPadding.top + kToolBarHeight / 2.0) / toolBarHeight;
      final double scaleAndAlignEnd = (appBarHeight - toolBarHeight) / appBarHeight;
      final CurvedAnimation scaleAndAlignCurve = new CurvedAnimation(
        parent: animation,
        curve: new Interval(0.0, scaleAndAlignEnd)
      );
      children.add(new Padding(
        padding: const EdgeDims.only(left: 72.0, bottom: 14.0),
        child: new Align(
          alignment: new Tween<FractionalOffset>(
            begin: new FractionalOffset(0.0, yAlignStart),
            end: new FractionalOffset(0.0, yAlignEnd)
          ).evaluate(scaleAndAlignCurve),
          child: new ScaleTransition(
            alignment: const FractionalOffset(0.0, 1.0),
            scale: new Tween<double>(begin: 1.5, end: 1.0).animate(scaleAndAlignCurve),
            child: new Align(
              alignment: new FractionalOffset(0.0, 1.0),
              child: new DefaultTextStyle(style: titleStyle, child: config.title)
            )
          )
        )
      ));
    }

    return new ClipRect(child: new Stack(children: children));
  }
}