Commit 870376da authored by Adam Barth's avatar Adam Barth

Teach ScrollableBlock how to scroll horizontally

Now ScrollableBlock can combine a horizontally scrolling viewport with a
horizontal block.

Also rename ViewportScrollDirection to just ScrollDirection for less verbosity.
parent 6f2a3e40
// 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/painting/box_painter.dart';
import 'package:sky/widgets.dart';
class Circle extends Component {
Widget build() {
return new Container(
width: 50.0,
margin: new EdgeDims.symmetric(horizontal: 2.0),
decoration: new BoxDecoration(
shape: Shape.circle,
backgroundColor: const Color(0xFF00FF00)
)
);
}
}
class Pad extends Component {
Widget build() {
return new SizedBox(width: 10.0);
}
}
class HorizontalScrollingApp extends App {
Widget build() {
List<Widget> circles = [
new Pad(),
new Circle(),
new Circle(),
new Circle(),
new Circle(),
new Circle(),
new Circle(),
new Circle(),
new Circle(),
new Circle(),
new Circle(),
new Circle(),
new Circle(),
new Pad(),
];
return new Center(
child: new Container(
height: 50.0,
child: new Flex([
new ScrollableBlock(circles, scrollDirection: ScrollDirection.horizontal)
], justifyContent: FlexJustifyContent.end)
)
);
}
}
void main() {
runApp(new HorizontalScrollingApp());
}
......@@ -1121,27 +1121,27 @@ class RenderBaseline extends RenderShiftedBox {
String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}baseline: ${baseline}\nbaselineType: ${baselineType}';
}
enum ViewportScrollDirection { horizontal, vertical, both }
enum ScrollDirection { horizontal, vertical, both }
class RenderViewport extends RenderBox with RenderObjectWithChildMixin<RenderBox> {
RenderViewport({
RenderBox child,
Offset scrollOffset,
ViewportScrollDirection scrollDirection: ViewportScrollDirection.vertical
ScrollDirection scrollDirection: ScrollDirection.vertical
}) : _scrollOffset = scrollOffset,
_scrollDirection = scrollDirection {
assert(_offsetIsSane(scrollOffset, scrollDirection));
this.child = child;
}
bool _offsetIsSane(Offset offset, ViewportScrollDirection direction) {
bool _offsetIsSane(Offset offset, ScrollDirection direction) {
switch (direction) {
case ViewportScrollDirection.both:
case ScrollDirection.both:
return true;
case ViewportScrollDirection.horizontal:
case ScrollDirection.horizontal:
return offset.dy == 0.0;
case ViewportScrollDirection.vertical:
case ScrollDirection.vertical:
return offset.dx == 0.0;
}
}
......@@ -1156,9 +1156,9 @@ class RenderViewport extends RenderBox with RenderObjectWithChildMixin<RenderBox
markNeedsPaint();
}
ViewportScrollDirection _scrollDirection;
ViewportScrollDirection get scrollDirection => _scrollDirection;
void set scrollDirection(ViewportScrollDirection value) {
ScrollDirection _scrollDirection;
ScrollDirection get scrollDirection => _scrollDirection;
void set scrollDirection(ScrollDirection value) {
if (value == _scrollDirection)
return;
assert(_offsetIsSane(scrollOffset, value));
......@@ -1169,13 +1169,13 @@ class RenderViewport extends RenderBox with RenderObjectWithChildMixin<RenderBox
BoxConstraints _getInnerConstraints(BoxConstraints constraints) {
BoxConstraints innerConstraints;
switch (scrollDirection) {
case ViewportScrollDirection.both:
case ScrollDirection.both:
innerConstraints = new BoxConstraints();
break;
case ViewportScrollDirection.horizontal:
case ScrollDirection.horizontal:
innerConstraints = constraints.heightConstraints();
break;
case ViewportScrollDirection.vertical:
case ScrollDirection.vertical:
innerConstraints = constraints.widthConstraints();
break;
}
......
......@@ -20,7 +20,8 @@ import 'package:sky/widgets/default_text_style.dart';
import 'package:sky/widgets/framework.dart';
export 'package:sky/base/hit_test.dart' show EventDisposition, combineEventDispositions;
export 'package:sky/rendering/box.dart' show BackgroundImage, BoxConstraints, BoxDecoration, Border, BorderSide, EdgeDims, ViewportScrollDirection;
export 'package:sky/rendering/block.dart' show BlockDirection;
export 'package:sky/rendering/box.dart' show BackgroundImage, BoxConstraints, BoxDecoration, Border, BorderSide, EdgeDims, ScrollDirection;
export 'package:sky/rendering/flex.dart' show FlexDirection, FlexJustifyContent, FlexAlignItems;
export 'package:sky/rendering/object.dart' show Point, Offset, Size, Rect, Color, Paint, Path;
export 'package:sky/rendering/toggleable.dart' show ValueChanged;
......@@ -271,12 +272,12 @@ class Viewport extends OneChildRenderObjectWrapper {
Viewport({
Key key,
this.scrollOffset: Offset.zero,
this.scrollDirection: ViewportScrollDirection.vertical,
this.scrollDirection: ScrollDirection.vertical,
Widget child
}) : super(key: key, child: child);
final Offset scrollOffset;
final ViewportScrollDirection scrollDirection;
final ScrollDirection scrollDirection;
RenderViewport createNode() => new RenderViewport(scrollOffset: scrollOffset, scrollDirection: scrollDirection);
RenderViewport get root => super.root;
......@@ -371,11 +372,20 @@ class Container extends Component {
// LAYOUT NODES
class Block extends MultiChildRenderObjectWrapper {
Block(List<Widget> children, { Key key })
: super(key: key, children: children);
Block(List<Widget> children, {
Key key,
this.direction: BlockDirection.vertical
}) : super(key: key, children: children);
RenderBlock createNode() => new RenderBlock();
final BlockDirection direction;
RenderBlock createNode() => new RenderBlock(direction: direction);
RenderBlock get root => super.root;
void syncRenderObject(Widget old) {
super.syncRenderObject(old);
root.direction = direction;
}
}
class Stack extends MultiChildRenderObjectWrapper {
......@@ -417,7 +427,7 @@ class Flex extends MultiChildRenderObjectWrapper {
final FlexAlignItems alignItems;
final TextBaseline textBaseline;
RenderFlex createNode() => new RenderFlex(direction: this.direction);
RenderFlex createNode() => new RenderFlex(direction: direction);
RenderFlex get root => super.root;
void syncRenderObject(Widget old) {
......
......@@ -37,13 +37,13 @@ abstract class Scrollable extends StatefulComponent {
Scrollable({
Key key,
this.scrollDirection: ViewportScrollDirection.vertical
this.scrollDirection: ScrollDirection.vertical
}) : super(key: key) {
assert(scrollDirection == ViewportScrollDirection.vertical ||
scrollDirection == ViewportScrollDirection.horizontal);
assert(scrollDirection == ScrollDirection.vertical ||
scrollDirection == ScrollDirection.horizontal);
}
ViewportScrollDirection scrollDirection;
ScrollDirection scrollDirection;
AnimatedSimulation _toEndAnimation; // See _startToEndAnimation()
AnimationPerformance _toOffsetAnimation; // Started by scrollTo(offset, duration: d)
......@@ -65,7 +65,7 @@ abstract class Scrollable extends StatefulComponent {
double get scrollOffset => _scrollOffset;
Offset get scrollOffsetVector {
if (scrollDirection == ViewportScrollDirection.horizontal)
if (scrollDirection == ScrollDirection.horizontal)
return new Offset(scrollOffset, 0.0);
return new Offset(0.0, scrollOffset);
}
......@@ -176,7 +176,7 @@ abstract class Scrollable extends StatefulComponent {
}
bool scrollBy(double scrollDelta) {
var newScrollOffset = scrollBehavior.applyCurve(_scrollOffset, scrollDelta);
double newScrollOffset = scrollBehavior.applyCurve(_scrollOffset, scrollDelta);
return scrollTo(newScrollOffset);
}
......@@ -195,12 +195,12 @@ abstract class Scrollable extends StatefulComponent {
}
EventDisposition _handleScrollUpdate(sky.GestureEvent event) {
scrollBy(scrollDirection == ViewportScrollDirection.horizontal ? event.dx : -event.dy);
scrollBy(scrollDirection == ScrollDirection.horizontal ? event.dx : -event.dy);
return EventDisposition.processed;
}
EventDisposition _handleFlingStart(sky.GestureEvent event) {
double eventVelocity = scrollDirection == ViewportScrollDirection.horizontal
double eventVelocity = scrollDirection == ScrollDirection.horizontal
? -event.velocityX
: -event.velocityY;
_startToEndAnimation(velocity: _velocityForFlingGesture(eventVelocity));
......@@ -235,7 +235,7 @@ class ScrollableViewport extends Scrollable {
ScrollableViewport({
Key key,
this.child,
ViewportScrollDirection scrollDirection: ViewportScrollDirection.vertical
ScrollDirection scrollDirection: ScrollDirection.vertical
}) : super(key: key, scrollDirection: scrollDirection);
Widget child;
......@@ -248,19 +248,19 @@ class ScrollableViewport extends Scrollable {
ScrollBehavior createScrollBehavior() => new OverscrollWhenScrollableBehavior();
OverscrollWhenScrollableBehavior get scrollBehavior => super.scrollBehavior;
double _viewportHeight = 0.0;
double _childHeight = 0.0;
double _viewportSize = 0.0;
double _childSize = 0.0;
void _handleViewportSizeChanged(Size newSize) {
_viewportHeight = newSize.height;
_viewportSize = scrollDirection == ScrollDirection.vertical ? newSize.height : newSize.width;
_updateScrollBehaviour();
}
void _handleChildSizeChanged(Size newSize) {
_childHeight = newSize.height;
_childSize = scrollDirection == ScrollDirection.vertical ? newSize.height : newSize.width;
_updateScrollBehaviour();
}
void _updateScrollBehaviour() {
scrollBehavior.contentsSize = _childHeight;
scrollBehavior.containerSize = _viewportHeight;
scrollBehavior.contentsSize = _childSize;
scrollBehavior.containerSize = _viewportSize;
if (scrollOffset > scrollBehavior.maxScrollOffset)
settleScrollOffset();
}
......@@ -284,13 +284,24 @@ class ScrollableViewport extends Scrollable {
/// fixed number of children that you wish to arrange in a block layout and that
/// might exceed the height of its container (and therefore need to scroll).
class ScrollableBlock extends Component {
ScrollableBlock(this.children, { Key key }) : super(key: key);
ScrollableBlock(this.children, {
Key key,
this.scrollDirection: ScrollDirection.vertical
}) : super(key: key);
final List<Widget> children;
final ScrollDirection scrollDirection;
BlockDirection get _direction {
if (scrollDirection == ScrollDirection.vertical)
return BlockDirection.vertical;
return BlockDirection.horizontal;
}
Widget build() {
return new ScrollableViewport(
child: new Block(children)
scrollDirection: scrollDirection,
child: new Block(children, direction: _direction)
);
}
}
......
......@@ -396,7 +396,7 @@ class TabBar extends Scrollable {
this.selectedIndex: 0,
this.onChanged,
this.isScrollable: false
}) : super(key: key, scrollDirection: ViewportScrollDirection.horizontal);
}) : super(key: key, scrollDirection: ScrollDirection.horizontal);
Iterable<TabLabel> labels;
int selectedIndex;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment