snack_bar.dart 4.21 KB
Newer Older
1 2 3 4
// Copyright 2015 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.

5 6
import 'package:flutter/animation.dart';
import 'package:flutter/widgets.dart';
7

8
import 'flat_button.dart';
9
import 'material.dart';
10
import 'material_button.dart';
11
import 'theme.dart';
12
import 'theme_data.dart';
13
import 'typography.dart';
Matt Perry's avatar
Matt Perry committed
14

Hixie's avatar
Hixie committed
15
// https://www.google.com/design/spec/components/snackbars-toasts.html#snackbars-toasts-specs
16
const double _kSideMargins = 24.0;
Hixie's avatar
Hixie committed
17
const double _kSingleLineVerticalPadding = 14.0;
18 19
const double _kMultiLineVerticalTopPadding = 24.0;
const double _kMultiLineVerticalSpaceBetweenTextAndButtons = 10.0;
20
const Color _kSnackBackground = const Color(0xFF323232);
Matt Perry's avatar
Matt Perry committed
21

Hixie's avatar
Hixie committed
22 23 24 25 26 27
// TODO(ianh): We should check if the given text and actions are going to fit on
// one line or not, and if they are, use the single-line layout, and if not, use
// the multiline layout. See link above.

// TODO(ianh): Implement the Tablet version of snackbar if we're "on a tablet".

28
const Duration _kSnackBarTransitionDuration = const Duration(milliseconds: 250);
Hixie's avatar
Hixie committed
29 30
const Duration kSnackBarShortDisplayDuration = const Duration(milliseconds: 1500);
const Duration kSnackBarMediumDisplayDuration = const Duration(milliseconds: 2750);
31
const Curve _snackBarFadeCurve = const Interval(0.72, 1.0, curve: Curves.fastOutSlowIn);
Hixie's avatar
Hixie committed
32

33
class SnackBarAction extends StatelessComponent {
34
  SnackBarAction({Key key, this.label, this.onPressed }) : super(key: key) {
35 36 37 38
    assert(label != null);
  }

  final String label;
39
  final VoidCallback onPressed;
40

Hixie's avatar
Hixie committed
41
  Widget build(BuildContext context) {
42 43 44 45 46
    return new Container(
      margin: const EdgeDims.only(left: _kSideMargins),
      child: new FlatButton(
        onPressed: onPressed,
        textTheme: ButtonColor.accent,
47 48 49 50 51
        child: new Text(label)
      )
    );
  }
}
52

Hixie's avatar
Hixie committed
53 54
class SnackBar extends StatelessComponent {
  SnackBar({
55 56 57
    Key key,
    this.content,
    this.actions,
Hixie's avatar
Hixie committed
58 59
    this.duration: kSnackBarShortDisplayDuration,
    this.performance
60
  }) : super(key: key) {
61 62 63
    assert(content != null);
  }

64 65
  final Widget content;
  final List<SnackBarAction> actions;
Hixie's avatar
Hixie committed
66 67
  final Duration duration;
  final PerformanceView performance;
68

69
  Widget build(BuildContext context) {
Hixie's avatar
Hixie committed
70
    assert(performance != null);
Hixie's avatar
Hixie committed
71
    List<Widget> children = <Widget>[
72 73
      new Flexible(
        child: new Container(
Hixie's avatar
Hixie committed
74
          margin: const EdgeDims.symmetric(vertical: _kSingleLineVerticalPadding),
75
          child: new DefaultTextStyle(
76
            style: Typography.white.subhead,
77
            child: content
78 79 80
          )
        )
      )
81
    ];
82 83
    if (actions != null)
      children.addAll(actions);
84
    ThemeData theme = Theme.of(context);
Hixie's avatar
Hixie committed
85 86 87 88 89 90 91 92 93 94
    return new ClipRect(
      child: new AlignTransition(
        performance: performance,
        alignment: new AnimatedValue<FractionalOffset>(const FractionalOffset(0.0, 0.0)),
        heightFactor: new AnimatedValue<double>(0.0, end: 1.0, curve: Curves.fastOutSlowIn),
        child: new Material(
          elevation: 6,
          color: _kSnackBackground,
          child: new Container(
            margin: const EdgeDims.symmetric(horizontal: _kSideMargins),
95 96 97 98 99 100 101
            child: new Theme(
              data: new ThemeData(
                brightness: ThemeBrightness.dark,
                accentColor: theme.accentColor,
                accentColorBrightness: theme.accentColorBrightness,
                text: Typography.white
              ),
Hixie's avatar
Hixie committed
102 103
              child: new FadeTransition(
                performance: performance,
104
                opacity: new AnimatedValue<double>(0.0, end: 1.0, curve: _snackBarFadeCurve),
105 106 107 108
                child: new Row(
                  children,
                  alignItems: FlexAlignItems.center
                )
109 110
              )
            )
Matt Perry's avatar
Matt Perry committed
111
          )
112 113 114 115
        )
      )
    );
  }
116

Hixie's avatar
Hixie committed
117
  // API for Scaffold.addSnackBar():
118

119
  static Performance createPerformanceController() {
Hixie's avatar
Hixie committed
120
    return new Performance(
121
      duration: _kSnackBarTransitionDuration,
Hixie's avatar
Hixie committed
122 123 124
      debugLabel: 'SnackBar'
    );
  }
125

126
  SnackBar withPerformance(Performance newPerformance, { Key fallbackKey }) {
Hixie's avatar
Hixie committed
127
    return new SnackBar(
128
      key: key ?? fallbackKey,
Hixie's avatar
Hixie committed
129 130 131 132 133 134
      content: content,
      actions: actions,
      duration: duration,
      performance: newPerformance
    );
  }
135
}