card_collection.dart 4.12 KB
Newer Older
1 2 3 4 5
// 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.

import 'package:sky/base/lerp.dart';
6
import 'package:sky/theme/colors.dart' as colors;
7
import 'package:sky/theme/typography.dart' as typography;
8
import 'package:sky/widgets.dart';
9

10 11 12 13 14 15
class CardModel {
  CardModel(this.value, this.height, this.color);
  int value;
  double height;
  Color color;
  String get label => "Item $value";
16
  Key get key => new Key.fromObjectIdentity(this);
17 18
}

19 20
class CardCollectionApp extends App {

21
  static const TextStyle cardLabelStyle =
22
    const TextStyle(color: colors.white, fontSize: 18.0, fontWeight: bold);
23 24 25

  final TextStyle backgroundTextStyle =
    typography.white.title.copyWith(textAlign: TextAlign.center);
26

27
  MixedViewportLayoutState layoutState = new MixedViewportLayoutState();
28
  List<CardModel> cardModels;
29 30

  void initState() {
31 32 33 34 35 36
    List<double> cardHeights = <double>[
      48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0,
      48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0,
      48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0
    ];
    cardModels = new List.generate(cardHeights.length, (i) {
37
      Color color = lerpColor(colors.Red[300], colors.Blue[900], i / cardHeights.length);
38 39
      return new CardModel(i, cardHeights[i], color);
    });
40 41 42
    super.initState();
  }

43 44 45 46 47 48 49 50 51 52
  void dismissCard(CardModel card) {
    if (cardModels.contains(card)) {
      setState(() {
        cardModels.remove(card);
      });
    }
  }

  Widget builder(int index) {
    if (index >= cardModels.length)
53
      return null;
54

55 56
    CardModel cardModel = cardModels[index];
    Widget card = new Dismissable(
57
      onResized: () { layoutState.invalidate([index]); },
58
      onDismissed: () { dismissCard(cardModel); },
59
      child: new Card(
60
        color: cardModel.color,
61
        child: new Container(
62
          height: cardModel.height,
63
          padding: const EdgeDims.all(8.0),
64 65 66 67 68
          child: new Center(child: new Text(cardModel.label, style: cardLabelStyle))
        )
      )
    );

69 70
    Widget backgroundText =
      new Text("Swipe in either direction", style: backgroundTextStyle);
71 72 73 74 75 76 77 78

    // The background Widget appears behind the Dismissable card when the card
    // moves to the left or right. The Positioned widget ensures that the
    // size of the background,card Stack will be based only on the card. The
    // Viewport ensures that when the card's resize animation occurs, the
    // background (text and icons) will just be clipped, not resized.
    Widget background = new Positioned(
      top: 0.0,
79 80
      right: 0.0,
      bottom: 0.0,
81 82 83 84 85 86 87 88 89 90 91 92 93
      left: 0.0,
      child: new Container(
        margin: const EdgeDims.all(4.0),
        child: new Viewport(
          child: new Container(
            height: cardModel.height,
            decoration: new BoxDecoration(backgroundColor: Theme.of(this).primaryColor),
            child: new Flex([
              new Icon(type: 'navigation/arrow_back', size: 36),
              new Flexible(child: backgroundText),
              new Icon(type: 'navigation/arrow_forward', size: 36)
            ])
          )
94 95 96
        )
      )
    );
97 98

    return new Stack([background, card], key: cardModel.key);
99 100 101 102 103 104
  }

  Widget build() {
    Widget cardCollection = new Container(
      padding: const EdgeDims.symmetric(vertical: 12.0, horizontal: 8.0),
      decoration: new BoxDecoration(backgroundColor: Theme.of(this).primarySwatch[50]),
105
      child: new ScrollableMixedWidgetList(
106 107 108
        builder: builder,
        token: cardModels.length,
        layoutState: layoutState
109 110 111
      )
    );

112 113 114 115 116
    return new IconTheme(
      data: const IconThemeData(color: IconThemeColor.white),
      child: new Theme(
        data: new ThemeData(
          brightness: ThemeBrightness.light,
117 118
          primarySwatch: colors.Blue,
          accentColor: colors.RedAccent[200]
119
        ),
120 121
        child: new Title(
          title: 'Cards',
122 123 124 125
          child: new Scaffold(
            toolbar: new ToolBar(center: new Text('Swipe Away')),
            body: cardCollection
          )
126 127 128 129 130 131 132 133 134
        )
      )
    );
  }
}

void main() {
  runApp(new CardCollectionApp());
}