浏览代码

Merge branch 'master' of gitlab.cds.internal.unity3d.com:upm-packages/ui-widgets/com.unity.uiwidgets into material

/main
xingwei.zhu 6 年前
当前提交
3d1425b4
共有 16 个文件被更改,包括 715 次插入86 次删除
  1. 27
      Runtime/editor/editor_window.cs
  2. 9
      Runtime/material/app.cs
  3. 7
      Runtime/promise/Promise_NonGeneric.cs
  4. 2
      Runtime/rendering/proxy_box.cs
  5. 30
      Runtime/rendering/wrap.cs
  6. 27
      Runtime/scheduler/binding.cs
  7. 12
      Runtime/ui/window.cs
  8. 117
      Runtime/widgets/automatic_keep_alive.cs
  9. 10
      Runtime/widgets/framework.cs
  10. 2
      Runtime/widgets/pages.cs
  11. 2
      Runtime/widgets/ticker_provider.cs
  12. 2
      Runtime/widgets/transitions.cs
  13. 13
      Tests/Editor/CanvasAndLayers.cs
  14. 3
      Runtime/rendering/wrap.cs.meta
  15. 535
      Runtime/widgets/dismissible.cs
  16. 3
      Runtime/widgets/dismissible.cs.meta

27
Runtime/editor/editor_window.cs


using Unity.UIWidgets.async;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.scheduler;
using Unity.UIWidgets.service;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;

}
}
WidgetsBinding _binding;
internal WidgetsBinding _binding;
float _lastWindowWidth;
float _lastWindowHeight;

}
public override IDisposable getScope() {
instance = this;
WindowAdapter oldInstance = (WindowAdapter) Window._instance;
Window._instance = this;
}
WidgetsBinding.instance = this._binding;
return new WindowDisposable(this);
}
SchedulerBinding._instance = this._binding;
return new WindowDisposable(this, oldInstance);
readonly WindowAdapter _oldWindow;
public WindowDisposable(WindowAdapter window) {
public WindowDisposable(WindowAdapter window, WindowAdapter oldWindow) {
this._oldWindow = oldWindow;
D.assert(instance == this._window);
instance = null;
D.assert(Window._instance == this._window);
Window._instance = this._oldWindow;
D.assert(WidgetsBinding.instance == this._window._binding);
WidgetsBinding.instance = null;
D.assert(SchedulerBinding._instance == this._window._binding);
SchedulerBinding._instance = this._oldWindow?._binding;
}
}

9
Runtime/material/app.cs


string title = "",
Color color = null,
ThemeData theme = null,
bool showPerformanceOverlay = false,
Window window = null) : base(key: key) {
D.assert(window != null);
this.window = window;
bool showPerformanceOverlay = false
) : base(key: key) {
this.navigatorKey = navigatorKey;
this.home = home;
this.routes = routes ?? new Dictionary<string, WidgetBuilder>();

public readonly Color color;
public readonly bool showPerformanceOverlay;
public readonly Window window;
public override State createState() {
return new _MaterialAppState();

7
Runtime/promise/Promise_NonGeneric.cs


promise.Reject(ex);
return promise;
}
public static IPromise Delayed(TimeSpan duration) {
var promise = new Promise();
Window.instance.run(duration, () => { promise.Resolve(); });
return promise;
}
public IPromise Finally(Action onComplete) {
var promise = new Promise(isSync: true);

2
Runtime/rendering/proxy_box.cs


public abstract T getClip(Size size);
public Rect getApproximateClipRect(Size size) {
public virtual Rect getApproximateClipRect(Size size) {
return Offset.zero & size;
}

30
Runtime/rendering/wrap.cs


TextDirection? textDirection = null,
VerticalDirection verticalDirection = VerticalDirection.down
) {
D.assert(direction != null);
D.assert(alignment != null);
D.assert(spacing != null);
D.assert(runAlignment != null);
D.assert(runSpacing != null);
D.assert(crossAxisAlignment != null);
this._direction = direction;
this._alignment = alignment;
this._spacing = spacing;

public Axis direction {
get { return this._direction; }
set {
D.assert(value != null);
if (this._direction == value) {
return;
}

public WrapAlignment alignment {
get { return this._alignment; }
set {
D.assert(value != null);
if (this._alignment == value) {
return;
}

public float spacing {
get { return this._spacing; }
set {
D.assert(value != null);
if (this._spacing == value) {
return;
}

public WrapAlignment runAlignment {
get { return this._runAlignment; }
set {
D.assert(value != null);
if (this._runAlignment == value) {
return;
}

public float runSpacing {
get { return this._runSpacing; }
set {
D.assert(value != null);
if (this._runSpacing == value) {
return;
}

public WrapCrossAlignment crossAxisAlignment {
get { return this._crossAxisAlignment; }
set {
D.assert(value != null);
if (this._crossAxisAlignment == value) {
return;
}

public bool _debugHasNecessaryDirections {
get {
D.assert(this.direction != null);
D.assert(this.alignment != null);
D.assert(this.runAlignment != null);
D.assert(this.crossAxisAlignment != null);
if (this.firstChild != null && this.lastChild != this.firstChild) {
// i.e. there"s more than one child
switch (this.direction) {

break;
case Axis.vertical:
D.assert(this.verticalDirection != null,
"Vertical $runtimeType with multiple children has a null verticalDirection, so the layout order is undefined.");
break;
}
}

"Horizontal $runtimeType with alignment $alignment has a null textDirection, so the alignment cannot be resolved.");
break;
case Axis.vertical:
D.assert(this.verticalDirection != null,
"Vertical $runtimeType with alignment $alignment has a null verticalDirection, so the alignment cannot be resolved.");
break;
}
}

case Axis.horizontal:
D.assert(this.verticalDirection != null,
"Horizontal $runtimeType with runAlignment $runAlignment has a null verticalDirection, so the alignment cannot be resolved.");
break;
case Axis.vertical:
D.assert(this.textDirection != null,

this.crossAxisAlignment == WrapCrossAlignment.end) {
switch (this.direction) {
case Axis.horizontal:
D.assert(this.verticalDirection != null,
"Horizontal $runtimeType with crossAxisAlignment $crossAxisAlignment has a null verticalDirection, so the alignment cannot be resolved.");
break;
case Axis.vertical:
D.assert(this.textDirection != null,

}
D.assert(childConstraints != null);
D.assert(mainAxisLimit != null);
float spacing = this.spacing;
float runSpacing = this.runSpacing;
List<_RunMetrics> runMetrics = new List<_RunMetrics> { };

crossAxisExtent += runSpacing;
}
runMetrics.Append(new _RunMetrics(runMainAxisExtent, runCrossAxisExtent, childCount));
runMetrics.Add(new _RunMetrics(runMainAxisExtent, runCrossAxisExtent, childCount));
runMainAxisExtent = 0.0f;
runCrossAxisExtent = 0.0f;
childCount = 0;

crossAxisExtent += runSpacing;
}
runMetrics.Append(new _RunMetrics(runMainAxisExtent, runCrossAxisExtent, childCount));
runMetrics.Add(new _RunMetrics(runMainAxisExtent, runCrossAxisExtent, childCount));
}
int runCount = runMetrics.Count;

27
Runtime/scheduler/binding.cs


return true;
});
this.debugStack = debugCurrentCallbackStack;
}
else {
} else {
this.debugStack = new StackTrace(2, true);
}

public class SchedulerBinding {
public static SchedulerBinding instance {
get {
D.assert(_instance != null, "Binding.instance is null");
D.assert(_instance != null,
"Binding.instance is null. " +
"This usually happens when there is a callback from outside of UIWidgets. " +
"Try to use \"using (WindowProvider.of(BuildContext).getScope()) { ... }\" to wrap your code.");
return _instance;
}

_instance = null;
}
else {
} else {
D.assert(_instance == null, "Binding.instance is already assigned.");
_instance = value;
}

static SchedulerBinding _instance;
internal static SchedulerBinding _instance;
public SchedulerBinding() {
Window.instance.onBeginFrame += this._handleBeginFrame;

if (rawTimeStamp != null) {
_debugDescribeTimeStamp(
this._currentFrameTimeStamp.Value, frameTimeStampDescription);
}
else {
} else {
frameTimeStampDescription.Append("(warm-up frame)");
}

}
this._removedIds.Clear();
}
finally {
} finally {
this._schedulerPhase = SchedulerPhase.midFrameMicrotasks;
}
}

foreach (FrameCallback callback in localPostFrameCallbacks) {
this._invokeFrameCallback(callback, this._currentFrameTimeStamp.Value);
}
}
finally {
} finally {
this._schedulerPhase = SchedulerPhase.idle;
D.assert(() => {
if (D.debugPrintEndFrameBanner) {

try {
callback(timeStamp);
}
catch (Exception ex) {
} catch (Exception ex) {
UIWidgetsError.reportError(new UIWidgetsErrorDetails(
exception: ex,
library: "scheduler library",

});
}
}
}
}

12
Runtime/ui/window.cs


public abstract class Window {
public static Window instance {
get {
D.assert(_instance != null, "Window.instance is null");
D.assert(_instance != null,
"Window.instance is null. " +
"This usually happens when there is a callback from outside of UIWidgets. " +
"Try to use \"using (WindowProvider.of(BuildContext).getScope()) { ... }\" to wrap your code.");
return _instance;
}

_instance = null;
}
else {
} else {
D.assert(_instance == null, "Window.instance is already assigned.");
_instance = value;
}

get { return _instance != null; }
}
static Window _instance;
internal static Window _instance;
public float devicePixelRatio {
get { return this._devicePixelRatio; }

public abstract IDisposable getScope();
}
}
}

117
Runtime/widgets/automatic_keep_alive.cs


}
}
// There is a copy of the implementation of this mixin
// in AutomaticKeepAliveClientWithTickerProviderStateMixin, remember to keep the copy up to date
KeepAliveHandle _keepAliveHandle;
void _ensureKeepAlive() {
D.assert(this._keepAliveHandle == null);
this._keepAliveHandle = new KeepAliveHandle();
new KeepAliveNotification(this._keepAliveHandle).dispatch(this.context);
}
void _releaseKeepAlive() {
this._keepAliveHandle.release();
this._keepAliveHandle = null;
}
protected abstract bool wantKeepAlive { get; }
protected void updateKeepAlive() {
if (this.wantKeepAlive) {
if (this._keepAliveHandle == null) {
this._ensureKeepAlive();
}
}
else {
if (this._keepAliveHandle != null) {
this._releaseKeepAlive();
}
}
}
public override void initState() {
base.initState();
if (this.wantKeepAlive) {
this._ensureKeepAlive();
}
}
public override void deactivate() {
if (this._keepAliveHandle != null) {
this._releaseKeepAlive();
}
base.deactivate();
}
public override Widget build(BuildContext context) {
if (this.wantKeepAlive && this._keepAliveHandle == null) {
this._ensureKeepAlive();
}
return null;
}
}
public abstract class AutomaticKeepAliveClientWithTickerProviderStateMixin<T> : State<T>, TickerProvider
where T : StatefulWidget {
HashSet<Ticker> _tickers;
public Ticker createTicker(TickerCallback onTick) {
this._tickers = this._tickers ?? new HashSet<Ticker>();
var result = new _AutomaticWidgetTicker<T>(onTick, this, debugLabel: "created by " + this);
this._tickers.Add(result);
return result;
}
internal void _removeTicker(_AutomaticWidgetTicker<T> ticker) {
D.assert(this._tickers != null);
D.assert(this._tickers.Contains(ticker));
this._tickers.Remove(ticker);
}
public override void dispose() {
D.assert(() => {
if (this._tickers != null) {
foreach (Ticker ticker in this._tickers) {
if (ticker.isActive) {
throw new UIWidgetsError(
this + " was disposed with an active Ticker.\n" +
this.GetType() +
" created a Ticker via its TickerProviderStateMixin, but at the time " +
"dispose() was called on the mixin, that Ticker was still active. All Tickers must " +
"be disposed before calling super.dispose(). Tickers used by AnimationControllers " +
"should be disposed by calling dispose() on the AnimationController itself. " +
"Otherwise, the ticker will leak.\n" +
"The offending ticker was: " + ticker.toString(debugIncludeStack: true)
);
}
}
}
return true;
});
base.dispose();
}
public override void didChangeDependencies() {
bool muted = !TickerMode.of(this.context);
if (this._tickers != null) {
foreach (Ticker ticker in this._tickers) {
ticker.muted = muted;
}
}
base.didChangeDependencies();
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<HashSet<Ticker>>(
"tickers",
this._tickers,
description: this._tickers != null ? "tracking " + this._tickers.Count + " tickers" : null,
defaultValue: Diagnostics.kNullDefaultValue
));
}
KeepAliveHandle _keepAliveHandle;
void _ensureKeepAlive() {

10
Runtime/widgets/framework.cs


return true;
});
if (Window.hasInstance) {
this._setState(fn);
} else {
using (WindowProvider.of(this.context).getScope()) {
this._setState(fn);
}
}
}
void _setState(VoidCallback fn = null) {
if (fn != null) {
fn();
}

2
Runtime/widgets/pages.cs


}
public override bool opaque {
get { return false; }
get { return true; }
}
public override bool barrierDismissible {

2
Runtime/widgets/ticker_provider.cs


}
}
// There is a copy of the implementation of this mixin at widgets/automatic_keep_alive.cs,
// in AutomaticKeepAliveClientWithTickerProviderStateMixin, remember to keep the copy up to date
public abstract class TickerProviderStateMixin<T> : State<T>, TickerProvider where T : StatefulWidget {
HashSet<Ticker> _tickers;

2
Runtime/widgets/transitions.cs


Animation<float> sizeFactor = null,
float axisAlignment = 0.0f,
Widget child = null) : base(key: key, listenable: sizeFactor) {
D.assert(axis != null);
D.assert(axisAlignment != null);
this.axis = axis;
this.axisAlignment = axisAlignment;
this.child = child;

13
Tests/Editor/CanvasAndLayers.cs


using System;
using System.Collections.Generic;
using System.Linq;
using RSG;
using Unity.UIWidgets.editor;
using Unity.UIWidgets.material;
using Unity.UIWidgets.painting;

Window.instance = this._windowAdapter;
if (Event.current.type == EventType.MouseDown) {
Promise.Delayed(new TimeSpan(0, 0, 5)).Then(() => { Debug.Log("Promise.Delayed: 5s"); });
}
this._options[this._selected]();
Window.instance = null;

}, null, TileMode.clamp)
};
// canvas.drawRect(
// Unity.UIWidgets.ui.Rect.fromLTRB(10, 10, 110, 110),
// paint);
canvas.rotate(Mathf.PI * 15 / 180);
var path = new Path();
path.moveTo(10, 150);
path.lineTo(10, 160);

}
canvas.drawPath(path, paint);
canvas.rotate(Mathf.PI * 15 / 180);
canvas.translate(100, 100);

3
Runtime/rendering/wrap.cs.meta


fileFormatVersion: 2
guid: bf63171d5e9d4f9fb93cf8cf7a0534bb
timeCreated: 1552011675

535
Runtime/widgets/dismissible.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.scheduler;
using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.widgets {
public delegate void DismissDirectionCallback(DismissDirection? direction);
public enum DismissDirection {
vertical,
horizontal,
endToStart,
startToEnd,
up,
down
}
public class Dismissible : StatefulWidget {
public Dismissible(
Key key = null,
Widget child = null,
Widget background = null,
Widget secondaryBackground = null,
VoidCallback onResize = null,
DismissDirectionCallback onDismissed = null,
DismissDirection direction = DismissDirection.horizontal,
TimeSpan? resizeDuration = null,
Dictionary<DismissDirection?, float?> dismissThresholds = null,
TimeSpan? movementDuration = null,
float crossAxisEndOffset = 0.0f
) : base(key: key) {
D.assert(key != null);
D.assert(secondaryBackground != null ? background != null : true);
this.resizeDuration = resizeDuration ?? new TimeSpan(0, 0, 0, 0, 300);
this.dismissThresholds = dismissThresholds ?? new Dictionary<DismissDirection?, float?>();
this.movementDuration = movementDuration ?? new TimeSpan(0, 0, 0, 0, 200);
}
public readonly Widget child;
public readonly Widget background;
public readonly Widget secondaryBackground;
public readonly VoidCallback onResize;
public readonly DismissDirectionCallback onDismissed;
public readonly DismissDirection direction;
public readonly TimeSpan resizeDuration;
public readonly Dictionary<DismissDirection?, float?> dismissThresholds;
public readonly TimeSpan movementDuration;
public readonly float crossAxisEndOffset;
public override State createState() {
return new _DismissibleState();
}
}
class _AutomaticWidgetTicker<T> : Ticker where T : StatefulWidget {
internal _AutomaticWidgetTicker(
TickerCallback onTick,
AutomaticKeepAliveClientWithTickerProviderStateMixin<T> creator,
string debugLabel = null) :
base(onTick: onTick, debugLabel: debugLabel) {
this._creator = creator;
}
readonly AutomaticKeepAliveClientWithTickerProviderStateMixin<T> _creator;
public override void dispose() {
this._creator._removeTicker(this);
base.dispose();
}
}
class _DismissibleClipper : CustomClipper<Rect> {
public _DismissibleClipper(
Axis axis,
Animation<Offset> moveAnimation
) : base(reclip: moveAnimation) {
D.assert(moveAnimation != null);
this.axis = axis;
this.moveAnimation = moveAnimation;
}
public readonly Axis axis;
public readonly Animation<Offset> moveAnimation;
public override Rect getClip(Size size) {
switch (this.axis) {
case Axis.horizontal:
float offset1 = this.moveAnimation.value.dx * size.width;
if (offset1 < 0) {
return Rect.fromLTRB(size.width + offset1, 0.0f, size.width, size.height);
}
return Rect.fromLTRB(0.0f, 0.0f, offset1, size.height);
case Axis.vertical:
float offset = this.moveAnimation.value.dy * size.height;
if (offset < 0) {
return Rect.fromLTRB(0.0f, size.height + offset, size.width, size.height);
}
return Rect.fromLTRB(0.0f, 0.0f, size.width, offset);
}
return null;
}
public override Rect getApproximateClipRect(Size size) {
return this.getClip(size);
}
public override bool shouldReclip(CustomClipper<Rect> oldClipper) {
D.assert(oldClipper is _DismissibleClipper);
_DismissibleClipper clipper = oldClipper as _DismissibleClipper;
return clipper.axis != this.axis
|| clipper.moveAnimation.value != this.moveAnimation.value;
}
}
enum _FlingGestureKind {
none,
forward,
reverse
}
public class _DismissibleState : AutomaticKeepAliveClientWithTickerProviderStateMixin<Dismissible> {
static readonly Curve _kResizeTimeCurve = new Interval(0.4f, 1.0f, curve: Curves.ease);
const float _kMinFlingVelocity = 700.0f;
const float _kMinFlingVelocityDelta = 400.0f;
const float _kFlingVelocityScale = 1.0f / 300.0f;
const float _kDismissThreshold = 0.4f;
public override void initState() {
base.initState();
this._moveController = new AnimationController(duration: this.widget.movementDuration, vsync: this);
this._moveController.addStatusListener(this._handleDismissStatusChanged);
this._updateMoveAnimation();
}
AnimationController _moveController;
Animation<Offset> _moveAnimation;
AnimationController _resizeController;
Animation<float> _resizeAnimation;
float _dragExtent = 0.0f;
bool _dragUnderway = false;
Size _sizePriorToCollapse;
protected override bool wantKeepAlive {
get { return this._moveController?.isAnimating == true || this._resizeController?.isAnimating == true; }
}
public override void dispose() {
this._moveController.dispose();
this._resizeController?.dispose();
base.dispose();
}
bool _directionIsXAxis {
get {
return this.widget.direction == DismissDirection.horizontal
|| this.widget.direction == DismissDirection.endToStart
|| this.widget.direction == DismissDirection.startToEnd;
}
}
DismissDirection? _extentToDirection(float? extent) {
if (extent == 0.0) {
return null;
}
if (this._directionIsXAxis) {
switch (Directionality.of(this.context)) {
case TextDirection.rtl:
return extent < 0 ? DismissDirection.startToEnd : DismissDirection.endToStart;
case TextDirection.ltr:
return extent > 0 ? DismissDirection.startToEnd : DismissDirection.endToStart;
}
D.assert(false);
return null;
}
return extent > 0 ? DismissDirection.down : DismissDirection.up;
}
DismissDirection? _dismissDirection {
get { return this._extentToDirection(this._dragExtent); }
}
bool _isActive {
get { return this._dragUnderway || this._moveController.isAnimating; }
}
float _overallDragAxisExtent {
get {
Size size = this.context.size;
return this._directionIsXAxis ? size.width : size.height;
}
}
void _handleDragStart(DragStartDetails details) {
this._dragUnderway = true;
if (this._moveController.isAnimating) {
this._dragExtent = this._moveController.value * this._overallDragAxisExtent * this._dragExtent.sign();
this._moveController.stop();
}
else {
this._dragExtent = 0.0f;
this._moveController.setValue(0.0f);
}
this.setState(() => { this._updateMoveAnimation(); });
}
void _handleDragUpdate(DragUpdateDetails details) {
if (!this._isActive || this._moveController.isAnimating) {
return;
}
float delta = details.primaryDelta ?? 0.0f;
float oldDragExtent = this._dragExtent;
switch (this.widget.direction) {
case DismissDirection.horizontal:
case DismissDirection.vertical:
this._dragExtent += delta;
break;
case DismissDirection.up:
if (this._dragExtent + delta < 0) {
this._dragExtent += delta;
}
break;
case DismissDirection.down:
if (this._dragExtent + delta > 0) {
this._dragExtent += delta;
}
break;
case DismissDirection.endToStart:
switch (Directionality.of(this.context)) {
case TextDirection.rtl:
if (this._dragExtent + delta > 0) {
this._dragExtent += delta;
}
break;
case TextDirection.ltr:
if (this._dragExtent + delta < 0) {
this._dragExtent += delta;
}
break;
}
break;
case DismissDirection.startToEnd:
switch (Directionality.of(this.context)) {
case TextDirection.rtl:
if (this._dragExtent + delta < 0) {
this._dragExtent += delta;
}
break;
case TextDirection.ltr:
if (this._dragExtent + delta > 0) {
this._dragExtent += delta;
}
break;
}
break;
}
if (oldDragExtent.sign() != this._dragExtent.sign()) {
this.setState(() => { this._updateMoveAnimation(); });
}
if (!this._moveController.isAnimating) {
this._moveController.setValue(this._dragExtent.abs() / this._overallDragAxisExtent);
}
}
void _updateMoveAnimation() {
float end = this._dragExtent.sign();
this._moveAnimation = this._moveController.drive(
new OffsetTween(
begin: Offset.zero,
end: this._directionIsXAxis
? new Offset(end, this.widget.crossAxisEndOffset)
: new Offset(this.widget.crossAxisEndOffset, end)
)
);
}
_FlingGestureKind _describeFlingGesture(Velocity velocity) {
if (this._dragExtent == 0.0f) {
return _FlingGestureKind.none;
}
float vx = velocity.pixelsPerSecond.dx;
float vy = velocity.pixelsPerSecond.dy;
DismissDirection? flingDirection;
if (this._directionIsXAxis) {
if (vx.abs() - vy.abs() < _kMinFlingVelocityDelta || vx.abs() < _kMinFlingVelocity) {
return _FlingGestureKind.none;
}
D.assert(vx != 0.0f);
flingDirection = this._extentToDirection(vx);
}
else {
if (vy.abs() - vx.abs() < _kMinFlingVelocityDelta || vy.abs() < _kMinFlingVelocity) {
return _FlingGestureKind.none;
}
D.assert(vy != 0.0);
flingDirection = this._extentToDirection(vy);
}
D.assert(this._dismissDirection != null);
if (flingDirection == this._dismissDirection) {
return _FlingGestureKind.forward;
}
return _FlingGestureKind.reverse;
}
void _handleDragEnd(DragEndDetails details) {
if (!this._isActive || this._moveController.isAnimating) {
return;
}
this._dragUnderway = false;
if (this._moveController.isCompleted) {
this._startResizeAnimation();
return;
}
float flingVelocity = this._directionIsXAxis
? details.velocity.pixelsPerSecond.dx
: details.velocity.pixelsPerSecond.dy;
switch (this._describeFlingGesture(details.velocity)) {
case _FlingGestureKind.forward:
D.assert(this._dragExtent != 0.0f);
D.assert(!this._moveController.isDismissed);
if ((this.widget.dismissThresholds[this._dismissDirection] ?? _kDismissThreshold) >= 1.0) {
this._moveController.reverse();
break;
}
this._dragExtent = flingVelocity.sign();
this._moveController.fling(velocity: flingVelocity.abs() * _kFlingVelocityScale);
break;
case _FlingGestureKind.reverse:
D.assert(this._dragExtent != 0.0);
D.assert(!this._moveController.isDismissed);
this._dragExtent = flingVelocity.sign();
this._moveController.fling(velocity: -flingVelocity.abs() * _kFlingVelocityScale);
break;
case _FlingGestureKind.none:
if (!this._moveController.isDismissed) {
// we already know it's not completed, we check that above
if (this._moveController.value >
(this.widget.dismissThresholds[this._dismissDirection] ?? _kDismissThreshold)) {
this._moveController.forward();
}
else {
this._moveController.reverse();
}
}
break;
}
}
void _handleDismissStatusChanged(AnimationStatus status) {
if (status == AnimationStatus.completed && !this._dragUnderway) {
this._startResizeAnimation();
}
this.updateKeepAlive();
}
void _startResizeAnimation() {
D.assert(this._moveController != null);
D.assert(this._moveController.isCompleted);
D.assert(this._resizeController == null);
D.assert(this._sizePriorToCollapse == null);
if (this.widget.resizeDuration == null) {
if (this.widget.onDismissed != null) {
DismissDirection? direction = this._dismissDirection;
D.assert(direction != null);
this.widget.onDismissed(direction);
}
}
else {
this._resizeController = new AnimationController(duration: this.widget.resizeDuration, vsync: this);
this._resizeController.addListener(this._handleResizeProgressChanged);
this._resizeController.addStatusListener((AnimationStatus status) => this.updateKeepAlive());
this._resizeController.forward();
this.setState(() => {
this._sizePriorToCollapse = this.context.size;
this._resizeAnimation = this._resizeController.drive(
new CurveTween(
curve: _kResizeTimeCurve
)
).drive(
new FloatTween(
begin: 1.0f,
end: 0.0f
)
);
});
}
}
void _handleResizeProgressChanged() {
if (this._resizeController.isCompleted) {
if (this.widget.onDismissed != null) {
DismissDirection? direction = this._dismissDirection;
D.assert(direction != null);
this.widget.onDismissed(direction);
}
}
else {
if (this.widget.onResize != null) {
this.widget.onResize();
}
}
}
public override Widget build(BuildContext context) {
base.build(context); // See AutomaticKeepAliveClientMixin.
D.assert(!this._directionIsXAxis || WidgetsD.debugCheckHasDirectionality(context));
Widget background = this.widget.background;
if (this.widget.secondaryBackground != null) {
DismissDirection? direction = this._dismissDirection;
if (direction == DismissDirection.endToStart || direction == DismissDirection.up) {
background = this.widget.secondaryBackground;
}
}
if (this._resizeAnimation != null) {
// we've been dragged aside, and are now resizing.
D.assert(() => {
if (this._resizeAnimation.status != AnimationStatus.forward) {
D.assert(this._resizeAnimation.status == AnimationStatus.completed);
throw new UIWidgetsError(
"A dismissed Dismissible widget is still part of the tree.\n" +
"Make sure to implement the onDismissed handler and to immediately remove the Dismissible\n" +
"widget from the application once that handler has fired."
);
}
return true;
});
return new SizeTransition(
sizeFactor: this._resizeAnimation,
axis: this._directionIsXAxis ? Axis.vertical : Axis.horizontal,
child: new SizedBox(
width: this._sizePriorToCollapse.width,
height: this._sizePriorToCollapse.height,
child: background
)
);
}
Widget content = new SlideTransition(
position: this._moveAnimation,
child: this.widget.child
);
if (background != null) {
List<Widget> children = new List<Widget> { };
if (!this._moveAnimation.isDismissed) {
children.Add(Positioned.fill(
child: new ClipRect(
clipper: new _DismissibleClipper(
axis: this._directionIsXAxis ? Axis.horizontal : Axis.vertical,
moveAnimation: this._moveAnimation
),
child: background
)
));
}
children.Add(content);
content = new Stack(children: children);
}
return new GestureDetector(
onHorizontalDragStart: this._directionIsXAxis ? (GestureDragStartCallback) this._handleDragStart : null,
onHorizontalDragUpdate: this._directionIsXAxis
? (GestureDragUpdateCallback) this._handleDragUpdate
: null,
onHorizontalDragEnd: this._directionIsXAxis ? (GestureDragEndCallback) this._handleDragEnd : null,
onVerticalDragStart: this._directionIsXAxis ? null : (GestureDragStartCallback) this._handleDragStart,
onVerticalDragUpdate: this._directionIsXAxis
? null
: (GestureDragUpdateCallback) this._handleDragUpdate,
onVerticalDragEnd: this._directionIsXAxis ? null : (GestureDragEndCallback) this._handleDragEnd,
behavior: HitTestBehavior.opaque,
child: content
);
}
}
}

3
Runtime/widgets/dismissible.cs.meta


fileFormatVersion: 2
guid: abd926e0982c44ca80edbb282a52b90b
timeCreated: 1552033946
正在加载...
取消
保存