浏览代码

page view

/main
fzhangtj 6 年前
当前提交
acdd4632
共有 13 个文件被更改,包括 633 次插入13 次删除
  1. 8
      Runtime/rendering/sliver_fixed_extent_list.cs
  2. 2
      Runtime/widgets/app.cs
  3. 4
      Runtime/widgets/scroll_controller.cs
  4. 13
      Runtime/widgets/scroll_metrics.cs
  5. 8
      Runtime/widgets/scroll_position.cs
  6. 20
      Runtime/widgets/sliver.cs
  7. 75
      Samples/UIWidgetSample/Navigation.unity
  8. 91
      Runtime/rendering/sliver_fill.cs
  9. 11
      Runtime/rendering/sliver_fill.cs.meta
  10. 363
      Runtime/widgets/page_view.cs
  11. 11
      Runtime/widgets/page_view.cs.meta
  12. 29
      Samples/UIWidgetSample/PageViewCanvas.cs
  13. 11
      Samples/UIWidgetSample/PageViewCanvas.cs.meta

8
Runtime/rendering/sliver_fixed_extent_list.cs


public abstract double itemExtent { get; set; }
protected double indexToLayoutOffset(double itemExtent, int index) {
protected virtual double indexToLayoutOffset(double itemExtent, int index) {
protected int getMinChildIndexForScrollOffset(double scrollOffset, double itemExtent) {
protected virtual int getMinChildIndexForScrollOffset(double scrollOffset, double itemExtent) {
protected int getMaxChildIndexForScrollOffset(double scrollOffset, double itemExtent) {
protected virtual int getMaxChildIndexForScrollOffset(double scrollOffset, double itemExtent) {
protected double estimateMaxScrollOffset(SliverConstraints constraints,
protected virtual double estimateMaxScrollOffset(SliverConstraints constraints,
int firstIndex = 0,
int lastIndex = 0,
double leadingScrollOffset = 0.0,

2
Runtime/widgets/app.cs


D.assert(
builder != null ||
home != null ||
routes.ContainsKey(Navigator.defaultRouteName) ||
this.routes.ContainsKey(Navigator.defaultRouteName) ||
onGenerateRoute != null ||
onUnknownRoute != null,
"Either the home property must be specified, " +

4
Runtime/widgets/scroll_controller.cs


public readonly string debugLabel;
public IEnumerable<ScrollPosition> positions {
public ICollection<ScrollPosition> positions {
get { return this._positions; }
}

base.dispose();
}
public ScrollPosition createScrollPosition(
public virtual ScrollPosition createScrollPosition(
ScrollPhysics physics,
ScrollContext context,
ScrollPosition oldPosition

13
Runtime/widgets/scroll_metrics.cs


double? maxScrollExtent = null,
double? pixels = null,
double? viewportDimension = null,
AxisDirection? axisDirection = null
AxisDirection? axisDirection = null,
double? viewportFraction = null
if (it is IPageMetrics) {
return new PageMetrics(
minScrollExtent: minScrollExtent ?? it.minScrollExtent,
maxScrollExtent: maxScrollExtent ?? it.maxScrollExtent,
pixels: pixels ?? it.pixels,
viewportDimension: viewportDimension ?? it.viewportDimension,
axisDirection: axisDirection ?? it.axisDirection,
viewportFraction: viewportFraction ?? ((IPageMetrics) it).viewportFraction
);
}
return new FixedScrollMetrics(
minScrollExtent: minScrollExtent ?? it.minScrollExtent,
maxScrollExtent: maxScrollExtent ?? it.maxScrollExtent,

8
Runtime/widgets/scroll_position.cs


public override double pixels {
get {
D.assert(this._pixels != null);
//D.assert(this._pixels != null);
return this._pixels ?? 0.0;
}
}

public double viewportDimension {
get { return this._viewportDimension.Value; }
get { return this._viewportDimension??0.0; }
}
double? _viewportDimension;

this.notifyListeners();
}
protected void saveScrollOffset() {
protected virtual void saveScrollOffset() {
var pageStorage = PageStorage.of(this.context.storageContext);
if (pageStorage != null) {
pageStorage.writeState(this.context.storageContext, this.pixels);

protected void restoreScrollOffset() {
protected virtual void restoreScrollOffset() {
if (this._pixels == null) {
var pageStorage = PageStorage.of(this.context.storageContext);
if (pageStorage != null) {

20
Runtime/widgets/sliver.cs


}
}
public class SliverFillViewport: SliverMultiBoxAdaptorWidget {
public SliverFillViewport(
Key key = null, SliverChildDelegate del = null,
double viewportFraction = 1.0): base(key: key, del: del) {
D.assert(viewportFraction > 0.0);
this.viewportFraction = viewportFraction;
}
public readonly double viewportFraction;
public override RenderObject createRenderObject(BuildContext context) {
SliverMultiBoxAdaptorElement element = (SliverMultiBoxAdaptorElement)context;
return new RenderSliverFillViewport(childManager: element, viewportFraction: viewportFraction);
}
public override void updateRenderObject(BuildContext context, RenderObject renderObject) {
((RenderSliverFillViewport)renderObject).viewportFraction = viewportFraction;
}
}
public class SliverMultiBoxAdaptorElement : RenderObjectElement, RenderSliverBoxChildManager {
public SliverMultiBoxAdaptorElement(SliverMultiBoxAdaptorWidget widget) : base(widget) {

75
Samples/UIWidgetSample/Navigation.unity


m_LocalScale: {x: 0, y: 0, z: 0}
m_Children:
- {fileID: 927824195}
- {fileID: 1818957069}
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!224 &927824195
RectTransform:
m_ObjectHideFlags: 0

m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 927824194}
m_CullTransparentMesh: 0
--- !u!1 &1818957068
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1818957069}
- component: {fileID: 1818957071}
- component: {fileID: 1818957070}
m_Layer: 5
m_Name: PageView
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1818957069
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1818957068}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 4286176}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1818957070
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1818957068}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a8dea5be0500345ccb20b797d19e741c, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Texture: {fileID: 0}
m_UVRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
--- !u!222 &1818957071
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1818957068}
m_CullTransparentMesh: 0
--- !u!1 &1838283857
GameObject:

91
Runtime/rendering/sliver_fill.cs


using System;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
using UnityEngine;
namespace Unity.UIWidgets.rendering {
public class RenderSliverFillViewport : RenderSliverFixedExtentBoxAdaptor {
public RenderSliverFillViewport(
RenderSliverBoxChildManager childManager = null,
double viewportFraction = 1.0
) :
base(childManager: childManager) {
D.assert(viewportFraction > 0.0);
this._viewportFraction = viewportFraction;
}
public override double itemExtent {
get => this.constraints.viewportMainAxisExtent * this.viewportFraction;
set {}
}
double _viewportFraction;
public double viewportFraction {
get => this._viewportFraction;
set {
if (this._viewportFraction == value)
return;
this._viewportFraction = value;
this.markNeedsLayout();
}
}
double _padding => (1.0 - this.viewportFraction) * this.constraints.viewportMainAxisExtent * 0.5;
protected override double indexToLayoutOffset(double itemExtent, int index) {
return this._padding + base.indexToLayoutOffset(itemExtent, index);
}
protected override int getMinChildIndexForScrollOffset(double scrollOffset, double itemExtent) {
return base.getMinChildIndexForScrollOffset(Math.Max(scrollOffset - this._padding, 0.0), itemExtent);
}
protected override int getMaxChildIndexForScrollOffset(double scrollOffset, double itemExtent) {
return base.getMaxChildIndexForScrollOffset(Math.Max(scrollOffset - this._padding, 0.0), itemExtent);
}
protected override double estimateMaxScrollOffset(SliverConstraints constraints,
int firstIndex = 0,
int lastIndex = 0,
double leadingScrollOffset = 0.0,
double trailingScrollOffset = 0.0
) {
double padding = this._padding;
return this.childManager.estimateMaxScrollOffset(
constraints,
firstIndex: firstIndex,
lastIndex: lastIndex,
leadingScrollOffset: leadingScrollOffset - padding,
trailingScrollOffset: trailingScrollOffset - padding
) + padding + padding;
}
}
public class RenderSliverFillRemaining : RenderSliverSingleBoxAdapter {
public RenderSliverFillRemaining(
RenderBox child
) : base(child: child) {
}
protected override void performLayout() {
double extent = this.constraints.remainingPaintExtent - Math.Min(this.constraints.overlap, 0.0);
if (this.child != null)
this.child.layout(this.constraints.asBoxConstraints(minExtent: extent, maxExtent: extent),
parentUsesSize: true);
double paintedChildSize = this.calculatePaintOffset(this.constraints, from: 0.0, to: extent);
Debug.Log("size" + paintedChildSize);
D.assert(paintedChildSize.isFinite());
D.assert(paintedChildSize >= 0.0);
this.geometry = new SliverGeometry(
scrollExtent: this.constraints.viewportMainAxisExtent,
paintExtent: paintedChildSize,
maxPaintExtent: paintedChildSize,
hasVisualOverflow: extent > this.constraints.remainingPaintExtent ||
this.constraints.scrollOffset > 0.0
);
if (this.child != null) this.setChildParentData(this.child, this.constraints, this.geometry);
}
}
}

11
Runtime/rendering/sliver_fill.cs.meta


fileFormatVersion: 2
guid: 2172361941dad4eb2acd42f7d238704c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

363
Runtime/widgets/page_view.cs


using System;
using System.Collections.Generic;
using RSG;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.physics;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.widgets {
public class PageController : ScrollController {
public PageController(
int initialPage = 0,
bool keepPage = true,
double viewportFraction = 1.0
) {
this.initialPage = initialPage;
this.keepPage = keepPage;
this.viewportFraction = viewportFraction;
D.assert(viewportFraction > 0.0);
}
public readonly int initialPage;
public readonly bool keepPage;
public readonly double viewportFraction;
public double page {
get {
D.assert(this.positions.isNotEmpty(),
"PageController.page cannot be accessed before a PageView is built with it."
);
D.assert(this.positions.Count == 1,
"The page property cannot be read when multiple PageViews are attached to " +
"the same PageController."
);
_PagePosition position = (_PagePosition) this.position;
return position.page;
}
}
public IPromise animateToPage(int page, TimeSpan duration, Curve curve) {
_PagePosition position = (_PagePosition) this.position;
return position.animateTo(
position.getPixelsFromPage(page),
duration,
curve
);
}
public void jumpToPage(int page) {
_PagePosition position = (_PagePosition) this.position;
position.jumpTo(position.getPixelsFromPage(page));
}
public IPromise nextPage(TimeSpan duration, Curve curve) {
return this.animateToPage(this.page.round() + 1, duration: duration, curve: curve);
}
public IPromise previousPage(TimeSpan duration, Curve curve) {
return this.animateToPage(this.page.round() - 1, duration: duration, curve: curve);
}
public override ScrollPosition createScrollPosition(ScrollPhysics physics, ScrollContext context,
ScrollPosition oldPosition) {
return new _PagePosition(
physics: physics,
context: context,
initialPage: this.initialPage,
keepPage: this.keepPage,
viewportFraction: this.viewportFraction,
oldPosition: oldPosition
);
}
public override void attach(ScrollPosition position) {
base.attach(position);
_PagePosition pagePosition = (_PagePosition) position;
pagePosition.viewportFraction = this.viewportFraction;
}
}
public interface IPageMetrics : ScrollMetrics {
double page { get; }
double viewportFraction { get; }
}
public class PageMetrics : FixedScrollMetrics, IPageMetrics {
public PageMetrics(
double minScrollExtent = 0.0,
double maxScrollExtent = 0.0,
double pixels = 0.0,
double viewportDimension = 0.0,
AxisDirection axisDirection = AxisDirection.down,
double viewportFraction = 0.0
) : base(
minScrollExtent: minScrollExtent,
maxScrollExtent: maxScrollExtent,
pixels: pixels,
viewportDimension: viewportDimension,
axisDirection: axisDirection
) {
this._viewportFraction = viewportFraction;
}
public readonly double _viewportFraction;
public double page => Math.Max(0.0, this.pixels.clamp(this.minScrollExtent, this.maxScrollExtent)) /
Math.Max(1.0, this.viewportDimension * this.viewportFraction);
public double viewportFraction => this._viewportFraction;
}
internal class _PagePosition : ScrollPositionWithSingleContext, IPageMetrics {
internal _PagePosition(
ScrollPhysics physics = null,
ScrollContext context = null,
int initialPage = 0,
bool keepPage = true,
double viewportFraction = 1.0,
ScrollPosition oldPosition = null
) :
base(
physics: physics,
context: context,
initialPixels: null,
keepScrollOffset: keepPage,
oldPosition: oldPosition
) {
D.assert(viewportFraction > 0.0);
this._viewportFraction = viewportFraction;
this._pageToUseOnStartup = initialPage;
}
public readonly int initialPage;
double _pageToUseOnStartup;
public double viewportFraction {
get => this._viewportFraction;
set {
if (this._viewportFraction == value)
return;
double oldPage = this.page;
this._viewportFraction = value;
this.forcePixels(this.getPixelsFromPage(oldPage));
}
}
double _viewportFraction;
public double getPageFromPixels(double pixels, double viewportDimension) {
return Math.Max(0.0, pixels) / Math.Max(1.0, viewportDimension * this.viewportFraction);
}
public double getPixelsFromPage(double page) {
return page * this.viewportDimension * this.viewportFraction;
}
public double page => this.getPageFromPixels(this.pixels.clamp(this.minScrollExtent, this.maxScrollExtent),
this.viewportDimension);
protected override void saveScrollOffset() {
PageStorage.of(this.context.storageContext)?.writeState(this.context.storageContext,
this.getPageFromPixels(this.pixels, this.viewportDimension));
}
protected override void restoreScrollOffset() {
object value = PageStorage.of(this.context.storageContext)?.readState(this.context.storageContext);
if (value != null) this._pageToUseOnStartup = (double) value;
}
public override bool applyViewportDimension(double viewportDimension) {
double oldViewportDimensions = this.viewportDimension;
bool result = base.applyViewportDimension(viewportDimension);
double oldPixels = this.pixels;
double page = (oldPixels == null || oldViewportDimensions == 0.0)
? this._pageToUseOnStartup
: this.getPageFromPixels(oldPixels, oldViewportDimensions);
double newPixels = this.getPixelsFromPage(page);
if (newPixels != oldPixels) {
this.correctPixels(newPixels);
return false;
}
return result;
}
}
public class PageScrollPhysics : ScrollPhysics {
public PageScrollPhysics(ScrollPhysics parent = null) : base(parent: parent) {
}
public override ScrollPhysics applyTo(ScrollPhysics ancestor) {
return new PageScrollPhysics(parent: this.buildParent(ancestor));
}
double _getPage(ScrollPosition position) {
if (position is _PagePosition)
return ((_PagePosition) position).page;
return position.pixels / position.viewportDimension;
}
double _getPixels(ScrollPosition position, double page) {
if (position is _PagePosition)
return ((_PagePosition) position).getPixelsFromPage(page);
return page * position.viewportDimension;
}
double _getTargetPixels(ScrollPosition position, Tolerance tolerance, double velocity) {
double page = this._getPage(position);
if (velocity < -tolerance.velocity)
page -= 0.5;
else if (velocity > tolerance.velocity)
page += 0.5;
return this._getPixels(position, page.round());
}
public override Simulation createBallisticSimulation(ScrollMetrics position, double velocity) {
if ((velocity <= 0.0 && position.pixels <= position.minScrollExtent) ||
(velocity >= 0.0 && position.pixels >= position.maxScrollExtent))
return base.createBallisticSimulation(position, velocity);
Tolerance tolerance = this.tolerance;
double target = this._getTargetPixels((ScrollPosition) position, tolerance, velocity);
if (target != position.pixels)
return new ScrollSpringSimulation(this.spring, position.pixels, target, velocity, tolerance: tolerance);
return null;
}
public override bool allowImplicitScrolling => false;
}
public static class PageViewUtils {
internal static PageController _defaultPageController = new PageController();
internal static PageScrollPhysics _kPagePhysics = new PageScrollPhysics();
}
public class PageView : StatefulWidget {
public PageView(
Key key = null,
Axis scrollDirection = Axis.horizontal,
bool reverse = false,
PageController controller = null,
ScrollPhysics physics = null,
bool pageSnapping = true,
ValueChanged<int> onPageChanged = null,
List<Widget> children = null,
IndexedWidgetBuilder itemBuilder = null,
SliverChildDelegate childDelegate = null,
int itemCount = 0
) : base(key: key) {
this.scrollDirection = scrollDirection;
this.reverse = reverse;
this.physics = physics;
this.pageSnapping = pageSnapping;
this.onPageChanged = onPageChanged;
this.controller = controller ?? PageViewUtils._defaultPageController;
if (itemBuilder != null)
this.childrenDelegate = new SliverChildBuilderDelegate(itemBuilder, childCount: itemCount);
else if (childDelegate != null)
this.childrenDelegate = childDelegate;
else
this.childrenDelegate = new SliverChildListDelegate(children ?? new List<Widget>());
}
public readonly Axis scrollDirection;
public readonly bool reverse;
public readonly PageController controller;
public readonly ScrollPhysics physics;
public readonly bool pageSnapping;
public readonly ValueChanged<int> onPageChanged;
public readonly SliverChildDelegate childrenDelegate;
public override State createState() {
return new _PageViewState();
}
}
internal class _PageViewState : State<PageView> {
int _lastReportedPage = 0;
public override void initState() {
base.initState();
this._lastReportedPage = this.widget.controller.initialPage;
}
AxisDirection _getDirection(BuildContext context) {
switch (this.widget.scrollDirection) {
case Axis.horizontal:
D.assert(WidgetsD.debugCheckHasDirectionality(context));
TextDirection textDirection = Directionality.of(context);
AxisDirection axisDirection = AxisUtils.textDirectionToAxisDirection(textDirection);
return this.widget.reverse ? AxisUtils.flipAxisDirection(axisDirection) : axisDirection;
case Axis.vertical:
return this.widget.reverse ? AxisDirection.up : AxisDirection.down;
}
throw new UIWidgetsError("fail to get axis direction");
}
public override Widget build(BuildContext context) {
AxisDirection axisDirection = this._getDirection(context);
ScrollPhysics physics = this.widget.pageSnapping
? PageViewUtils._kPagePhysics.applyTo(this.widget.physics)
: this.widget.physics;
return new NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification notification) => {
if (notification.depth == 0 && this.widget.onPageChanged != null &&
notification is ScrollUpdateNotification) {
IPageMetrics metrics = (IPageMetrics) notification.metrics;
int currentPage = metrics.page.round();
if (currentPage != this._lastReportedPage) {
this._lastReportedPage = currentPage;
this.widget.onPageChanged(currentPage);
}
}
return false;
},
child: new Scrollable(
axisDirection: axisDirection,
controller: this.widget.controller,
physics: physics,
viewportBuilder: (BuildContext _context, ViewportOffset position) => {
return new Viewport(
cacheExtent: 0.0,
axisDirection: axisDirection,
offset: position,
slivers: new List<Widget> {
new SliverFillViewport(
viewportFraction: this.widget.controller.viewportFraction,
del: this.widget.childrenDelegate
)
}
);
}
)
);
}
public override void debugFillProperties(DiagnosticPropertiesBuilder description) {
base.debugFillProperties(description);
description.add(new EnumProperty<Axis>("scrollDirection", this.widget.scrollDirection));
description.add(new FlagProperty("reverse", value: this.widget.reverse, ifTrue: "reversed"));
description.add(
new DiagnosticsProperty<PageController>("controller", this.widget.controller, showName: false));
description.add(new DiagnosticsProperty<ScrollPhysics>("physics", this.widget.physics, showName: false));
description.add(new FlagProperty("pageSnapping", value: this.widget.pageSnapping,
ifFalse: "snapping disabled"));
}
}
}

11
Runtime/widgets/page_view.cs.meta


fileFormatVersion: 2
guid: 00d46a618968045298e84302af711284
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

29
Samples/UIWidgetSample/PageViewCanvas.cs


using System.Collections.Generic;
using Unity.UIWidgets.engine;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
namespace UIWidgetsSample {
public class PageViewCanvas : WidgetCanvas {
protected override Widget getWidget() {
return new Container(
width: 200,
height: 400,
child: new PageView(
children: new List<Widget>(){
new Container(
color: new Color(0xFFE91E63)
),
new Container(
color: new Color(0xFF00BCD4)
),
new Container(
color: new Color(0xFF673AB7)
)
}
));
}
}
}

11
Samples/UIWidgetSample/PageViewCanvas.cs.meta


fileFormatVersion: 2
guid: a8dea5be0500345ccb20b797d19e741c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存