floating_action_button.dart 3.15 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
import 'package:flutter/widgets.dart';
6

Adam Barth's avatar
Adam Barth committed
7 8
import 'icon_theme.dart';
import 'icon_theme_data.dart';
9 10 11
import 'ink_well.dart';
import 'material.dart';
import 'theme.dart';
12 13 14 15

// TODO(eseidel): This needs to change based on device size?
// http://www.google.com/design/spec/layout/metrics-keylines.html#metrics-keylines-keylines-spacing
const double _kSize = 56.0;
Devon Carew's avatar
Devon Carew committed
16
const double _kSizeMini = 40.0;
17 18
const Duration _kChildSegue = const Duration(milliseconds: 400);
const Interval _kChildSegueInterval = const Interval(0.65, 1.0);
19

20 21
class FloatingActionButton extends StatefulComponent {
  const FloatingActionButton({
22
    Key key,
23 24
    this.child,
    this.backgroundColor,
25 26
    this.elevation: 6,
    this.highlightElevation: 12,
Devon Carew's avatar
Devon Carew committed
27 28
    this.onPressed,
    this.mini: false
29 30
  }) : super(key: key);

31 32
  final Widget child;
  final Color backgroundColor;
33
  final VoidCallback onPressed;
34 35
  final int elevation;
  final int highlightElevation;
Devon Carew's avatar
Devon Carew committed
36
  final bool mini;
37

38
  _FloatingActionButtonState createState() => new _FloatingActionButtonState();
39
}
40

41
class _FloatingActionButtonState extends State<FloatingActionButton> {
42
  Animation<double> _childSegue;
43
  AnimationController _childSegueController;
44 45 46

  void initState() {
    super.initState();
47 48 49 50 51 52 53 54 55
    _childSegueController = new AnimationController(duration: _kChildSegue)
      ..forward();
    _childSegue = new Tween<double>(
      begin: -0.125,
      end: 0.0
    ).animate(new CurvedAnimation(
      parent: _childSegueController,
      curve: _kChildSegueInterval
    ));
56 57 58 59 60 61
  }

  void didUpdateConfig(FloatingActionButton oldConfig) {
    super.didUpdateConfig(oldConfig);
    if (Widget.canUpdate(oldConfig.child, config.child) && config.backgroundColor == oldConfig.backgroundColor)
      return;
62 63 64
    _childSegueController
      ..value = 0.0
      ..forward();
65 66
  }

67 68 69 70 71 72 73 74 75
  bool _highlight = false;

  void _handleHighlightChanged(bool value) {
    setState(() {
      _highlight = value;
    });
  }

  Widget build(BuildContext context) {
76
    IconThemeColor iconThemeColor = IconThemeColor.white;
77
    Color materialColor = config.backgroundColor;
78
    if (materialColor == null) {
79
      ThemeData themeData = Theme.of(context);
80 81 82 83 84 85 86
      materialColor = themeData.accentColor;
      iconThemeColor = themeData.accentColorBrightness == ThemeBrightness.dark ? IconThemeColor.white : IconThemeColor.black;
    }

    return new Material(
      color: materialColor,
      type: MaterialType.circle,
87 88
      elevation: _highlight ? config.highlightElevation : config.elevation,
      child: new Container(
Devon Carew's avatar
Devon Carew committed
89 90
        width: config.mini ? _kSizeMini : _kSize,
        height: config.mini ? _kSizeMini : _kSize,
91 92 93 94 95 96
        child: new InkWell(
          onTap: config.onPressed,
          onHighlightChanged: _handleHighlightChanged,
          child: new Center(
            child: new IconTheme(
              data: new IconThemeData(color: iconThemeColor),
97
              child: new RotationTransition(
98
                turns: _childSegue,
99 100
                child: config.child
              )
101 102 103 104 105 106 107
            )
          )
        )
      )
    );
  }
}