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

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

Issue 1213043002: Make TabBar conform to the Material spec for icon/text tabs (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Update test expectations Created 5 years, 6 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 | sky/tests/examples/tabs-expected.txt » ('j') | 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/rendering/box.dart'; 7 import 'package:sky/rendering/box.dart';
8 import 'package:sky/rendering/object.dart'; 8 import 'package:sky/rendering/object.dart';
9 import 'package:sky/widgets/basic.dart'; 9 import 'package:sky/widgets/basic.dart';
10 import 'package:sky/widgets/icon.dart'; 10 import 'package:sky/widgets/icon.dart';
11 import 'package:sky/widgets/ink_well.dart'; 11 import 'package:sky/widgets/ink_well.dart';
12 import 'package:sky/widgets/theme.dart'; 12 import 'package:sky/widgets/theme.dart';
13 import 'package:sky/widgets/widget.dart'; 13 import 'package:sky/widgets/widget.dart';
14 14
15 typedef void SelectedIndexChanged(int selectedIndex); 15 typedef void SelectedIndexChanged(int selectedIndex);
16 16
17 const double _kTabHeight = 46.0; 17 const double _kTabHeight = 46.0;
18 const double _kTextAndIconTabHeight = 72.0;
18 const double _kTabIndicatorHeight = 2.0; 19 const double _kTabIndicatorHeight = 2.0;
19 const double _kTabBarHeight = _kTabHeight + _kTabIndicatorHeight;
20 const double _kMinTabWidth = 72.0; 20 const double _kMinTabWidth = 72.0;
21 const int _kTabIconSize = 24; 21 const int _kTabIconSize = 24;
22 22
23 class TabBarParentData extends BoxParentData with 23 class TabBarParentData extends BoxParentData with
24 ContainerParentDataMixin<RenderBox> { } 24 ContainerParentDataMixin<RenderBox> { }
25 25
26 class RenderTabBar extends RenderBox with 26 class RenderTabBar extends RenderBox with
27 ContainerRenderObjectMixin<RenderBox, TabBarParentData>, 27 ContainerRenderObjectMixin<RenderBox, TabBarParentData>,
28 RenderBoxContainerDefaultsMixin<RenderBox, TabBarParentData> { 28 RenderBoxContainerDefaultsMixin<RenderBox, TabBarParentData> {
29 29
(...skipping 17 matching lines...) Expand all
47 47
48 Color _indicatorColor; 48 Color _indicatorColor;
49 Color get indicatorColor => _indicatorColor; 49 Color get indicatorColor => _indicatorColor;
50 void set indicatorColor(Color value) { 50 void set indicatorColor(Color value) {
51 if (_indicatorColor != value) { 51 if (_indicatorColor != value) {
52 _indicatorColor = value; 52 _indicatorColor = value;
53 markNeedsPaint(); 53 markNeedsPaint();
54 } 54 }
55 } 55 }
56 56
57 bool _textAndIcons;
58 bool get textAndIcons => _textAndIcons;
59 void set textAndIcons(bool value) {
60 if (_textAndIcons != value) {
61 _textAndIcons = value;
62 markNeedsLayout();
63 }
64 }
65
57 void setupParentData(RenderBox child) { 66 void setupParentData(RenderBox child) {
58 if (child.parentData is! TabBarParentData) 67 if (child.parentData is! TabBarParentData)
59 child.parentData = new TabBarParentData(); 68 child.parentData = new TabBarParentData();
60 } 69 }
61 70
62 double getMinIntrinsicWidth(BoxConstraints constraints) { 71 double getMinIntrinsicWidth(BoxConstraints constraints) {
63 BoxConstraints widthConstraints = 72 BoxConstraints widthConstraints =
64 new BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraint s.maxHeight); 73 new BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraint s.maxHeight);
65 double maxWidth = 0.0; 74 double maxWidth = 0.0;
66 RenderBox child = firstChild; 75 RenderBox child = firstChild;
(...skipping 11 matching lines...) Expand all
78 double maxWidth = 0.0; 87 double maxWidth = 0.0;
79 RenderBox child = firstChild; 88 RenderBox child = firstChild;
80 while (child != null) { 89 while (child != null) {
81 maxWidth = math.max(maxWidth, child.getMaxIntrinsicWidth(widthConstraints) ); 90 maxWidth = math.max(maxWidth, child.getMaxIntrinsicWidth(widthConstraints) );
82 assert(child.parentData is TabBarParentData); 91 assert(child.parentData is TabBarParentData);
83 child = child.parentData.nextSibling; 92 child = child.parentData.nextSibling;
84 } 93 }
85 return constraints.constrainWidth(maxWidth * childCount); 94 return constraints.constrainWidth(maxWidth * childCount);
86 } 95 }
87 96
88 double _getIntrinsicHeight(BoxConstraints constraints) => constraints.constrai nHeight(_kTabBarHeight); 97 double get _tabBarHeight {
98 return (textAndIcons ? _kTextAndIconTabHeight : _kTabHeight) + _kTabIndicato rHeight;
99 }
100
101 double _getIntrinsicHeight(BoxConstraints constraints) => constraints.constrai nHeight(_tabBarHeight);
89 102
90 double getMinIntrinsicHeight(BoxConstraints constraints) => _getIntrinsicHeigh t(constraints); 103 double getMinIntrinsicHeight(BoxConstraints constraints) => _getIntrinsicHeigh t(constraints);
91 104
92 double getMaxIntrinsicHeight(BoxConstraints constraints) => _getIntrinsicHeigh t(constraints); 105 double getMaxIntrinsicHeight(BoxConstraints constraints) => _getIntrinsicHeigh t(constraints);
93 106
94 void performLayout() { 107 void performLayout() {
95 assert(constraints is BoxConstraints); 108 assert(constraints is BoxConstraints);
96 109
97 size = constraints.constrain(new Size(constraints.maxWidth, _kTabBarHeight)) ; 110 size = constraints.constrain(new Size(constraints.maxWidth, _tabBarHeight));
98 assert(!size.isInfinite); 111 assert(!size.isInfinite);
99 112
100 if (childCount == 0) 113 if (childCount == 0)
101 return; 114 return;
102 115
103 double tabWidth = size.width / childCount; 116 double tabWidth = size.width / childCount;
104 BoxConstraints tabConstraints = 117 BoxConstraints tabConstraints =
105 new BoxConstraints.tightFor(width: tabWidth, height: size.height); 118 new BoxConstraints.tightFor(width: tabWidth, height: size.height);
106 double x = 0.0; 119 double x = 0.0;
107 RenderBox child = firstChild; 120 RenderBox child = firstChild;
108 while (child != null) { 121 while (child != null) {
109 child.layout(tabConstraints); 122 child.layout(tabConstraints);
110 assert(child.parentData is TabBarParentData); 123 assert(child.parentData is TabBarParentData);
111 child.parentData.position = new Point(x, 0.0); 124 child.parentData.position = new Point(x, 0.0);
112 x += tabWidth; 125 x += tabWidth;
113 child = child.parentData.nextSibling; 126 child = child.parentData.nextSibling;
114 } 127 }
115 } 128 }
116 129
117 void hitTestChildren(HitTestResult result, { Point position }) { 130 void hitTestChildren(HitTestResult result, { Point position }) {
118 defaultHitTestChildren(result, position: position); 131 defaultHitTestChildren(result, position: position);
119 } 132 }
120 133
121 void _paintIndicator(RenderCanvas canvas, RenderBox selectedTab) { 134 void _paintIndicator(RenderCanvas canvas, RenderBox selectedTab) {
122 if (indicatorColor == null) 135 if (indicatorColor == null)
123 return; 136 return;
124 137
125 var size = new Size(selectedTab.size.width, _kTabIndicatorHeight); 138 var size = new Size(selectedTab.size.width, _kTabIndicatorHeight);
126 var point = new Point(selectedTab.parentData.position.x, _kTabHeight); 139 var point = new Point(
140 selectedTab.parentData.position.x,
141 _tabBarHeight - _kTabIndicatorHeight);
127 Rect rect = new Rect.fromPointAndSize(point, size); 142 Rect rect = new Rect.fromPointAndSize(point, size);
128 canvas.drawRect(rect, new Paint()..color = indicatorColor); 143 canvas.drawRect(rect, new Paint()..color = indicatorColor);
129 } 144 }
130 145
131 void paint(RenderCanvas canvas) { 146 void paint(RenderCanvas canvas) {
132 if (backgroundColor != null) { 147 if (backgroundColor != null) {
133 Rect rect = new Rect.fromSize(size); 148 Rect rect = new Rect.fromSize(size);
134 canvas.drawRect(rect, new Paint()..color = backgroundColor); 149 canvas.drawRect(rect, new Paint()..color = backgroundColor);
135 } 150 }
136 151
137 int index = 0; 152 int index = 0;
138 RenderBox child = firstChild; 153 RenderBox child = firstChild;
139 while (child != null) { 154 while (child != null) {
140 assert(child.parentData is TabBarParentData); 155 assert(child.parentData is TabBarParentData);
141 canvas.paintChild(child, child.parentData.position); 156 canvas.paintChild(child, child.parentData.position);
142 if (index++ == selectedIndex) 157 if (index++ == selectedIndex)
143 _paintIndicator(canvas, child); 158 _paintIndicator(canvas, child);
144 child = child.parentData.nextSibling; 159 child = child.parentData.nextSibling;
145 } 160 }
146 } 161 }
147 } 162 }
148 163
149 class TabBarWrapper extends MultiChildRenderObjectWrapper { 164 class TabBarWrapper extends MultiChildRenderObjectWrapper {
150 TabBarWrapper({ 165 TabBarWrapper({
151 List<Widget> children, 166 List<Widget> children,
152 this.selectedIndex, 167 this.selectedIndex,
153 this.backgroundColor, 168 this.backgroundColor,
154 this.indicatorColor, 169 this.indicatorColor,
170 this.textAndIcons,
155 String key 171 String key
156 }) : super(key: key, children: children); 172 }) : super(key: key, children: children);
157 173
158 final int selectedIndex; 174 final int selectedIndex;
159 final Color backgroundColor; 175 final Color backgroundColor;
160 final Color indicatorColor; 176 final Color indicatorColor;
177 final bool textAndIcons;
161 178
162 RenderTabBar get root => super.root; 179 RenderTabBar get root => super.root;
163 RenderTabBar createNode() => new RenderTabBar(); 180 RenderTabBar createNode() => new RenderTabBar();
164 181
165 void syncRenderObject(Widget old) { 182 void syncRenderObject(Widget old) {
166 super.syncRenderObject(old); 183 super.syncRenderObject(old);
167 root.selectedIndex = selectedIndex; 184 root.selectedIndex = selectedIndex;
168 root.backgroundColor = backgroundColor; 185 root.backgroundColor = backgroundColor;
169 root.indicatorColor = indicatorColor; 186 root.indicatorColor = indicatorColor;
187 root.textAndIcons = textAndIcons;
170 } 188 }
171 } 189 }
172 190
173 class TabLabel { 191 class TabLabel {
174 const TabLabel({ this.text, this.icon }); 192 const TabLabel({ this.text, this.icon });
175 193
176 final String text; 194 final String text;
177 final String icon; 195 final String icon;
178 } 196 }
179 197
(...skipping 20 matching lines...) Expand all
200 } 218 }
201 219
202 Widget build() { 220 Widget build() {
203 Widget labelContents; 221 Widget labelContents;
204 if (label.icon == null) { 222 if (label.icon == null) {
205 labelContents = _buildLabelText(); 223 labelContents = _buildLabelText();
206 } else if (label.text == null) { 224 } else if (label.text == null) {
207 labelContents = _buildLabelIcon(); 225 labelContents = _buildLabelIcon();
208 } else { 226 } else {
209 labelContents = new Flex( 227 labelContents = new Flex(
210 <Widget>[_buildLabelText(), _buildLabelIcon()], 228 <Widget>[
229 new Container(
230 child: _buildLabelIcon(),
231 margin: const EdgeDims.only(bottom: 10.0)
232 ),
233 _buildLabelText()
234 ],
211 justifyContent: FlexJustifyContent.center, 235 justifyContent: FlexJustifyContent.center,
212 alignItems: FlexAlignItems.center, 236 alignItems: FlexAlignItems.center,
213 direction: FlexDirection.vertical 237 direction: FlexDirection.vertical
214 ); 238 );
215 } 239 }
216 240
217 Widget highlightedLabel = new Opacity( 241 Widget highlightedLabel = new Opacity(
218 child: labelContents, 242 child: labelContents,
219 opacity: selected ? 1.0 : 0.7 243 opacity: selected ? 1.0 : 0.7
220 ); 244 );
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 ); 277 );
254 return new Listener( 278 return new Listener(
255 child: tab, 279 child: tab,
256 onGestureTap: (_) => _handleTap(tabIndex) 280 onGestureTap: (_) => _handleTap(tabIndex)
257 ); 281 );
258 } 282 }
259 283
260 Widget build() { 284 Widget build() {
261 assert(labels != null && labels.isNotEmpty); 285 assert(labels != null && labels.isNotEmpty);
262 List<Widget> tabs = <Widget>[]; 286 List<Widget> tabs = <Widget>[];
287 bool textAndIcons = false;
263 for (int tabIndex = 0; tabIndex < labels.length; tabIndex++) { 288 for (int tabIndex = 0; tabIndex < labels.length; tabIndex++) {
264 tabs.add(_toTab(labels[tabIndex], tabIndex)); 289 tabs.add(_toTab(labels[tabIndex], tabIndex));
290 if (labels[tabIndex].text != null && labels[tabIndex].icon != null)
291 textAndIcons = true;
265 } 292 }
266 return new TabBarWrapper( 293 return new TabBarWrapper(
267 children: tabs, 294 children: tabs,
268 selectedIndex: selectedIndex, 295 selectedIndex: selectedIndex,
269 backgroundColor: Theme.of(this).primary[500], 296 backgroundColor: Theme.of(this).primary[500],
270 indicatorColor: Theme.of(this).accent[200] 297 indicatorColor: Theme.of(this).accent[200],
298 textAndIcons: textAndIcons
271 ); 299 );
272 } 300 }
273 } 301 }
274
275
OLDNEW
« no previous file with comments | « no previous file | sky/tests/examples/tabs-expected.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698