Problem description
PageView by default occupies the entire content area. If you want two pieces of content to be displayed in one screen, you need to set the viewportFraction property. With viewportFraction set, the content area is centered by default, and there is no left aligned property for the content area!! .
Use custom CustomPageView Pageview aligned left @flutter · GitHub
use
1: Create a new custom_page_view.dart file in the project
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class CustomPageView extends StatefulWidget {
CustomPageView({
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.allowImplicitScrolling = false.this.restorationId,
@required this.viewportDirection,
}) : assert(allowImplicitScrolling ! =null),
controller = controller ?? _defaultPageController,
childrenDelegate = SliverChildListDelegate(children),
super(key: key);
CustomPageView.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.allowImplicitScrolling = false.this.restorationId,
@required this.viewportDirection,
}) : assert(allowImplicitScrolling ! =null),
controller = controller ?? _defaultPageController,
childrenDelegate =
SliverChildBuilderDelegate(itemBuilder, childCount: itemCount),
super(key: key);
CustomPageView.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.allowImplicitScrolling = false.this.restorationId,
@required this.viewportDirection,
}) : assert(childrenDelegate ! =null),
assert(allowImplicitScrolling ! =null),
controller = controller ?? _defaultPageController,
super(key: key);
final bool allowImplicitScrolling;
final String restorationId;
final Axis scrollDirection;
final bool reverse;
final viewportDirection;
final PageController controller;
final ScrollPhysics physics;
final bool pageSnapping;
final ValueChanged<int> onPageChanged;
final SliverChildDelegate childrenDelegate;
/// {@macro flutter.widgets.scrollable.dragStartBehavior}
final DragStartBehavior dragStartBehavior;
@override
_CustomPageViewState createState() => _CustomPageViewState();
}
class _CustomPageViewState extends State<CustomPageView> {
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 = _ForceImplicitScrollPhysics(
allowImplicitScrolling: widget.allowImplicitScrolling,
).applyTo(widget.pageSnapping
? _kPagePhysics.applyTo(widget.physics)
: widget.physics);
return NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification notification) {
if (notification.depth == 0&& widget.onPageChanged ! =null &&
notification is ScrollUpdateNotification) {
final PageMetrics metrics = notification.metrics as PageMetrics;
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,
restorationId: widget.restorationId,
viewportBuilder: (BuildContext context, ViewportOffset position) {
return Viewport(
cacheExtent: widget.allowImplicitScrolling ? 1.0 : 0.0, cacheExtentStyle: CacheExtentStyle.viewport, axisDirection: axisDirection, offset: position, slivers: <Widget>[ SliverFillViewport( viewportFraction: widget.controller.viewportFraction, delegate: widget.childrenDelegate, padEnds: widget.viewportDirection, ), ], ); },),); }@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'));
description.add(FlagProperty('allowImplicitScrolling',
value: widget.allowImplicitScrolling,
ifTrue: 'allow implicit scrolling')); }}final PageController _defaultPageController = PageController();
const PageScrollPhysics _kPagePhysics = PageScrollPhysics();
class _ForceImplicitScrollPhysics extends ScrollPhysics {
const _ForceImplicitScrollPhysics({
@required this.allowImplicitScrolling,
ScrollPhysics parent,
}) : assert(allowImplicitScrolling ! =null),
super(parent: parent);
@override
_ForceImplicitScrollPhysics applyTo(ScrollPhysics ancestor) {
return _ForceImplicitScrollPhysics(
allowImplicitScrolling: allowImplicitScrolling,
parent: buildParent(ancestor),
);
}
@override
final bool allowImplicitScrolling;
}
Copy the code
2: Change the original PageView to CustomPageView
CustomPageView(
viewportDirection: false.// The key is this attribute
controller: PageController(viewportFraction: 0.8),
children: [
Container(color: Colors.red),
Container(color: Colors.blue),
Container(color: Colors.green),
Container(color: Colors.white),
])
Copy the code
Running effect
Related issue
Left Aligned ViewPort in Page View · Issue #52014 · flutter/flutter · GitHub