Commit 69311c28 authored by Adam Barth's avatar Adam Barth

Improve date picker fidelity (#4023)

This patch updates the date picker to match the new spec.

We're still missing a fade effect when scrolling from one month to
another and we're missing the landscape layout.

Fixes #3558
parent ef563c48
...@@ -18,12 +18,8 @@ enum PageableListFlingBehavior { ...@@ -18,12 +18,8 @@ enum PageableListFlingBehavior {
stopAtNextPage stopAtNextPage
} }
/// Scrollable widget that scrolls one "page" at a time. abstract class PageableListBase extends Scrollable {
/// PageableListBase({
/// In a pageable list, one child is visible at a time. Scrolling the list
/// reveals either the next or previous child.
class PageableList extends Scrollable {
PageableList({
Key key, Key key,
double initialScrollOffset, double initialScrollOffset,
Axis scrollDirection: Axis.vertical, Axis scrollDirection: Axis.vertical,
...@@ -36,8 +32,7 @@ class PageableList extends Scrollable { ...@@ -36,8 +32,7 @@ class PageableList extends Scrollable {
this.itemsSnapAlignment: PageableListFlingBehavior.stopAtNextPage, this.itemsSnapAlignment: PageableListFlingBehavior.stopAtNextPage,
this.onPageChanged, this.onPageChanged,
this.duration: const Duration(milliseconds: 200), this.duration: const Duration(milliseconds: 200),
this.curve: Curves.ease, this.curve: Curves.ease
this.children
}) : super( }) : super(
key: key, key: key,
initialScrollOffset: initialScrollOffset, initialScrollOffset: initialScrollOffset,
...@@ -66,19 +61,102 @@ class PageableList extends Scrollable { ...@@ -66,19 +61,102 @@ class PageableList extends Scrollable {
/// The animation curve to use when animating to a given page. /// The animation curve to use when animating to a given page.
final Curve curve; final Curve curve;
int get _itemCount;
}
/// Scrollable widget that scrolls one "page" at a time.
///
/// In a pageable list, one child is visible at a time. Scrolling the list
/// reveals either the next or previous child.
class PageableList extends PageableListBase {
PageableList({
Key key,
double initialScrollOffset,
Axis scrollDirection: Axis.vertical,
ViewportAnchor scrollAnchor: ViewportAnchor.start,
ScrollListener onScrollStart,
ScrollListener onScroll,
ScrollListener onScrollEnd,
SnapOffsetCallback snapOffsetCallback,
bool itemsWrap: false,
PageableListFlingBehavior itemsSnapAlignment: PageableListFlingBehavior.stopAtNextPage,
ValueChanged<int> onPageChanged,
Duration duration: const Duration(milliseconds: 200),
Curve curve: Curves.ease,
this.children
}) : super(
key: key,
initialScrollOffset: initialScrollOffset,
scrollDirection: scrollDirection,
scrollAnchor: scrollAnchor,
onScrollStart: onScrollStart,
onScroll: onScroll,
onScrollEnd: onScrollEnd,
snapOffsetCallback: snapOffsetCallback,
itemsWrap: itemsWrap,
itemsSnapAlignment: itemsSnapAlignment,
onPageChanged: onPageChanged,
duration: duration,
curve: curve
);
/// The list of pages themselves. /// The list of pages themselves.
final Iterable<Widget> children; final Iterable<Widget> children;
@override
int get _itemCount => children?.length ?? 0;
@override @override
PageableListState<PageableList> createState() => new PageableListState<PageableList>(); PageableListState<PageableList> createState() => new PageableListState<PageableList>();
} }
/// State for a [PageableList] widget. class PageableLazyList extends PageableListBase {
/// PageableLazyList({
/// Widgets that subclass [PageableList] can subclass this class to have Key key,
/// sensible default behaviors for pageable lists. double initialScrollOffset,
class PageableListState<T extends PageableList> extends ScrollableState<T> { Axis scrollDirection: Axis.vertical,
int get _itemCount => config.children?.length ?? 0; ViewportAnchor scrollAnchor: ViewportAnchor.start,
ScrollListener onScrollStart,
ScrollListener onScroll,
ScrollListener onScrollEnd,
SnapOffsetCallback snapOffsetCallback,
PageableListFlingBehavior itemsSnapAlignment: PageableListFlingBehavior.stopAtNextPage,
ValueChanged<int> onPageChanged,
Duration duration: const Duration(milliseconds: 200),
Curve curve: Curves.ease,
this.itemCount,
this.itemBuilder
}) : super(
key: key,
initialScrollOffset: initialScrollOffset,
scrollDirection: scrollDirection,
scrollAnchor: scrollAnchor,
onScrollStart: onScrollStart,
onScroll: onScroll,
onScrollEnd: onScrollEnd,
snapOffsetCallback: snapOffsetCallback,
itemsWrap: false,
itemsSnapAlignment: itemsSnapAlignment,
onPageChanged: onPageChanged,
duration: duration,
curve: curve
);
/// The total number of list items.
final int itemCount;
/// A function that returns the pages themselves.
final ItemListBuilder itemBuilder;
@override
int get _itemCount => itemCount ?? 0;
@override
_PageableLazyListState createState() => new _PageableLazyListState();
}
abstract class _PageableListStateBase<T extends PageableListBase> extends ScrollableState<T> {
int get _itemCount => config._itemCount;
int _previousItemCount; int _previousItemCount;
double get _pixelsPerScrollUnit { double get _pixelsPerScrollUnit {
...@@ -124,7 +202,7 @@ class PageableListState<T extends PageableList> extends ScrollableState<T> { ...@@ -124,7 +202,7 @@ class PageableListState<T extends PageableList> extends ScrollableState<T> {
} }
@override @override
void didUpdateConfig(PageableList oldConfig) { void didUpdateConfig(PageableListBase oldConfig) {
super.didUpdateConfig(oldConfig); super.didUpdateConfig(oldConfig);
bool scrollBehaviorUpdateNeeded = config.scrollDirection != oldConfig.scrollDirection; bool scrollBehaviorUpdateNeeded = config.scrollDirection != oldConfig.scrollDirection;
...@@ -149,17 +227,6 @@ class PageableListState<T extends PageableList> extends ScrollableState<T> { ...@@ -149,17 +227,6 @@ class PageableListState<T extends PageableList> extends ScrollableState<T> {
)); ));
} }
@override
Widget buildContent(BuildContext context) {
return new PageViewport(
itemsWrap: config.itemsWrap,
mainAxis: config.scrollDirection,
anchor: config.scrollAnchor,
startOffset: scrollOffset,
children: config.children
);
}
UnboundedBehavior _unboundedBehavior; UnboundedBehavior _unboundedBehavior;
OverscrollBehavior _overscrollBehavior; OverscrollBehavior _overscrollBehavior;
...@@ -216,15 +283,44 @@ class PageableListState<T extends PageableList> extends ScrollableState<T> { ...@@ -216,15 +283,44 @@ class PageableListState<T extends PageableList> extends ScrollableState<T> {
} }
} }
class PageViewport extends VirtualViewportFromIterable { /// State for a [PageableList] widget.
PageViewport({ ///
this.startOffset: 0.0, /// Widgets that subclass [PageableList] can subclass this class to have
this.mainAxis: Axis.vertical, /// sensible default behaviors for pageable lists.
this.anchor: ViewportAnchor.start, class PageableListState<T extends PageableList> extends _PageableListStateBase<T> {
this.itemsWrap: false, @override
this.overlayPainter, Widget buildContent(BuildContext context) {
this.children return new PageViewport(
}) { itemsWrap: config.itemsWrap,
mainAxis: config.scrollDirection,
anchor: config.scrollAnchor,
startOffset: scrollOffset,
children: config.children
);
}
}
class _PageableLazyListState extends _PageableListStateBase<PageableLazyList> {
@override
Widget buildContent(BuildContext context) {
return new LazyPageViewport(
mainAxis: config.scrollDirection,
anchor: config.scrollAnchor,
startOffset: scrollOffset,
itemCount: config.itemCount,
itemBuilder: config.itemBuilder
);
}
}
class _VirtualPageViewport extends VirtualViewport {
_VirtualPageViewport(
this.startOffset,
this.mainAxis,
this.anchor,
this.itemsWrap,
this.overlayPainter
) {
assert(mainAxis != null); assert(mainAxis != null);
} }
...@@ -236,21 +332,18 @@ class PageViewport extends VirtualViewportFromIterable { ...@@ -236,21 +332,18 @@ class PageViewport extends VirtualViewportFromIterable {
final bool itemsWrap; final bool itemsWrap;
final RenderObjectPainter overlayPainter; final RenderObjectPainter overlayPainter;
@override
final Iterable<Widget> children;
@override @override
RenderList createRenderObject(BuildContext context) => new RenderList(); RenderList createRenderObject(BuildContext context) => new RenderList();
@override @override
_PageViewportElement createElement() => new _PageViewportElement(this); _VirtualPageViewportElement createElement() => new _VirtualPageViewportElement(this);
} }
class _PageViewportElement extends VirtualViewportElement { class _VirtualPageViewportElement extends VirtualViewportElement {
_PageViewportElement(PageViewport widget) : super(widget); _VirtualPageViewportElement(_VirtualPageViewport widget) : super(widget);
@override @override
PageViewport get widget => super.widget; _VirtualPageViewport get widget => super.widget;
@override @override
RenderList get renderObject => super.renderObject; RenderList get renderObject => super.renderObject;
...@@ -279,7 +372,7 @@ class _PageViewportElement extends VirtualViewportElement { ...@@ -279,7 +372,7 @@ class _PageViewportElement extends VirtualViewportElement {
} }
@override @override
void updateRenderObject(PageViewport oldWidget) { void updateRenderObject(_VirtualPageViewport oldWidget) {
renderObject renderObject
..mainAxis = widget.mainAxis ..mainAxis = widget.mainAxis
..overlayPainter = widget.overlayPainter; ..overlayPainter = widget.overlayPainter;
...@@ -342,3 +435,46 @@ class _PageViewportElement extends VirtualViewportElement { ...@@ -342,3 +435,46 @@ class _PageViewportElement extends VirtualViewportElement {
super.layout(constraints); super.layout(constraints);
} }
} }
class PageViewport extends _VirtualPageViewport with VirtualViewportFromIterable {
PageViewport({
double startOffset: 0.0,
Axis mainAxis: Axis.vertical,
ViewportAnchor anchor: ViewportAnchor.start,
bool itemsWrap: false,
RenderObjectPainter overlayPainter,
this.children
}) : super(
startOffset,
mainAxis,
anchor,
itemsWrap,
overlayPainter
);
@override
final Iterable<Widget> children;
}
class LazyPageViewport extends _VirtualPageViewport with VirtualViewportFromBuilder {
LazyPageViewport({
double startOffset: 0.0,
Axis mainAxis: Axis.vertical,
ViewportAnchor anchor: ViewportAnchor.start,
RenderObjectPainter overlayPainter,
this.itemCount,
this.itemBuilder
}) : super(
startOffset,
mainAxis,
anchor,
false, // Don't support wrapping yet.
overlayPainter
);
@override
final int itemCount;
@override
final ItemListBuilder itemBuilder;
}
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