| OLD | NEW |
| 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'; | 7 import 'package:sky/animation/generators.dart'; |
| 8 import 'package:sky/animation/mechanics.dart'; | 8 import 'package:sky/animation/mechanics.dart'; |
| 9 import 'package:sky/animation/scroll_behavior.dart'; | 9 import 'package:sky/animation/scroll_behavior.dart'; |
| 10 import 'package:sky/painting/text_style.dart'; | 10 import 'package:sky/painting/text_style.dart'; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 | 81 |
| 82 bool _scrollable; | 82 bool _scrollable; |
| 83 bool get scrollable => _scrollable; | 83 bool get scrollable => _scrollable; |
| 84 void set scrollable(bool value) { | 84 void set scrollable(bool value) { |
| 85 if (_scrollable != value) { | 85 if (_scrollable != value) { |
| 86 _scrollable = value; | 86 _scrollable = value; |
| 87 markNeedsLayout(); | 87 markNeedsLayout(); |
| 88 } | 88 } |
| 89 } | 89 } |
| 90 | 90 |
| 91 @override |
| 91 void setupParentData(RenderBox child) { | 92 void setupParentData(RenderBox child) { |
| 92 if (child.parentData is! TabBarParentData) | 93 if (child.parentData is! TabBarParentData) |
| 93 child.parentData = new TabBarParentData(); | 94 child.parentData = new TabBarParentData(); |
| 94 } | 95 } |
| 95 | 96 |
| 97 @override |
| 96 double getMinIntrinsicWidth(BoxConstraints constraints) { | 98 double getMinIntrinsicWidth(BoxConstraints constraints) { |
| 97 BoxConstraints widthConstraints = | 99 BoxConstraints widthConstraints = |
| 98 new BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraint
s.maxHeight); | 100 new BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraint
s.maxHeight); |
| 99 | 101 |
| 100 double maxWidth = 0.0; | 102 double maxWidth = 0.0; |
| 101 RenderBox child = firstChild; | 103 RenderBox child = firstChild; |
| 102 while (child != null) { | 104 while (child != null) { |
| 103 maxWidth = math.max(maxWidth, child.getMinIntrinsicWidth(widthConstraints)
); | 105 maxWidth = math.max(maxWidth, child.getMinIntrinsicWidth(widthConstraints)
); |
| 104 assert(child.parentData is TabBarParentData); | 106 assert(child.parentData is TabBarParentData); |
| 105 child = child.parentData.nextSibling; | 107 child = child.parentData.nextSibling; |
| 106 } | 108 } |
| 107 double width = scrollable ? maxWidth : maxWidth * childCount; | 109 double width = scrollable ? maxWidth : maxWidth * childCount; |
| 108 return constraints.constrainWidth(width); | 110 return constraints.constrainWidth(width); |
| 109 } | 111 } |
| 110 | 112 |
| 113 @override |
| 111 double getMaxIntrinsicWidth(BoxConstraints constraints) { | 114 double getMaxIntrinsicWidth(BoxConstraints constraints) { |
| 112 BoxConstraints widthConstraints = | 115 BoxConstraints widthConstraints = |
| 113 new BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraint
s.maxHeight); | 116 new BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraint
s.maxHeight); |
| 114 | 117 |
| 115 double maxWidth = 0.0; | 118 double maxWidth = 0.0; |
| 116 RenderBox child = firstChild; | 119 RenderBox child = firstChild; |
| 117 while (child != null) { | 120 while (child != null) { |
| 118 maxWidth = math.max(maxWidth, child.getMaxIntrinsicWidth(widthConstraints)
); | 121 maxWidth = math.max(maxWidth, child.getMaxIntrinsicWidth(widthConstraints)
); |
| 119 assert(child.parentData is TabBarParentData); | 122 assert(child.parentData is TabBarParentData); |
| 120 child = child.parentData.nextSibling; | 123 child = child.parentData.nextSibling; |
| 121 } | 124 } |
| 122 double width = scrollable ? maxWidth : maxWidth * childCount; | 125 double width = scrollable ? maxWidth : maxWidth * childCount; |
| 123 return constraints.constrainWidth(width); | 126 return constraints.constrainWidth(width); |
| 124 } | 127 } |
| 125 | 128 |
| 126 double get _tabBarHeight { | 129 double get _tabBarHeight { |
| 127 return (textAndIcons ? _kTextAndIconTabHeight : _kTabHeight) + _kTabIndicato
rHeight; | 130 return (textAndIcons ? _kTextAndIconTabHeight : _kTabHeight) + _kTabIndicato
rHeight; |
| 128 } | 131 } |
| 129 | 132 |
| 130 double _getIntrinsicHeight(BoxConstraints constraints) => constraints.constrai
nHeight(_tabBarHeight); | 133 double _getIntrinsicHeight(BoxConstraints constraints) => constraints.constrai
nHeight(_tabBarHeight); |
| 131 | 134 |
| 135 @override |
| 132 double getMinIntrinsicHeight(BoxConstraints constraints) => _getIntrinsicHeigh
t(constraints); | 136 double getMinIntrinsicHeight(BoxConstraints constraints) => _getIntrinsicHeigh
t(constraints); |
| 133 | 137 |
| 138 @override |
| 134 double getMaxIntrinsicHeight(BoxConstraints constraints) => _getIntrinsicHeigh
t(constraints); | 139 double getMaxIntrinsicHeight(BoxConstraints constraints) => _getIntrinsicHeigh
t(constraints); |
| 135 | 140 |
| 136 void layoutFixedWidthTabs() { | 141 void layoutFixedWidthTabs() { |
| 137 double tabWidth = size.width / childCount; | 142 double tabWidth = size.width / childCount; |
| 138 BoxConstraints tabConstraints = | 143 BoxConstraints tabConstraints = |
| 139 new BoxConstraints.tightFor(width: tabWidth, height: size.height); | 144 new BoxConstraints.tightFor(width: tabWidth, height: size.height); |
| 140 double x = 0.0; | 145 double x = 0.0; |
| 141 RenderBox child = firstChild; | 146 RenderBox child = firstChild; |
| 142 while (child != null) { | 147 while (child != null) { |
| 143 child.layout(tabConstraints); | 148 child.layout(tabConstraints); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 } | 189 } |
| 185 assert(childIndex == widths.length); | 190 assert(childIndex == widths.length); |
| 186 } | 191 } |
| 187 if (size != layoutSize || widths != layoutWidths) { | 192 if (size != layoutSize || widths != layoutWidths) { |
| 188 layoutSize = size; | 193 layoutSize = size; |
| 189 layoutWidths = widths; | 194 layoutWidths = widths; |
| 190 onLayoutChanged(layoutSize, layoutWidths); | 195 onLayoutChanged(layoutSize, layoutWidths); |
| 191 } | 196 } |
| 192 } | 197 } |
| 193 | 198 |
| 199 @override |
| 194 void performLayout() { | 200 void performLayout() { |
| 195 assert(constraints is BoxConstraints); | 201 assert(constraints is BoxConstraints); |
| 196 | 202 |
| 197 size = constraints.constrain(new Size(constraints.maxWidth, _tabBarHeight)); | 203 size = constraints.constrain(new Size(constraints.maxWidth, _tabBarHeight)); |
| 198 assert(!size.isInfinite); | 204 assert(!size.isInfinite); |
| 199 | 205 |
| 200 if (childCount == 0) | 206 if (childCount == 0) |
| 201 return; | 207 return; |
| 202 | 208 |
| 203 if (scrollable) | 209 if (scrollable) |
| 204 layoutScrollableTabs(); | 210 layoutScrollableTabs(); |
| 205 else | 211 else |
| 206 layoutFixedWidthTabs(); | 212 layoutFixedWidthTabs(); |
| 207 | 213 |
| 208 if (onLayoutChanged != null) | 214 if (onLayoutChanged != null) |
| 209 reportLayoutChangedIfNeeded(); | 215 reportLayoutChangedIfNeeded(); |
| 210 } | 216 } |
| 211 | 217 |
| 218 @override |
| 212 void hitTestChildren(HitTestResult result, { Point position }) { | 219 void hitTestChildren(HitTestResult result, { Point position }) { |
| 213 defaultHitTestChildren(result, position: position); | 220 defaultHitTestChildren(result, position: position); |
| 214 } | 221 } |
| 215 | 222 |
| 216 void _paintIndicator(PaintingCanvas canvas, RenderBox selectedTab, Offset offs
et) { | 223 void _paintIndicator(PaintingCanvas canvas, RenderBox selectedTab, Offset offs
et) { |
| 217 if (indicatorColor == null) | 224 if (indicatorColor == null) |
| 218 return; | 225 return; |
| 219 | 226 |
| 220 var size = new Size(selectedTab.size.width, _kTabIndicatorHeight); | 227 var size = new Size(selectedTab.size.width, _kTabIndicatorHeight); |
| 221 var point = new Point( | 228 var point = new Point( |
| 222 selectedTab.parentData.position.x, | 229 selectedTab.parentData.position.x, |
| 223 _tabBarHeight - _kTabIndicatorHeight | 230 _tabBarHeight - _kTabIndicatorHeight |
| 224 ); | 231 ); |
| 225 Rect rect = (point + offset) & size; | 232 Rect rect = (point + offset) & size; |
| 226 canvas.drawRect(rect, new Paint()..color = indicatorColor); | 233 canvas.drawRect(rect, new Paint()..color = indicatorColor); |
| 227 } | 234 } |
| 228 | 235 |
| 236 @override |
| 229 void paint(PaintingCanvas canvas, Offset offset) { | 237 void paint(PaintingCanvas canvas, Offset offset) { |
| 230 if (backgroundColor != null) { | 238 if (backgroundColor != null) { |
| 231 double width = layoutWidths != null | 239 double width = layoutWidths != null |
| 232 ? layoutWidths.reduce((sum, width) => sum + width) | 240 ? layoutWidths.reduce((sum, width) => sum + width) |
| 233 : size.width; | 241 : size.width; |
| 234 Rect rect = offset & new Size(width, size.height); | 242 Rect rect = offset & new Size(width, size.height); |
| 235 canvas.drawRect(rect, new Paint()..color = backgroundColor); | 243 canvas.drawRect(rect, new Paint()..color = backgroundColor); |
| 236 } | 244 } |
| 237 | 245 |
| 238 int index = 0; | 246 int index = 0; |
| 239 RenderBox child = firstChild; | 247 RenderBox child = firstChild; |
| 240 while (child != null) { | 248 while (child != null) { |
| 241 assert(child.parentData is TabBarParentData); | 249 assert(child.parentData is TabBarParentData); |
| 242 canvas.paintChild(child, child.parentData.position + offset); | 250 canvas.paintChild(child, child.parentData.position + offset); |
| 243 if (index++ == selectedIndex) | 251 if (index++ == selectedIndex) |
| 244 _paintIndicator(canvas, child, offset); | 252 _paintIndicator(canvas, child, offset); |
| 245 child = child.parentData.nextSibling; | 253 child = child.parentData.nextSibling; |
| 246 } | 254 } |
| 247 } | 255 } |
| 248 } | 256 } |
| 249 | 257 |
| 250 class TabBarWrapper extends MultiChildRenderObjectWrapper { | 258 class TabBarWrapper extends MultiChildRenderObjectWrapper { |
| 251 TabBarWrapper({ | 259 TabBarWrapper({ |
| 252 List<Widget> children, | 260 List<Widget> children, |
| 253 this.selectedIndex, | 261 this.selectedIndex, |
| 254 this.backgroundColor, | 262 this.backgroundColor, |
| 255 this.indicatorColor, | 263 this.indicatorColor, |
| 256 this.textAndIcons, | 264 this.textAndIcons, |
| 257 this.scrollable: false, | 265 this.scrollable: false, |
| 258 this.onLayoutChanged, | 266 this.onLayoutChanged, |
| 259 String key | 267 String key |
| 260 }) : super(key: key, children: children); | 268 }) : super(key: key, children: children); |
| 261 | 269 |
| 262 final int selectedIndex; | 270 final int selectedIndex; |
| 263 final Color backgroundColor; | 271 final Color backgroundColor; |
| 264 final Color indicatorColor; | 272 final Color indicatorColor; |
| 265 final bool textAndIcons; | 273 final bool textAndIcons; |
| 266 final bool scrollable; | 274 final bool scrollable; |
| 267 final LayoutChanged onLayoutChanged; | 275 final LayoutChanged onLayoutChanged; |
| 268 | 276 |
| 277 @override |
| 269 RenderTabBar get root => super.root; | 278 RenderTabBar get root => super.root; |
| 279 |
| 280 @override |
| 270 RenderTabBar createNode() => new RenderTabBar(onLayoutChanged); | 281 RenderTabBar createNode() => new RenderTabBar(onLayoutChanged); |
| 271 | 282 |
| 283 @override |
| 272 void syncRenderObject(Widget old) { | 284 void syncRenderObject(Widget old) { |
| 273 super.syncRenderObject(old); | 285 super.syncRenderObject(old); |
| 274 root.selectedIndex = selectedIndex; | 286 root.selectedIndex = selectedIndex; |
| 275 root.backgroundColor = backgroundColor; | 287 root.backgroundColor = backgroundColor; |
| 276 root.indicatorColor = indicatorColor; | 288 root.indicatorColor = indicatorColor; |
| 277 root.textAndIcons = textAndIcons; | 289 root.textAndIcons = textAndIcons; |
| 278 root.scrollable = scrollable; | 290 root.scrollable = scrollable; |
| 279 root.onLayoutChanged = onLayoutChanged; | 291 root.onLayoutChanged = onLayoutChanged; |
| 280 } | 292 } |
| 281 } | 293 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 303 assert(label.text != null); | 315 assert(label.text != null); |
| 304 TextStyle textStyle = Theme.of(this).toolbarText.button.merge(_kTabTextStyle
); | 316 TextStyle textStyle = Theme.of(this).toolbarText.button.merge(_kTabTextStyle
); |
| 305 return new Text(label.text, style: textStyle); | 317 return new Text(label.text, style: textStyle); |
| 306 } | 318 } |
| 307 | 319 |
| 308 Widget _buildLabelIcon() { | 320 Widget _buildLabelIcon() { |
| 309 assert(label.icon != null); | 321 assert(label.icon != null); |
| 310 return new Icon(type: label.icon, size: _kTabIconSize); | 322 return new Icon(type: label.icon, size: _kTabIconSize); |
| 311 } | 323 } |
| 312 | 324 |
| 325 @override |
| 313 Widget build() { | 326 Widget build() { |
| 314 Widget labelContents; | 327 Widget labelContents; |
| 315 if (label.icon == null) { | 328 if (label.icon == null) { |
| 316 labelContents = _buildLabelText(); | 329 labelContents = _buildLabelText(); |
| 317 } else if (label.text == null) { | 330 } else if (label.text == null) { |
| 318 labelContents = _buildLabelIcon(); | 331 labelContents = _buildLabelIcon(); |
| 319 } else { | 332 } else { |
| 320 labelContents = new Flex( | 333 labelContents = new Flex( |
| 321 <Widget>[ | 334 <Widget>[ |
| 322 new Container( | 335 new Container( |
| 323 child: _buildLabelIcon(), | 336 child: _buildLabelIcon(), |
| 324 margin: const EdgeDims.only(bottom: 10.0) | 337 margin: const EdgeDims.only(bottom: 10.0) |
| 325 ), | 338 ), |
| 326 _buildLabelText() | 339 _buildLabelText() |
| 327 ], | 340 ], |
| 328 justifyContent: FlexJustifyContent.center, | 341 justifyContent: FlexJustifyContent.center, |
| 329 alignItems: FlexAlignItems.center, | 342 alignItems: FlexAlignItems.center, |
| 330 direction: FlexDirection.vertical | 343 direction: FlexDirection.vertical |
| 331 ); | 344 ); |
| 332 } | 345 } |
| 333 | 346 |
| 334 Widget highlightedLabel = new Opacity( | 347 Widget highlightedLabel = new Opacity( |
| 335 child: labelContents, | 348 child: labelContents, |
| 336 opacity: selected ? 1.0 : 0.7 | 349 opacity: selected ? 1.0 : 0.7 |
| 337 ); | 350 ); |
| 338 | 351 |
| 339 Container centeredLabel = new Container( | 352 Container centeredLabel = new Container( |
| 340 child: new Center(child: highlightedLabel), | 353 child: new Center(child: highlightedLabel), |
| 341 constraints: new BoxConstraints(minWidth: _kMinTabWidth), | 354 constraints: new BoxConstraints(minWidth: _kMinTabWidth), |
| 342 padding: _kTabLabelPadding | 355 padding: _kTabLabelPadding |
| 343 ); | 356 ); |
| 344 | 357 |
| 345 return new InkWell(child: centeredLabel); | 358 return new InkWell(child: centeredLabel); |
| 346 } | 359 } |
| 347 } | 360 } |
| 348 | 361 |
| 349 class TabBarScrollBehavior extends ScrollBehavior { | 362 class TabBarScrollBehavior extends ScrollBehavior { |
| 350 TabBarScrollBehavior({ this.maxScrollOffset: 0.0 }); | 363 TabBarScrollBehavior({ this.maxScrollOffset: 0.0 }); |
| 351 | 364 |
| 352 double maxScrollOffset; | 365 double maxScrollOffset; |
| 353 | 366 |
| 367 @override |
| 354 Simulation release(Particle particle) { | 368 Simulation release(Particle particle) { |
| 355 if (particle.velocity == 0.0 || particle.position < 0.0 || particle.position
>= maxScrollOffset) | 369 if (particle.velocity == 0.0 || particle.position < 0.0 || particle.position
>= maxScrollOffset) |
| 356 return null; | 370 return null; |
| 357 | 371 |
| 358 System system = new ParticleInBoxWithFriction( | 372 System system = new ParticleInBoxWithFriction( |
| 359 particle: particle, | 373 particle: particle, |
| 360 friction: _kTabBarScrollFriction, | 374 friction: _kTabBarScrollFriction, |
| 361 box: new ClosedBox(min: 0.0, max: maxScrollOffset)); | 375 box: new ClosedBox(min: 0.0, max: maxScrollOffset)); |
| 362 return new Simulation(system, terminationCondition: () => particle.position
== 0.0); | 376 return new Simulation(system, terminationCondition: () => particle.position
== 0.0); |
| 363 } | 377 } |
| 364 | 378 |
| 379 @override |
| 365 double applyCurve(double scrollOffset, double scrollDelta) { | 380 double applyCurve(double scrollOffset, double scrollDelta) { |
| 366 return (scrollOffset + scrollDelta).clamp(0.0, maxScrollOffset); | 381 return (scrollOffset + scrollDelta).clamp(0.0, maxScrollOffset); |
| 367 } | 382 } |
| 368 } | 383 } |
| 369 | 384 |
| 370 class TabBar extends Scrollable { | 385 class TabBar extends Scrollable { |
| 371 TabBar({ | 386 TabBar({ |
| 372 String key, | 387 String key, |
| 373 this.labels, | 388 this.labels, |
| 374 this.selectedIndex: 0, | 389 this.selectedIndex: 0, |
| 375 this.onChanged, | 390 this.onChanged, |
| 376 this.scrollable: false | 391 this.scrollable: false |
| 377 }) : super(key: key, direction: ScrollDirection.horizontal); | 392 }) : super(key: key, direction: ScrollDirection.horizontal); |
| 378 | 393 |
| 379 Iterable<TabLabel> labels; | 394 Iterable<TabLabel> labels; |
| 380 int selectedIndex; | 395 int selectedIndex; |
| 381 SelectedIndexChanged onChanged; | 396 SelectedIndexChanged onChanged; |
| 382 bool scrollable; | 397 bool scrollable; |
| 383 | 398 |
| 399 @override |
| 384 void syncFields(TabBar source) { | 400 void syncFields(TabBar source) { |
| 385 super.syncFields(source); | 401 super.syncFields(source); |
| 386 labels = source.labels; | 402 labels = source.labels; |
| 387 selectedIndex = source.selectedIndex; | 403 selectedIndex = source.selectedIndex; |
| 388 onChanged = source.onChanged; | 404 onChanged = source.onChanged; |
| 389 scrollable = source.scrollable; | 405 scrollable = source.scrollable; |
| 390 if (!scrollable) | 406 if (!scrollable) |
| 391 scrollTo(0.0); | 407 scrollTo(0.0); |
| 392 } | 408 } |
| 393 | 409 |
| 410 @override |
| 394 ScrollBehavior createScrollBehavior() => new TabBarScrollBehavior(); | 411 ScrollBehavior createScrollBehavior() => new TabBarScrollBehavior(); |
| 412 |
| 413 @override |
| 395 TabBarScrollBehavior get scrollBehavior => super.scrollBehavior; | 414 TabBarScrollBehavior get scrollBehavior => super.scrollBehavior; |
| 396 | 415 |
| 397 void _handleTap(int tabIndex) { | 416 void _handleTap(int tabIndex) { |
| 398 if (tabIndex != selectedIndex && onChanged != null) | 417 if (tabIndex != selectedIndex && onChanged != null) |
| 399 onChanged(tabIndex); | 418 onChanged(tabIndex); |
| 400 } | 419 } |
| 401 | 420 |
| 402 Widget _toTab(TabLabel label, int tabIndex) { | 421 Widget _toTab(TabLabel label, int tabIndex) { |
| 403 Tab tab = new Tab( | 422 Tab tab = new Tab( |
| 404 label: label, | 423 label: label, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 416 | 435 |
| 417 void _layoutChanged(Size tabBarSize, List<double> tabWidths) { | 436 void _layoutChanged(Size tabBarSize, List<double> tabWidths) { |
| 418 setState(() { | 437 setState(() { |
| 419 _tabBarSize = tabBarSize; | 438 _tabBarSize = tabBarSize; |
| 420 _tabWidths = tabWidths; | 439 _tabWidths = tabWidths; |
| 421 scrollBehavior.maxScrollOffset = | 440 scrollBehavior.maxScrollOffset = |
| 422 _tabWidths.reduce((sum, width) => sum + width) - _tabBarSize.width; | 441 _tabWidths.reduce((sum, width) => sum + width) - _tabBarSize.width; |
| 423 }); | 442 }); |
| 424 } | 443 } |
| 425 | 444 |
| 445 @override |
| 426 Widget buildContent() { | 446 Widget buildContent() { |
| 427 assert(labels != null && labels.isNotEmpty); | 447 assert(labels != null && labels.isNotEmpty); |
| 428 List<Widget> tabs = <Widget>[]; | 448 List<Widget> tabs = <Widget>[]; |
| 429 bool textAndIcons = false; | 449 bool textAndIcons = false; |
| 430 int tabIndex = 0; | 450 int tabIndex = 0; |
| 431 for (TabLabel label in labels) { | 451 for (TabLabel label in labels) { |
| 432 tabs.add(_toTab(label, tabIndex++)); | 452 tabs.add(_toTab(label, tabIndex++)); |
| 433 if (label.text != null && label.icon != null) | 453 if (label.text != null && label.icon != null) |
| 434 textAndIcons = true; | 454 textAndIcons = true; |
| 435 } | 455 } |
| 436 | 456 |
| 437 Color backgroundColor = Theme.of(this).primaryColor; | 457 Color backgroundColor = Theme.of(this).primaryColor; |
| 438 Color indicatorColor = Theme.of(this).accentColor; | 458 Color indicatorColor = Theme.of(this).accentColor; |
| 439 if (indicatorColor == backgroundColor) { | 459 if (indicatorColor == backgroundColor) { |
| 440 indicatorColor = colors.White; | 460 indicatorColor = colors.White; |
| 441 } | 461 } |
| 442 | 462 |
| 443 TabBarWrapper tabBarWrapper = new TabBarWrapper( | 463 TabBarWrapper tabBarWrapper = new TabBarWrapper( |
| 444 children: tabs, | 464 children: tabs, |
| 445 selectedIndex: selectedIndex, | 465 selectedIndex: selectedIndex, |
| 446 backgroundColor: backgroundColor, | 466 backgroundColor: backgroundColor, |
| 447 indicatorColor: indicatorColor, | 467 indicatorColor: indicatorColor, |
| 448 textAndIcons: textAndIcons, | 468 textAndIcons: textAndIcons, |
| 449 scrollable: scrollable, | 469 scrollable: scrollable, |
| 450 onLayoutChanged: scrollable ? _layoutChanged : null | 470 onLayoutChanged: scrollable ? _layoutChanged : null |
| 451 ); | 471 ); |
| 452 | 472 |
| 453 Matrix4 transform = new Matrix4.identity(); | 473 Matrix4 transform = new Matrix4.identity(); |
| 454 transform.translate(-scrollOffset, 0.0); | 474 transform.translate(-scrollOffset, 0.0); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 482 final List<TabNavigatorView> views; | 502 final List<TabNavigatorView> views; |
| 483 final int selectedIndex; | 503 final int selectedIndex; |
| 484 final SelectedIndexChanged onChanged; | 504 final SelectedIndexChanged onChanged; |
| 485 final bool scrollable; | 505 final bool scrollable; |
| 486 | 506 |
| 487 void _handleSelectedIndexChanged(int tabIndex) { | 507 void _handleSelectedIndexChanged(int tabIndex) { |
| 488 if (onChanged != null) | 508 if (onChanged != null) |
| 489 onChanged(tabIndex); | 509 onChanged(tabIndex); |
| 490 } | 510 } |
| 491 | 511 |
| 512 @override |
| 492 Widget build() { | 513 Widget build() { |
| 493 assert(views != null && views.isNotEmpty); | 514 assert(views != null && views.isNotEmpty); |
| 494 assert(selectedIndex >= 0 && selectedIndex < views.length); | 515 assert(selectedIndex >= 0 && selectedIndex < views.length); |
| 495 | 516 |
| 496 TabBar tabBar = new TabBar( | 517 TabBar tabBar = new TabBar( |
| 497 labels: views.map((view) => view.label), | 518 labels: views.map((view) => view.label), |
| 498 onChanged: _handleSelectedIndexChanged, | 519 onChanged: _handleSelectedIndexChanged, |
| 499 selectedIndex: selectedIndex, | 520 selectedIndex: selectedIndex, |
| 500 scrollable: scrollable | 521 scrollable: scrollable |
| 501 ); | 522 ); |
| 502 | 523 |
| 503 Widget content = views[selectedIndex].buildContent(); | 524 Widget content = views[selectedIndex].buildContent(); |
| 504 return new Flex([tabBar, new Flexible(child: content)], | 525 return new Flex([tabBar, new Flexible(child: content)], |
| 505 direction: FlexDirection.vertical | 526 direction: FlexDirection.vertical |
| 506 ); | 527 ); |
| 507 } | 528 } |
| 508 } | 529 } |
| OLD | NEW |