119 lines
3.7 KiB
Dart
119 lines
3.7 KiB
Dart
// 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/animation/animated_value.dart';
|
|
import 'package:sky/animation/animation_performance.dart';
|
|
import 'package:sky/animation/curves.dart';
|
|
import 'package:sky/base/lerp.dart';
|
|
import 'package:sky/painting/box_painter.dart';
|
|
import 'package:sky/painting/text_style.dart';
|
|
import 'package:sky/rendering/box.dart';
|
|
import 'package:sky/theme/colors.dart';
|
|
import 'package:sky/widgets/basic.dart';
|
|
import 'package:sky/widgets/block_viewport.dart';
|
|
import 'package:sky/widgets/card.dart';
|
|
import 'package:sky/widgets/icon.dart';
|
|
import 'package:sky/widgets/scrollable.dart';
|
|
import 'package:sky/widgets/scaffold.dart';
|
|
import 'package:sky/widgets/theme.dart';
|
|
import 'package:sky/widgets/tool_bar.dart';
|
|
import 'package:sky/widgets/framework.dart';
|
|
import 'package:sky/widgets/task_description.dart';
|
|
|
|
class CardModel {
|
|
CardModel(this.value, this.height, this.color);
|
|
int value;
|
|
double height;
|
|
Color color;
|
|
String get label => "Card $value";
|
|
Key get key => new Key.fromObjectIdentity(this);
|
|
}
|
|
|
|
class EnsureVisibleApp extends App {
|
|
|
|
static const TextStyle cardLabelStyle =
|
|
const TextStyle(color: white, fontSize: 18.0, fontWeight: bold);
|
|
|
|
List<CardModel> cardModels;
|
|
BlockViewportLayoutState layoutState = new BlockViewportLayoutState();
|
|
ScrollListener scrollListener;
|
|
ValueAnimation<double> scrollAnimation;
|
|
|
|
void initState() {
|
|
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);
|
|
});
|
|
|
|
scrollAnimation = new ValueAnimation<double>()
|
|
..duration = const Duration(milliseconds: 200)
|
|
..variable = new AnimatedValue<double>(0.0, curve: ease);
|
|
|
|
super.initState();
|
|
}
|
|
|
|
EventDisposition handleTap(Widget target) {
|
|
ensureWidgetIsVisible(target, animation: scrollAnimation);
|
|
return EventDisposition.processed;
|
|
}
|
|
|
|
Widget builder(int index) {
|
|
if (index >= cardModels.length)
|
|
return null;
|
|
CardModel cardModel = cardModels[index];
|
|
Widget card = new Card(
|
|
color: cardModel.color,
|
|
child: new Container(
|
|
height: cardModel.height,
|
|
padding: const EdgeDims.all(8.0),
|
|
child: new Center(child: new Text(cardModel.label, style: cardLabelStyle))
|
|
)
|
|
);
|
|
return new Listener(
|
|
key: cardModel.key,
|
|
onGestureTap: (_) { return handleTap(card); },
|
|
child: card
|
|
);
|
|
}
|
|
|
|
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(
|
|
builder: builder,
|
|
token: cardModels.length,
|
|
layoutState: layoutState
|
|
)
|
|
);
|
|
|
|
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('Tap a Card')),
|
|
body: cardCollection
|
|
)
|
|
)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
runApp(new EnsureVisibleApp());
|
|
}
|