Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: sky/sdk/lib/widgets/tabs.dart

Issue 1215713009: Scrollable TabBar Version 1 - support for flinging (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 import 'dart:math' as math; 5 import 'dart:math' as math;
6 6
7 import 'package:sky/animation/generators.dart';
8 import 'package:sky/animation/mechanics.dart';
7 import 'package:sky/animation/scroll_behavior.dart'; 9 import 'package:sky/animation/scroll_behavior.dart';
8 import 'package:sky/painting/text_style.dart'; 10 import 'package:sky/painting/text_style.dart';
9 import 'package:sky/rendering/box.dart'; 11 import 'package:sky/rendering/box.dart';
10 import 'package:sky/rendering/object.dart'; 12 import 'package:sky/rendering/object.dart';
11 import 'package:vector_math/vector_math.dart'; 13 import 'package:vector_math/vector_math.dart';
12 import 'package:sky/widgets/basic.dart'; 14 import 'package:sky/widgets/basic.dart';
13 import 'package:sky/widgets/icon.dart'; 15 import 'package:sky/widgets/icon.dart';
14 import 'package:sky/widgets/ink_well.dart'; 16 import 'package:sky/widgets/ink_well.dart';
15 import 'package:sky/widgets/scrollable.dart'; 17 import 'package:sky/widgets/scrollable.dart';
16 import 'package:sky/widgets/theme.dart'; 18 import 'package:sky/widgets/theme.dart';
17 import 'package:sky/widgets/widget.dart'; 19 import 'package:sky/widgets/widget.dart';
18 20
19 typedef void SelectedIndexChanged(int selectedIndex); 21 typedef void SelectedIndexChanged(int selectedIndex);
20 typedef void LayoutChanged(Size size, List<double> widths); 22 typedef void LayoutChanged(Size size, List<double> widths);
21 23
22 // See https://www.google.com/design/spec/components/tabs.html#tabs-specs 24 // See https://www.google.com/design/spec/components/tabs.html#tabs-specs
23 const double _kTabHeight = 46.0; 25 const double _kTabHeight = 46.0;
24 const double _kTextAndIconTabHeight = 72.0; 26 const double _kTextAndIconTabHeight = 72.0;
25 const double _kTabIndicatorHeight = 2.0; 27 const double _kTabIndicatorHeight = 2.0;
26 const double _kMinTabWidth = 72.0; 28 const double _kMinTabWidth = 72.0;
27 const double _kMaxTabWidth = 264.0; 29 const double _kMaxTabWidth = 264.0;
28 const double _kRelativeMaxTabWidth = 56.0; 30 const double _kRelativeMaxTabWidth = 56.0;
29 const EdgeDims _kTabLabelPadding = const EdgeDims.symmetric(horizontal: 12.0); 31 const EdgeDims _kTabLabelPadding = const EdgeDims.symmetric(horizontal: 12.0);
30 const TextStyle _kTabTextStyle = const TextStyle(textAlign: TextAlign.center); 32 const TextStyle _kTabTextStyle = const TextStyle(textAlign: TextAlign.center);
31 const int _kTabIconSize = 24; 33 const int _kTabIconSize = 24;
34 const double _kTabBarScrollFriction = 0.005;
32 35
33 class TabBarParentData extends BoxParentData with 36 class TabBarParentData extends BoxParentData with
34 ContainerParentDataMixin<RenderBox> { } 37 ContainerParentDataMixin<RenderBox> { }
35 38
36 class RenderTabBar extends RenderBox with 39 class RenderTabBar extends RenderBox with
37 ContainerRenderObjectMixin<RenderBox, TabBarParentData>, 40 ContainerRenderObjectMixin<RenderBox, TabBarParentData>,
38 RenderBoxContainerDefaultsMixin<RenderBox, TabBarParentData> { 41 RenderBoxContainerDefaultsMixin<RenderBox, TabBarParentData> {
39 42
40 RenderTabBar(this.onLayoutChanged); 43 RenderTabBar(this.onLayoutChanged);
41 44
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 Container centeredLabel = new Container( 338 Container centeredLabel = new Container(
336 child: new Center(child: highlightedLabel), 339 child: new Center(child: highlightedLabel),
337 constraints: new BoxConstraints(minWidth: _kMinTabWidth), 340 constraints: new BoxConstraints(minWidth: _kMinTabWidth),
338 padding: _kTabLabelPadding 341 padding: _kTabLabelPadding
339 ); 342 );
340 343
341 return new InkWell(child: centeredLabel); 344 return new InkWell(child: centeredLabel);
342 } 345 }
343 } 346 }
344 347
348 class TabBarScrollBehavior extends ScrollBehavior {
349 TabBarScrollBehavior({ this.maxScrollOffset: 0.0 });
350
351 double maxScrollOffset;
352
353 Simulation release(Particle particle) {
354 if (particle.velocity == 0.0 || particle.position < 0.0 || particle.position >= maxScrollOffset)
355 return null;
356
357 System system = new ParticleInBoxWithFriction(
358 particle: particle,
359 friction: _kTabBarScrollFriction,
360 box: new ClosedBox(min: 0.0, max: maxScrollOffset));
361 return new Simulation(system, terminationCondition: () => particle.position == 0.0);
362 }
363
364 double applyCurve(double scrollOffset, double scrollDelta) {
365 return (scrollOffset + scrollDelta).clamp(0.0, maxScrollOffset);
366 }
367 }
368
345 class TabBar extends Scrollable { 369 class TabBar extends Scrollable {
346 TabBar({ 370 TabBar({
347 String key, 371 String key,
348 this.labels, 372 this.labels,
349 this.selectedIndex: 0, 373 this.selectedIndex: 0,
350 this.onChanged, 374 this.onChanged,
351 this.scrollable: false 375 this.scrollable: false
352 }) : super(key: key, direction: ScrollDirection.horizontal); 376 }) : super(key: key, direction: ScrollDirection.horizontal);
353 377
354 Iterable<TabLabel> labels; 378 Iterable<TabLabel> labels;
355 int selectedIndex; 379 int selectedIndex;
356 SelectedIndexChanged onChanged; 380 SelectedIndexChanged onChanged;
357 bool scrollable; 381 bool scrollable;
358 382
359 void syncFields(TabBar source) { 383 void syncFields(TabBar source) {
360 super.syncFields(source); 384 super.syncFields(source);
361 labels = source.labels; 385 labels = source.labels;
362 selectedIndex = source.selectedIndex; 386 selectedIndex = source.selectedIndex;
363 onChanged = source.onChanged; 387 onChanged = source.onChanged;
364 scrollable = source.scrollable; 388 scrollable = source.scrollable;
365 if (!scrollable) 389 if (!scrollable)
366 scrollTo(0.0); 390 scrollTo(0.0);
367 } 391 }
368 392
369 ScrollBehavior createScrollBehavior() => new BoundedScrollBehavior(); 393 ScrollBehavior createScrollBehavior() => new TabBarScrollBehavior();
370 BoundedScrollBehavior get scrollBehavior => super.scrollBehavior; 394 TabBarScrollBehavior get scrollBehavior => super.scrollBehavior;
371 395
372 void _handleTap(int tabIndex) { 396 void _handleTap(int tabIndex) {
373 if (tabIndex != selectedIndex && onChanged != null) 397 if (tabIndex != selectedIndex && onChanged != null)
374 onChanged(tabIndex); 398 onChanged(tabIndex);
375 } 399 }
376 400
377 Widget _toTab(TabLabel label, int tabIndex) { 401 Widget _toTab(TabLabel label, int tabIndex) {
378 Tab tab = new Tab( 402 Tab tab = new Tab(
379 label: label, 403 label: label,
380 selected: tabIndex == selectedIndex, 404 selected: tabIndex == selectedIndex,
381 key: label.text == null ? label.icon : label.text 405 key: label.text == null ? label.icon : label.text
382 ); 406 );
383 return new Listener( 407 return new Listener(
384 child: tab, 408 child: tab,
385 onGestureTap: (_) => _handleTap(tabIndex) 409 onGestureTap: (_) => _handleTap(tabIndex)
386 ); 410 );
387 } 411 }
388 412
389 Size _tabBarSize; 413 Size _tabBarSize;
390 List<double> _tabWidths; 414 List<double> _tabWidths;
391 415
392 void _layoutChanged(Size tabBarSize, List<double> tabWidths) { 416 void _layoutChanged(Size tabBarSize, List<double> tabWidths) {
393 setState(() { 417 setState(() {
394 _tabBarSize = tabBarSize; 418 _tabBarSize = tabBarSize;
395 _tabWidths = tabWidths; 419 _tabWidths = tabWidths;
396 scrollBehavior.maxOffset = 420 scrollBehavior.maxScrollOffset =
397 _tabWidths.reduce((sum, width) => sum + width) - _tabBarSize.width; 421 _tabWidths.reduce((sum, width) => sum + width) - _tabBarSize.width;
398 }); 422 });
399 } 423 }
400 424
401 Widget buildContent() { 425 Widget buildContent() {
402 assert(labels != null && labels.isNotEmpty); 426 assert(labels != null && labels.isNotEmpty);
403 List<Widget> tabs = <Widget>[]; 427 List<Widget> tabs = <Widget>[];
404 bool textAndIcons = false; 428 bool textAndIcons = false;
405 int tabIndex = 0; 429 int tabIndex = 0;
406 for (TabLabel label in labels) { 430 for (TabLabel label in labels) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 selectedIndex: selectedIndex, 492 selectedIndex: selectedIndex,
469 scrollable: scrollable 493 scrollable: scrollable
470 ); 494 );
471 495
472 Widget content = views[selectedIndex].buildContent(); 496 Widget content = views[selectedIndex].buildContent();
473 return new Flex([tabBar, new Flexible(child: content)], 497 return new Flex([tabBar, new Flexible(child: content)],
474 direction: FlexDirection.vertical 498 direction: FlexDirection.vertical
475 ); 499 );
476 } 500 }
477 } 501 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698