You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
234 lines
8.0 KiB
234 lines
8.0 KiB
/*
|
|
* ====================================================
|
|
* package :
|
|
* author : Created by nansi.
|
|
* time : 2019/6/3 10:51 AM
|
|
* remark :
|
|
* ====================================================
|
|
*/
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/gestures.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
|
|
final PageController _defaultPageController = PageController();
|
|
const PageScrollPhysics _kPagePhysics = PageScrollPhysics();
|
|
|
|
class CachePageView extends StatefulWidget {
|
|
/// Creates a scrollable list that works page by page from an explicit [List]
|
|
/// of widgets.
|
|
///
|
|
/// This constructor is appropriate for page views with a small number of
|
|
/// children because constructing the [List] requires doing work for every
|
|
/// child that could possibly be displayed in the page view, instead of just
|
|
/// those children that are actually visible.
|
|
CachePageView({
|
|
Key key,
|
|
this.scrollDirection = Axis.horizontal,
|
|
this.reverse = false,
|
|
PageController controller,
|
|
this.physics,
|
|
this.pageSnapping = true,
|
|
this.onPageChanged,
|
|
List<Widget> children = const <Widget>[],
|
|
this.dragStartBehavior = DragStartBehavior.start,
|
|
this.cacheCount = 0,
|
|
}) : controller = controller ?? _defaultPageController,
|
|
childrenDelegate = SliverChildListDelegate(children),
|
|
super(key: key);
|
|
|
|
/// Creates a scrollable list that works page by page using widgets that are
|
|
/// created on demand.
|
|
///
|
|
/// This constructor is appropriate for page views with a large (or infinite)
|
|
/// number of children because the builder is called only for those children
|
|
/// that are actually visible.
|
|
///
|
|
/// Providing a non-null [itemCount] lets the [PageView] compute the maximum
|
|
/// scroll extent.
|
|
///
|
|
/// [itemBuilder] will be called only with indices greater than or equal to
|
|
/// zero and less than [itemCount].
|
|
CachePageView.builder({
|
|
Key key,
|
|
this.scrollDirection = Axis.horizontal,
|
|
this.reverse = false,
|
|
PageController controller,
|
|
this.physics,
|
|
this.pageSnapping = true,
|
|
this.onPageChanged,
|
|
@required IndexedWidgetBuilder itemBuilder,
|
|
int itemCount,
|
|
this.dragStartBehavior = DragStartBehavior.start,
|
|
this.cacheCount = 0,
|
|
}) : controller = controller ?? _defaultPageController,
|
|
childrenDelegate =
|
|
SliverChildBuilderDelegate(itemBuilder, childCount: itemCount),
|
|
super(key: key);
|
|
|
|
/// Creates a scrollable list that works page by page with a custom child
|
|
/// model.
|
|
CachePageView.custom({
|
|
Key key,
|
|
this.scrollDirection = Axis.horizontal,
|
|
this.reverse = false,
|
|
PageController controller,
|
|
this.physics,
|
|
this.pageSnapping = true,
|
|
this.onPageChanged,
|
|
@required this.childrenDelegate,
|
|
this.dragStartBehavior = DragStartBehavior.start,
|
|
this.cacheCount = 0,
|
|
}) : assert(childrenDelegate != null),
|
|
controller = controller ?? _defaultPageController,
|
|
super(key: key);
|
|
|
|
/// cache count
|
|
final cacheCount;
|
|
|
|
/// The axis along which the page view scrolls.
|
|
///
|
|
/// Defaults to [Axis.horizontal].
|
|
final Axis scrollDirection;
|
|
|
|
/// Whether the page view scrolls in the reading direction.
|
|
///
|
|
/// For example, if the reading direction is left-to-right and
|
|
/// [scrollDirection] is [Axis.horizontal], then the page view scrolls from
|
|
/// left to right when [reverse] is false and from right to left when
|
|
/// [reverse] is true.
|
|
///
|
|
/// Similarly, if [scrollDirection] is [Axis.vertical], then the page view
|
|
/// scrolls from top to bottom when [reverse] is false and from bottom to top
|
|
/// when [reverse] is true.
|
|
///
|
|
/// Defaults to false.
|
|
final bool reverse;
|
|
|
|
/// An object that can be used to control the position to which this page
|
|
/// view is scrolled.
|
|
final PageController controller;
|
|
|
|
/// How the page view should respond to user input.
|
|
///
|
|
/// For example, determines how the page view continues to animate after the
|
|
/// user stops dragging the page view.
|
|
///
|
|
/// The physics are modified to snap to page boundaries using
|
|
/// [PageScrollPhysics] prior to being used.
|
|
///
|
|
/// Defaults to matching platform conventions.
|
|
final ScrollPhysics physics;
|
|
|
|
/// Set to false to disable page snapping, useful for custom scroll behavior.
|
|
final bool pageSnapping;
|
|
|
|
/// Called whenever the page in the center of the viewport changes.
|
|
final ValueChanged<int> onPageChanged;
|
|
|
|
/// A delegate that provides the children for the [PageView].
|
|
///
|
|
/// The [PageView.custom] constructor lets you specify this delegate
|
|
/// explicitly. The [PageView] and [PageView.builder] constructors create a
|
|
/// [childrenDelegate] that wraps the given [List] and [IndexedWidgetBuilder],
|
|
/// respectively.
|
|
final SliverChildDelegate childrenDelegate;
|
|
|
|
/// {@macro flutter.widgets.scrollable.dragStartBehavior}
|
|
final DragStartBehavior dragStartBehavior;
|
|
|
|
@override
|
|
_CachePageViewState createState() => _CachePageViewState();
|
|
}
|
|
|
|
class _CachePageViewState extends State<CachePageView> {
|
|
int _lastReportedPage = 0;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_lastReportedPage = widget.controller.initialPage;
|
|
}
|
|
|
|
AxisDirection _getDirection(BuildContext context) {
|
|
switch (widget.scrollDirection) {
|
|
case Axis.horizontal:
|
|
assert(debugCheckHasDirectionality(context));
|
|
final TextDirection textDirection = Directionality.of(context);
|
|
final AxisDirection axisDirection =
|
|
textDirectionToAxisDirection(textDirection);
|
|
return widget.reverse
|
|
? flipAxisDirection(axisDirection)
|
|
: axisDirection;
|
|
case Axis.vertical:
|
|
return widget.reverse ? AxisDirection.up : AxisDirection.down;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final AxisDirection axisDirection = _getDirection(context);
|
|
final ScrollPhysics physics = widget.pageSnapping
|
|
? _kPagePhysics.applyTo(widget.physics)
|
|
: widget.physics;
|
|
|
|
return LayoutBuilder(
|
|
builder: (context, constraints) {
|
|
return NotificationListener<ScrollNotification>(
|
|
onNotification: (ScrollNotification notification) {
|
|
if (notification.depth == 0 &&
|
|
widget.onPageChanged != null &&
|
|
notification is ScrollUpdateNotification) {
|
|
final PageMetrics metrics = notification.metrics;
|
|
final int currentPage = metrics.page.round();
|
|
if (currentPage != _lastReportedPage) {
|
|
_lastReportedPage = currentPage;
|
|
widget.onPageChanged(currentPage);
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
child: Scrollable(
|
|
dragStartBehavior: widget.dragStartBehavior,
|
|
axisDirection: axisDirection,
|
|
controller: widget.controller,
|
|
physics: physics,
|
|
viewportBuilder: (BuildContext context, ViewportOffset position) {
|
|
return Viewport(
|
|
cacheExtent: widget.cacheCount * constraints.maxWidth,
|
|
axisDirection: axisDirection,
|
|
offset: position,
|
|
slivers: <Widget>[
|
|
SliverFillViewport(
|
|
viewportFraction: widget.controller.viewportFraction,
|
|
delegate: widget.childrenDelegate,
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
@override
|
|
void debugFillProperties(DiagnosticPropertiesBuilder description) {
|
|
super.debugFillProperties(description);
|
|
description
|
|
.add(EnumProperty<Axis>('scrollDirection', widget.scrollDirection));
|
|
description.add(
|
|
FlagProperty('reverse', value: widget.reverse, ifTrue: 'reversed'));
|
|
description.add(DiagnosticsProperty<PageController>(
|
|
'controller', widget.controller,
|
|
showName: false));
|
|
description.add(DiagnosticsProperty<ScrollPhysics>(
|
|
'physics', widget.physics,
|
|
showName: false));
|
|
description.add(FlagProperty('pageSnapping',
|
|
value: widget.pageSnapping, ifFalse: 'snapping disabled'));
|
|
}
|
|
}
|