card_collection.dart 4.54 KB
Newer Older
1 2 3 4 5 6 7 8
// 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';
import 'package:sky/painting/text_style.dart';
import 'package:sky/theme/colors.dart';
import 'package:sky/widgets/basic.dart';
9
import 'package:sky/widgets/block_viewport.dart';
10 11
import 'package:sky/widgets/card.dart';
import 'package:sky/widgets/dismissable.dart';
12
import 'package:sky/widgets/icon.dart';
13
import 'package:sky/widgets/scrollable.dart';
14
import 'package:sky/widgets/scaffold.dart';
15 16
import 'package:sky/widgets/theme.dart';
import 'package:sky/widgets/tool_bar.dart';
17
import 'package:sky/theme/typography.dart' as typography;
18
import 'package:sky/widgets/framework.dart';
19 20
import 'package:sky/widgets/task_description.dart';

21 22 23 24 25 26
class CardModel {
  CardModel(this.value, this.height, this.color);
  int value;
  double height;
  Color color;
  String get label => "Item $value";
27
  Key get key => new Key.fromObjectIdentity(this);
28 29
}

30 31
class CardCollectionApp extends App {

32 33 34 35 36
  static const TextStyle cardLabelStyle =
    const TextStyle(color: white, fontSize: 18.0, fontWeight: bold);

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

38 39
  BlockViewportLayoutState layoutState = new BlockViewportLayoutState();
  List<CardModel> cardModels;
40 41

  void initState() {
42 43 44 45 46 47 48 49 50
    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) {
      Color color = lerpColor(Red[300], Blue[900], i / cardHeights.length);
      return new CardModel(i, cardHeights[i], color);
    });
51 52 53
    super.initState();
  }

54 55 56 57 58 59 60 61 62 63
  void dismissCard(CardModel card) {
    if (cardModels.contains(card)) {
      setState(() {
        cardModels.remove(card);
      });
    }
  }

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

66 67
    CardModel cardModel = cardModels[index];
    Widget card = new Dismissable(
68
      onResized: () { layoutState.invalidate([index]); },
69
      onDismissed: () { dismissCard(cardModel); },
70
      child: new Card(
71
        color: cardModel.color,
72
        child: new Container(
73
          height: cardModel.height,
74
          padding: const EdgeDims.all(8.0),
75 76 77 78 79
          child: new Center(child: new Text(cardModel.label, style: cardLabelStyle))
        )
      )
    );

80 81
    Widget backgroundText =
      new Text("Swipe in either direction", style: backgroundTextStyle);
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

    // 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,
      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)
            ])
          )
103 104 105
        )
      )
    );
106 107

    return new Stack([background, card], key: cardModel.key);
108 109 110 111 112 113 114
  }

  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]),
      child: new VariableHeightScrollable(
115 116 117
        builder: builder,
        token: cardModels.length,
        layoutState: layoutState
118 119 120
      )
    );

121 122 123 124 125 126 127 128 129 130 131 132 133 134
    return new IconTheme(
      data: const IconThemeData(color: IconThemeColor.white),
      child: new Theme(
        data: new ThemeData(
          brightness: ThemeBrightness.light,
          primarySwatch: Blue,
          accentColor: RedAccent[200]
        ),
        child: new TaskDescription(
          label: 'Cards',
          child: new Scaffold(
            toolbar: new ToolBar(center: new Text('Swipe Away')),
            body: cardCollection
          )
135 136 137 138 139 140 141 142 143
        )
      )
    );
  }
}

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