Yuncong Zhang
6 年前
当前提交
34c69532
共有 54 个文件被更改,包括 5328 次插入 和 185 次删除
-
27Runtime/foundation/debug.cs
-
1Runtime/material/app_bar.cs
-
1Runtime/material/flexible_space_bar.cs
-
1Runtime/material/ink_well.cs
-
6Runtime/material/material_localizations.cs
-
30Runtime/material/theme_data.cs
-
3Runtime/rendering/box.cs
-
26Runtime/rendering/layer.cs
-
13Runtime/rendering/object.cs
-
87Runtime/rendering/proxy_box.cs
-
65Runtime/rendering/stack.cs
-
8Runtime/ui/compositing.cs
-
205Runtime/ui/painting/canvas_impl.cs
-
52Runtime/ui/painting/canvas_shader.cs
-
33Runtime/ui/painting/painting.cs
-
12Runtime/ui/painting/path.cs
-
6Runtime/widgets/app.cs
-
54Runtime/widgets/basic.cs
-
49Runtime/widgets/implicit_animations.cs
-
2Runtime/widgets/localizations.cs
-
4Runtime/widgets/scroll_configuration.cs
-
125Runtime/widgets/transitions.cs
-
12Runtime/widgets/preferred_size.cs
-
84Samples/UIWidgetSample/MaterialSample.cs
-
2Samples/UIWidgetSample/Resources/VideoSampleRT.renderTexture
-
2Samples/UIWidgetSample/ToDoAppSample.cs
-
2Samples/UIWidgetsGallery/gallery/options.cs
-
56Tests/Editor/CanvasAndLayers.cs
-
24Tests/Editor/Widgets.cs
-
25Runtime/flow/backdrop_filter_layer.cs
-
11Runtime/flow/backdrop_filter_layer.cs.meta
-
772Runtime/material/dropdown.cs
-
3Runtime/material/dropdown.cs.meta
-
381Runtime/material/input_border.cs
-
3Runtime/material/input_border.cs.meta
-
1001Runtime/material/input_decorator.cs
-
3Runtime/material/input_decorator.cs.meta
-
551Runtime/material/progress_indicator.cs
-
3Runtime/material/progress_indicator.cs.meta
-
107Runtime/material/tab_bar_theme.cs
-
11Runtime/material/tab_bar_theme.cs.meta
-
187Runtime/material/tab_controller.cs
-
11Runtime/material/tab_controller.cs.meta
-
90Runtime/material/tab_indicator.cs
-
11Runtime/material/tab_indicator.cs.meta
-
1001Runtime/material/tabs.cs
-
11Runtime/material/tabs.cs.meta
-
242Runtime/widgets/form.cs
-
3Runtime/widgets/form.cs.meta
-
11Runtime/widgets/preferred_size.cs.meta
-
69Runtime/widgets/will_pop_scope.cs
-
3Runtime/widgets/will_pop_scope.cs.meta
-
11Runtime/widgets/perferred_size.cs.meta
-
0/Runtime/widgets/preferred_size.cs
|
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.ui; |
|||
|
|||
namespace Unity.UIWidgets.flow { |
|||
public class BackdropFilterLayer : ContainerLayer { |
|||
ImageFilter _filter; |
|||
|
|||
public ImageFilter filter { |
|||
set { this._filter = value; } |
|||
} |
|||
|
|||
public override void paint(PaintContext context) { |
|||
D.assert(this.needsPainting); |
|||
|
|||
var canvas = context.canvas; |
|||
canvas.saveLayer(this.paintBounds, new Paint {backdrop = this._filter}); |
|||
|
|||
try { |
|||
this.paintChildren(context); |
|||
} finally { |
|||
canvas.restore(); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 13a0ce179081f4b35b10fac26f568cc8 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using RSG; |
|||
using Unity.UIWidgets.animation; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.gestures; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.service; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using UnityEngine; |
|||
using Canvas = Unity.UIWidgets.ui.Canvas; |
|||
using Color = Unity.UIWidgets.ui.Color; |
|||
using Rect = Unity.UIWidgets.ui.Rect; |
|||
using TextStyle = Unity.UIWidgets.painting.TextStyle; |
|||
|
|||
namespace Unity.UIWidgets.material { |
|||
class DropdownConstants { |
|||
public static readonly TimeSpan _kDropdownMenuDuration = new TimeSpan(0, 0, 0, 0, 300); |
|||
public const float _kMenuItemHeight = 48.0f; |
|||
public const float _kDenseButtonHeight = 24.0f; |
|||
public static EdgeInsets _kMenuItemPadding = EdgeInsets.symmetric(horizontal: 16.0f); |
|||
public static EdgeInsets _kAlignedButtonPadding = EdgeInsets.only(left: 16.0f, right: 4.0f); |
|||
public static EdgeInsets _kUnalignedButtonPadding = EdgeInsets.zero; |
|||
public static EdgeInsets _kAlignedMenuMargin = EdgeInsets.zero; |
|||
public static EdgeInsets _kUnalignedMenuMargin = EdgeInsets.only(left: 16.0f, right: 24.0f); |
|||
} |
|||
|
|||
class _DropdownMenuPainter : AbstractCustomPainter { |
|||
public _DropdownMenuPainter( |
|||
Color color = null, |
|||
int? elevation = null, |
|||
int? selectedIndex = null, |
|||
Animation<float> resize = null |
|||
) : base(repaint: resize) { |
|||
D.assert(elevation != null); |
|||
this._painter = new BoxDecoration( |
|||
color: color, |
|||
borderRadius: BorderRadius.circular(2.0f), |
|||
boxShadow: ShadowConstants.kElevationToShadow[elevation ?? 0] |
|||
).createBoxPainter(); |
|||
this.color = color; |
|||
this.elevation = elevation; |
|||
this.selectedIndex = selectedIndex; |
|||
this.resize = resize; |
|||
} |
|||
|
|||
public readonly Color color; |
|||
public readonly int? elevation; |
|||
public readonly int? selectedIndex; |
|||
public readonly Animation<float> resize; |
|||
|
|||
public readonly BoxPainter _painter; |
|||
|
|||
public override void paint(Canvas canvas, Size size) { |
|||
float selectedItemOffset = this.selectedIndex ?? 0 * DropdownConstants._kMenuItemHeight + |
|||
Constants.kMaterialListPadding.top; |
|||
FloatTween top = new FloatTween( |
|||
begin: selectedItemOffset.clamp(0.0f, size.height - DropdownConstants._kMenuItemHeight), |
|||
end: 0.0f |
|||
); |
|||
|
|||
FloatTween bottom = new FloatTween( |
|||
begin: (top.begin + DropdownConstants._kMenuItemHeight).clamp(DropdownConstants._kMenuItemHeight, |
|||
size.height), |
|||
end: size.height |
|||
); |
|||
|
|||
Rect rect = Rect.fromLTRB(0.0f, top.evaluate(this.resize), size.width, bottom.evaluate(this.resize)); |
|||
|
|||
this._painter.paint(canvas, rect.topLeft, new ImageConfiguration(size: rect.size)); |
|||
} |
|||
|
|||
public override bool shouldRepaint(CustomPainter painter) { |
|||
_DropdownMenuPainter oldPainter = painter as _DropdownMenuPainter; |
|||
return oldPainter.color != this.color |
|||
|| oldPainter.elevation != this.elevation |
|||
|| oldPainter.selectedIndex != this.selectedIndex |
|||
|| oldPainter.resize != this.resize; |
|||
} |
|||
} |
|||
|
|||
class _DropdownScrollBehavior : ScrollBehavior { |
|||
public _DropdownScrollBehavior() { |
|||
} |
|||
|
|||
public override Widget buildViewportChrome(BuildContext context, Widget child, AxisDirection axisDirection) { |
|||
return child; |
|||
} |
|||
|
|||
public override ScrollPhysics getScrollPhysics(BuildContext context) { |
|||
return new ClampingScrollPhysics(); |
|||
} |
|||
} |
|||
|
|||
class _DropdownMenu<T> : StatefulWidget where T : class { |
|||
public _DropdownMenu( |
|||
Key key = null, |
|||
EdgeInsets padding = null, |
|||
_DropdownRoute<T> route = null |
|||
) : base(key: key) { |
|||
this.route = route; |
|||
this.padding = padding; |
|||
} |
|||
|
|||
public readonly _DropdownRoute<T> route; |
|||
public readonly EdgeInsets padding; |
|||
|
|||
public override State createState() { |
|||
return new _DropdownMenuState<T>(); |
|||
} |
|||
} |
|||
|
|||
class _DropdownMenuState<T> : State<_DropdownMenu<T>> where T : class { |
|||
CurvedAnimation _fadeOpacity; |
|||
CurvedAnimation _resize; |
|||
|
|||
public _DropdownMenuState() { |
|||
} |
|||
|
|||
public override void initState() { |
|||
base.initState(); |
|||
// We need to hold these animations as state because of their curve
|
|||
// direction. When the route's animation reverses, if we were to recreate
|
|||
// the CurvedAnimation objects in build, we'd lose
|
|||
// CurvedAnimation._curveDirection.
|
|||
this._fadeOpacity = new CurvedAnimation( |
|||
parent: this.widget.route.animation, |
|||
curve: new Interval(0.0f, 0.25f), |
|||
reverseCurve: new Interval(0.75f, 1.0f) |
|||
); |
|||
this._resize = new CurvedAnimation( |
|||
parent: this.widget.route.animation, |
|||
curve: new Interval(0.25f, 0.5f), |
|||
reverseCurve: new Threshold(0.0f) |
|||
); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
D.assert(MaterialD.debugCheckHasMaterialLocalizations(context)); |
|||
MaterialLocalizations localizations = MaterialLocalizations.of(context); |
|||
_DropdownRoute<T> route = this.widget.route; |
|||
float unit = 0.5f / (route.items.Count + 1.5f); |
|||
List<Widget> children = new List<Widget>(); |
|||
for (int itemIndex = 0; itemIndex < route.items.Count; ++itemIndex) { |
|||
CurvedAnimation opacity; |
|||
if (itemIndex == route.selectedIndex) { |
|||
opacity = new CurvedAnimation(parent: route.animation, curve: new Threshold(0.0f)); |
|||
} |
|||
else { |
|||
float start = (0.5f + (itemIndex + 1) * unit).clamp(0.0f, 1.0f); |
|||
float end = (start + 1.5f * unit).clamp(0.0f, 1.0f); |
|||
opacity = new CurvedAnimation(parent: route.animation, curve: new Interval(start, end)); |
|||
} |
|||
|
|||
var index = itemIndex; |
|||
children.Add(new FadeTransition( |
|||
opacity: opacity, |
|||
child: new InkWell( |
|||
child: new Container( |
|||
padding: this.widget.padding, |
|||
child: route.items[itemIndex] |
|||
), |
|||
onTap: () => Navigator.pop( |
|||
context, |
|||
new _DropdownRouteResult<T>(route.items[index].value) |
|||
) |
|||
) |
|||
)); |
|||
} |
|||
|
|||
return new FadeTransition( |
|||
opacity: this._fadeOpacity, |
|||
child: new CustomPaint( |
|||
painter: new _DropdownMenuPainter( |
|||
color: Theme.of(context).canvasColor, |
|||
elevation: route.elevation, |
|||
selectedIndex: route.selectedIndex, |
|||
resize: this._resize |
|||
), |
|||
child: new Material( |
|||
type: MaterialType.transparency, |
|||
textStyle: route.style, |
|||
child: new ScrollConfiguration( |
|||
behavior: new _DropdownScrollBehavior(), |
|||
child: new Scrollbar( |
|||
child: new ListView( |
|||
controller: this.widget.route.scrollController, |
|||
padding: Constants.kMaterialListPadding, |
|||
itemExtent: DropdownConstants._kMenuItemHeight, |
|||
shrinkWrap: true, |
|||
children: children |
|||
) |
|||
) |
|||
) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
class _DropdownMenuRouteLayout<T> : SingleChildLayoutDelegate { |
|||
public _DropdownMenuRouteLayout( |
|||
Rect buttonRect, |
|||
float menuTop, |
|||
float menuHeight, |
|||
TextDirection textDirection |
|||
) { |
|||
this.buttonRect = buttonRect; |
|||
this.menuTop = menuTop; |
|||
this.menuHeight = menuHeight; |
|||
this.textDirection = textDirection; |
|||
} |
|||
|
|||
public readonly Rect buttonRect; |
|||
public readonly float menuTop; |
|||
public readonly float menuHeight; |
|||
public readonly TextDirection textDirection; |
|||
|
|||
public override BoxConstraints getConstraintsForChild(BoxConstraints constraints) { |
|||
float maxHeight = Mathf.Max(0.0f, constraints.maxHeight - 2 * DropdownConstants._kMenuItemHeight); |
|||
float width = Mathf.Min(constraints.maxWidth, this.buttonRect.width); |
|||
return new BoxConstraints( |
|||
minWidth: width, |
|||
maxWidth: width, |
|||
minHeight: 0.0f, |
|||
maxHeight: maxHeight |
|||
); |
|||
} |
|||
|
|||
public override Offset getPositionForChild(Size size, Size childSize) { |
|||
D.assert(() => { |
|||
Rect container = Offset.zero & size; |
|||
if (container.intersect(this.buttonRect) == this.buttonRect) { |
|||
// If the button was entirely on-screen, then verify
|
|||
// that the menu is also on-screen.
|
|||
// If the button was a bit off-screen, then, oh well.
|
|||
D.assert(this.menuTop >= 0.0f); |
|||
D.assert(this.menuTop + this.menuHeight <= size.height); |
|||
} |
|||
|
|||
return true; |
|||
}); |
|||
float left; |
|||
switch (this.textDirection) { |
|||
case TextDirection.rtl: |
|||
left = this.buttonRect.right.clamp(0.0f, size.width) - childSize.width; |
|||
break; |
|||
case TextDirection.ltr: |
|||
left = this.buttonRect.left.clamp(0.0f, size.width - childSize.width); |
|||
break; |
|||
default: |
|||
throw new Exception("Unknown text direction: " + this.textDirection); |
|||
} |
|||
|
|||
return new Offset(left, this.menuTop); |
|||
} |
|||
|
|||
public override bool shouldRelayout(SingleChildLayoutDelegate _oldDelegate) { |
|||
_DropdownMenuRouteLayout<T> oldDelegate = _oldDelegate as _DropdownMenuRouteLayout<T>; |
|||
return this.buttonRect != oldDelegate.buttonRect |
|||
|| this.menuTop != oldDelegate.menuTop |
|||
|| this.menuHeight != oldDelegate.menuHeight |
|||
|| this.textDirection != oldDelegate.textDirection; |
|||
} |
|||
} |
|||
|
|||
class _DropdownRouteResult<T> where T: class { |
|||
public _DropdownRouteResult(T result) { |
|||
this.result = result; |
|||
} |
|||
|
|||
public readonly T result; |
|||
|
|||
public static bool operator ==(_DropdownRouteResult<T> left, _DropdownRouteResult<T> right) { |
|||
return left.result == right.result; |
|||
} |
|||
|
|||
public static bool operator !=(_DropdownRouteResult<T> left, _DropdownRouteResult<T> right) { |
|||
return left.result != right.result; |
|||
} |
|||
|
|||
public override int GetHashCode() { |
|||
return this.result.GetHashCode(); |
|||
} |
|||
} |
|||
|
|||
class _DropdownRoute<T> : PopupRoute where T : class { |
|||
public _DropdownRoute( |
|||
List<DropdownMenuItem<T>> items = null, |
|||
EdgeInsets padding = null, |
|||
Rect buttonRect = null, |
|||
int? selectedIndex = null, |
|||
int elevation = 8, |
|||
ThemeData theme = null, |
|||
TextStyle style = null, |
|||
string barrierLabel = null |
|||
) { |
|||
D.assert(style != null); |
|||
this.items = items; |
|||
this.padding = padding; |
|||
this.buttonRect = buttonRect; |
|||
this.selectedIndex = selectedIndex; |
|||
this.elevation = elevation; |
|||
this.theme = theme; |
|||
this.style = style; |
|||
this.barrierLabel = barrierLabel; |
|||
} |
|||
|
|||
public readonly List<DropdownMenuItem<T>> items; |
|||
public readonly EdgeInsets padding; |
|||
public readonly Rect buttonRect; |
|||
public readonly int? selectedIndex; |
|||
public readonly int elevation; |
|||
public readonly ThemeData theme; |
|||
public readonly TextStyle style; |
|||
|
|||
public ScrollController scrollController; |
|||
|
|||
public override TimeSpan transitionDuration { |
|||
get { return DropdownConstants._kDropdownMenuDuration; } |
|||
} |
|||
|
|||
public override bool barrierDismissible { |
|||
get { return true; } |
|||
} |
|||
|
|||
public override Color barrierColor { |
|||
get { return null; } |
|||
} |
|||
|
|||
public string barrierLabel; |
|||
|
|||
public override Widget buildPage(BuildContext context, Animation<float> animation, |
|||
Animation<float> secondaryAnimation) { |
|||
D.assert(WidgetsD.debugCheckHasDirectionality(context)); |
|||
float screenHeight = MediaQuery.of(context).size.height; |
|||
float maxMenuHeight = screenHeight - 2.0f * DropdownConstants._kMenuItemHeight; |
|||
|
|||
float buttonTop = this.buttonRect.top; |
|||
float buttonBottom = this.buttonRect.bottom; |
|||
|
|||
float topLimit = Mathf.Min(DropdownConstants._kMenuItemHeight, buttonTop); |
|||
float bottomLimit = Mathf.Max(screenHeight - DropdownConstants._kMenuItemHeight, buttonBottom); |
|||
|
|||
float? selectedItemOffset = this.selectedIndex * DropdownConstants._kMenuItemHeight + |
|||
Constants.kMaterialListPadding.top; |
|||
|
|||
float? menuTop = (buttonTop - selectedItemOffset) - |
|||
(DropdownConstants._kMenuItemHeight - this.buttonRect.height) / 2.0f; |
|||
float preferredMenuHeight = (this.items.Count * DropdownConstants._kMenuItemHeight) + |
|||
Constants.kMaterialListPadding.vertical; |
|||
|
|||
float menuHeight = Mathf.Min(maxMenuHeight, preferredMenuHeight); |
|||
|
|||
float? menuBottom = menuTop + menuHeight; |
|||
|
|||
if (menuTop < topLimit) { |
|||
menuTop = Mathf.Min(buttonTop, topLimit); |
|||
} |
|||
|
|||
if (menuBottom > bottomLimit) { |
|||
menuBottom = Mathf.Max(buttonBottom, bottomLimit); |
|||
menuTop = menuBottom - menuHeight; |
|||
} |
|||
|
|||
if (this.scrollController == null) { |
|||
float scrollOffset = preferredMenuHeight > maxMenuHeight |
|||
? Mathf.Max(0.0f, selectedItemOffset ?? 0.0f - (buttonTop - (menuTop ?? 0.0f))) |
|||
: 0.0f; |
|||
this.scrollController = new ScrollController(initialScrollOffset: scrollOffset); |
|||
} |
|||
|
|||
TextDirection textDirection = Directionality.of(context); |
|||
Widget menu = new _DropdownMenu<T>( |
|||
route: this, |
|||
padding: this.padding |
|||
); |
|||
|
|||
if (this.theme != null) { |
|||
menu = new Theme(data: this.theme, child: menu); |
|||
} |
|||
|
|||
return MediaQuery.removePadding( |
|||
context: context, |
|||
removeTop: true, |
|||
removeBottom: true, |
|||
removeLeft: true, |
|||
removeRight: true, |
|||
child: new Builder( |
|||
builder: (BuildContext _context) => { |
|||
return new CustomSingleChildLayout( |
|||
layoutDelegate: new _DropdownMenuRouteLayout<T>( |
|||
buttonRect: this.buttonRect, |
|||
menuTop: menuTop ?? 0.0f, |
|||
menuHeight: menuHeight, |
|||
textDirection: textDirection |
|||
), |
|||
child: menu |
|||
); |
|||
} |
|||
) |
|||
); |
|||
} |
|||
|
|||
public void _dismiss() { |
|||
this.navigator?.removeRoute(this); |
|||
} |
|||
} |
|||
|
|||
public class DropdownMenuItem<T> : StatelessWidget where T : class { |
|||
public DropdownMenuItem( |
|||
Key key = null, |
|||
T value = null, |
|||
Widget child = null |
|||
) : base(key: key) { |
|||
D.assert(child != null); |
|||
this.value = value; |
|||
this.child = child; |
|||
} |
|||
|
|||
public readonly Widget child; |
|||
|
|||
public readonly T value; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new Container( |
|||
height: DropdownConstants._kMenuItemHeight, |
|||
alignment: Alignment.centerLeft, |
|||
child: this.child |
|||
); |
|||
} |
|||
} |
|||
|
|||
public class DropdownButtonHideUnderline : InheritedWidget { |
|||
public DropdownButtonHideUnderline( |
|||
Key key = null, |
|||
Widget child = null |
|||
) : base(key: key, child: child) { |
|||
D.assert(child != null); |
|||
} |
|||
|
|||
public static bool at(BuildContext context) { |
|||
return context.inheritFromWidgetOfExactType(typeof(DropdownButtonHideUnderline)) != null; |
|||
} |
|||
|
|||
public override bool updateShouldNotify(InheritedWidget oldWidget) { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
public class DropdownButton<T> : StatefulWidget where T : class { |
|||
public DropdownButton( |
|||
Key key = null, |
|||
List<DropdownMenuItem<T>> items = null, |
|||
T value = null, |
|||
Widget hint = null, |
|||
Widget disabledHint = null, |
|||
ValueChanged<T> onChanged = null, |
|||
int elevation = 8, |
|||
TextStyle style = null, |
|||
float iconSize = 24.0f, |
|||
bool isDense = false, |
|||
bool isExpanded = false |
|||
) : |
|||
base(key: key) { |
|||
D.assert(items == null || value == null || |
|||
items.Where<DropdownMenuItem<T>>((DropdownMenuItem<T> item) => item.value.Equals(value)).ToList() |
|||
.Count == 1); |
|||
this.items = items; |
|||
this.value = value; |
|||
this.hint = hint; |
|||
this.disabledHint = disabledHint; |
|||
this.onChanged = onChanged; |
|||
this.elevation = elevation; |
|||
this.style = style; |
|||
this.iconSize = iconSize; |
|||
this.isDense = isDense; |
|||
this.isExpanded = isExpanded; |
|||
} |
|||
|
|||
public readonly List<DropdownMenuItem<T>> items; |
|||
|
|||
public readonly T value; |
|||
|
|||
public readonly Widget hint; |
|||
|
|||
public readonly Widget disabledHint; |
|||
|
|||
public readonly ValueChanged<T> onChanged; |
|||
|
|||
public readonly int elevation; |
|||
|
|||
public readonly TextStyle style; |
|||
|
|||
public readonly float iconSize; |
|||
|
|||
public readonly bool isDense; |
|||
|
|||
public readonly bool isExpanded; |
|||
|
|||
public override State createState() { |
|||
return new _DropdownButtonState<T>(); |
|||
} |
|||
} |
|||
|
|||
class _DropdownButtonState<T> : State<DropdownButton<T>>, WidgetsBindingObserver where T : class { |
|||
int? _selectedIndex; |
|||
_DropdownRoute<T> _dropdownRoute; |
|||
|
|||
public void didChangeTextScaleFactor() { |
|||
} |
|||
|
|||
public void didChangeLocales(List<Locale> locale) { |
|||
} |
|||
|
|||
public IPromise<bool> didPopRoute() { |
|||
return Promise<bool>.Resolved(false); |
|||
} |
|||
|
|||
public IPromise<bool> didPushRoute(string route) { |
|||
return Promise<bool>.Resolved(false); |
|||
} |
|||
|
|||
public override void initState() { |
|||
base.initState(); |
|||
this._updateSelectedIndex(); |
|||
WidgetsBinding.instance.addObserver(this); |
|||
} |
|||
|
|||
public override void dispose() { |
|||
WidgetsBinding.instance.removeObserver(this); |
|||
this._removeDropdownRoute(); |
|||
base.dispose(); |
|||
} |
|||
|
|||
public void didChangeMetrics() { |
|||
this._removeDropdownRoute(); |
|||
} |
|||
|
|||
void _removeDropdownRoute() { |
|||
this._dropdownRoute?._dismiss(); |
|||
this._dropdownRoute = null; |
|||
} |
|||
|
|||
public override void didUpdateWidget(StatefulWidget oldWidget) { |
|||
base.didUpdateWidget(oldWidget); |
|||
this._updateSelectedIndex(); |
|||
} |
|||
|
|||
void _updateSelectedIndex() { |
|||
if (!this._enabled) { |
|||
return; |
|||
} |
|||
|
|||
D.assert(this.widget.value == null || |
|||
this.widget.items.Where((DropdownMenuItem<T> item) => item.value.Equals(this.widget.value)) |
|||
.ToList().Count == 1); |
|||
this._selectedIndex = null; |
|||
for (int itemIndex = 0; itemIndex < this.widget.items.Count; itemIndex++) { |
|||
if (this.widget.items[itemIndex].value.Equals(this.widget.value)) { |
|||
this._selectedIndex = itemIndex; |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
|
|||
TextStyle _textStyle { |
|||
get { return this.widget.style ?? Theme.of(this.context).textTheme.subhead; } |
|||
} |
|||
|
|||
void _handleTap() { |
|||
RenderBox itemBox = (RenderBox) this.context.findRenderObject(); |
|||
Rect itemRect = itemBox.localToGlobal(Offset.zero) & itemBox.size; |
|||
TextDirection textDirection = Directionality.of(this.context); |
|||
EdgeInsets menuMargin = ButtonTheme.of(this.context).alignedDropdown |
|||
? DropdownConstants._kAlignedMenuMargin |
|||
: DropdownConstants._kUnalignedMenuMargin; |
|||
|
|||
D.assert(this._dropdownRoute == null); |
|||
this._dropdownRoute = new _DropdownRoute<T>( |
|||
items: this.widget.items, |
|||
buttonRect: menuMargin.inflateRect(itemRect), |
|||
padding: DropdownConstants._kMenuItemPadding, |
|||
selectedIndex: this._selectedIndex ?? 0, |
|||
elevation: this.widget.elevation, |
|||
theme: Theme.of(this.context, shadowThemeOnly: true), |
|||
style: this._textStyle, |
|||
barrierLabel: MaterialLocalizations.of(this.context).modalBarrierDismissLabel |
|||
); |
|||
|
|||
Navigator.push(this.context, this._dropdownRoute).Then(newValue => { |
|||
_DropdownRouteResult<T> value = newValue as _DropdownRouteResult<T>; |
|||
this._dropdownRoute = null; |
|||
if (!this.mounted || newValue == null) { |
|||
return; |
|||
} |
|||
|
|||
if (this.widget.onChanged != null) { |
|||
this.widget.onChanged(value.result); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
float? _denseButtonHeight { |
|||
get { |
|||
return Mathf.Max(this._textStyle.fontSize ?? 0.0f, |
|||
Mathf.Max(this.widget.iconSize, DropdownConstants._kDenseButtonHeight)); |
|||
} |
|||
} |
|||
|
|||
Color _downArrowColor { |
|||
get { |
|||
if (this._enabled) { |
|||
if (Theme.of(this.context).brightness == Brightness.light) { |
|||
return Colors.grey.shade700; |
|||
} |
|||
else { |
|||
return Colors.white70; |
|||
} |
|||
} |
|||
else { |
|||
if (Theme.of(this.context).brightness == Brightness.light) { |
|||
return Colors.grey.shade400; |
|||
} |
|||
else { |
|||
return Colors.white10; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
bool _enabled { |
|||
get { return this.widget.items != null && this.widget.items.isNotEmpty() && this.widget.onChanged != null; } |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
D.assert(MaterialD.debugCheckHasMaterial(context)); |
|||
D.assert(MaterialD.debugCheckHasMaterialLocalizations(context)); |
|||
|
|||
List<Widget> items = this._enabled ? new List<Widget>(this.widget.items) : new List<Widget>(); |
|||
int hintIndex = 0; |
|||
if (this.widget.hint != null || (!this._enabled && this.widget.disabledHint != null)) { |
|||
Widget emplacedHint = |
|||
this._enabled |
|||
? this.widget.hint |
|||
: new DropdownMenuItem<Widget>(child: this.widget.disabledHint ?? this.widget.hint); |
|||
hintIndex = items.Count; |
|||
items.Add(new DefaultTextStyle( |
|||
style: this._textStyle.copyWith(color: Theme.of(context).hintColor), |
|||
child: new IgnorePointer( |
|||
child: emplacedHint |
|||
) |
|||
)); |
|||
} |
|||
|
|||
EdgeInsets padding = ButtonTheme.of(context).alignedDropdown |
|||
? DropdownConstants._kAlignedButtonPadding |
|||
: DropdownConstants._kUnalignedButtonPadding; |
|||
|
|||
IndexedStack innerItemsWidget = new IndexedStack( |
|||
index: this._enabled ? (this._selectedIndex ?? hintIndex) : hintIndex, |
|||
alignment: Alignment.centerLeft, |
|||
children: items |
|||
); |
|||
|
|||
Widget result = new DefaultTextStyle( |
|||
style: this._textStyle, |
|||
child: new Container( |
|||
padding: padding, |
|||
height: this.widget.isDense ? this._denseButtonHeight : null, |
|||
child: new Row( |
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|||
mainAxisSize: MainAxisSize.min, |
|||
children: new List<Widget> { |
|||
this.widget.isExpanded ? new Expanded(child: innerItemsWidget) : (Widget) innerItemsWidget, |
|||
new Icon(Icons.arrow_drop_down, |
|||
size: this.widget.iconSize, |
|||
color: this._downArrowColor |
|||
) |
|||
} |
|||
) |
|||
) |
|||
); |
|||
|
|||
if (!DropdownButtonHideUnderline.at(context)) { |
|||
float bottom = this.widget.isDense ? 0.0f : 8.0f; |
|||
result = new Stack( |
|||
children: new List<Widget> { |
|||
result, |
|||
new Positioned( |
|||
left: 0.0f, |
|||
right: 0.0f, |
|||
bottom: bottom, |
|||
child: new Container( |
|||
height: 1.0f, |
|||
decoration: new BoxDecoration( |
|||
border: new Border( |
|||
bottom: new BorderSide(color: new Color(0xFFBDBDBD), width: 0.0f)) |
|||
) |
|||
) |
|||
) |
|||
} |
|||
); |
|||
} |
|||
|
|||
return new GestureDetector( |
|||
onTap: this._enabled ? (GestureTapCallback) this._handleTap : null, |
|||
behavior: HitTestBehavior.opaque, |
|||
child: result |
|||
); |
|||
} |
|||
} |
|||
|
|||
public class DropdownButtonFormField<T> : FormField<T> where T : class { |
|||
public DropdownButtonFormField( |
|||
Key key = null, |
|||
T value = null, |
|||
List<DropdownMenuItem<T>> items = null, |
|||
ValueChanged<T> onChanged = null, |
|||
InputDecoration decoration = null, |
|||
FormFieldSetter<T> onSaved = null, |
|||
FormFieldValidator<T> validator = null, |
|||
Widget hint = null |
|||
) : base( |
|||
key: key, |
|||
onSaved: onSaved, |
|||
initialValue: value, |
|||
validator: validator, |
|||
builder: (FormFieldState<T> field) => { |
|||
InputDecoration effectiveDecoration = (decoration ?? new InputDecoration()) |
|||
.applyDefaults(Theme.of(field.context).inputDecorationTheme); |
|||
return new InputDecorator( |
|||
decoration: effectiveDecoration.copyWith(errorText: field.errorText), |
|||
isEmpty: value == null, |
|||
child: new DropdownButtonHideUnderline( |
|||
child: new DropdownButton<T>( |
|||
isDense: true, |
|||
value: value, |
|||
items: items, |
|||
hint: hint, |
|||
onChanged: field.didChange |
|||
) |
|||
) |
|||
); |
|||
} |
|||
) { |
|||
this.onChanged = onChanged; |
|||
} |
|||
|
|||
public readonly ValueChanged<T> onChanged; |
|||
|
|||
public override State createState() { |
|||
return new _DropdownButtonFormFieldState<T>(); |
|||
} |
|||
} |
|||
|
|||
class _DropdownButtonFormFieldState<T> : FormFieldState<T> where T : class { |
|||
public DropdownButtonFormField<T> widget { |
|||
get { return base.widget as DropdownButtonFormField<T>; } |
|||
} |
|||
|
|||
public override void didChange(T value) { |
|||
base.didChange(value); |
|||
if (this.widget.onChanged != null) { |
|||
this.widget.onChanged(value); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 54d382ec712d4e87b802716ca97c1f3d |
|||
timeCreated: 1552537966 |
|
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.ui; |
|||
using UnityEngine; |
|||
using Canvas = Unity.UIWidgets.ui.Canvas; |
|||
using Rect = Unity.UIWidgets.ui.Rect; |
|||
|
|||
namespace Unity.UIWidgets.material { |
|||
public abstract class InputBorder : ShapeBorder { |
|||
public InputBorder( |
|||
BorderSide borderSide = null |
|||
) { |
|||
this.borderSide = this.borderSide ?? BorderSide.none; |
|||
} |
|||
|
|||
public static readonly InputBorder none = new _NoInputBorder(); |
|||
|
|||
public readonly BorderSide borderSide; |
|||
|
|||
public abstract InputBorder copyWith(BorderSide borderSide = null); |
|||
|
|||
public virtual bool isOutline { get; } |
|||
|
|||
public abstract void paint(Canvas canvas, Rect rect, |
|||
float gapStart, |
|||
float gapExtent = 0.0f, |
|||
float gapPercentage = 0.0f, |
|||
TextDirection? textDirection = null |
|||
); |
|||
|
|||
public override void paint(Canvas canvas, Rect rect) { |
|||
this.paint(canvas, rect, 0.0f); |
|||
} |
|||
} |
|||
|
|||
class _NoInputBorder : InputBorder { |
|||
public _NoInputBorder() : base(borderSide: BorderSide.none) { |
|||
} |
|||
|
|||
public override InputBorder copyWith(BorderSide borderSide) { |
|||
return new _NoInputBorder(); |
|||
} |
|||
|
|||
public override bool isOutline { |
|||
get { return false; } |
|||
} |
|||
|
|||
public override EdgeInsets dimensions { |
|||
get { return EdgeInsets.zero; } |
|||
} |
|||
|
|||
public override ShapeBorder scale(float t) { |
|||
return new _NoInputBorder(); |
|||
} |
|||
|
|||
public override Path getInnerPath(Rect rect) { |
|||
Path path = new Path(); |
|||
path.addRect(rect); |
|||
return path; |
|||
} |
|||
|
|||
public override Path getOuterPath(Rect rect) { |
|||
Path path = new Path(); |
|||
path.addRect(rect); |
|||
return path; |
|||
} |
|||
|
|||
public override void paint(Canvas canvas, Rect rect, |
|||
float gapStart, |
|||
float gapExtent = 0.0f, |
|||
float gapPercentage = 0.0f, |
|||
TextDirection? textDirection = null |
|||
) { |
|||
} |
|||
} |
|||
|
|||
class UnderlineInputBorder : InputBorder { |
|||
public UnderlineInputBorder( |
|||
BorderSide borderSide = null, |
|||
BorderRadius borderRadius = null |
|||
) : base(borderSide: borderSide ?? new BorderSide()) { |
|||
this.borderRadius = borderRadius ?? BorderRadius.only( |
|||
topLeft: Radius.circular(4.0f), |
|||
topRight: Radius.circular(4.0f) |
|||
); |
|||
} |
|||
|
|||
public readonly BorderRadius borderRadius; |
|||
|
|||
public override bool isOutline { |
|||
get { return false; } |
|||
} |
|||
|
|||
public UnderlineInputBorder copyWith(BorderSide borderSide = null, BorderRadius borderRadius = null) { |
|||
return new UnderlineInputBorder( |
|||
borderSide: borderSide ?? this.borderSide, |
|||
borderRadius: borderRadius ?? this.borderRadius |
|||
); |
|||
} |
|||
|
|||
public override InputBorder copyWith(BorderSide borderSide = null) { |
|||
return new UnderlineInputBorder( |
|||
borderSide: borderSide ?? this.borderSide |
|||
); |
|||
} |
|||
|
|||
public override EdgeInsets dimensions { |
|||
get { return EdgeInsets.only(bottom: this.borderSide.width); } |
|||
} |
|||
|
|||
public override ShapeBorder scale(float t) { |
|||
return new UnderlineInputBorder(borderSide: this.borderSide.scale(t)); |
|||
} |
|||
|
|||
public override Path getInnerPath(Rect rect) { |
|||
Path path = new Path(); |
|||
path.addRect(Rect.fromLTWH(rect.left, rect.top, rect.width, |
|||
Mathf.Max(0.0f, rect.height - this.borderSide.width))); |
|||
return path; |
|||
} |
|||
|
|||
public override Path getOuterPath(Rect rect) { |
|||
Path path = new Path(); |
|||
path.addRRect(this.borderRadius.toRRect(rect)); |
|||
return path; |
|||
} |
|||
|
|||
public override ShapeBorder lerpFrom(ShapeBorder a, float t) { |
|||
if (a is UnderlineInputBorder) { |
|||
return new UnderlineInputBorder( |
|||
borderSide: BorderSide.lerp((a as UnderlineInputBorder).borderSide, this.borderSide, t), |
|||
borderRadius: BorderRadius.lerp((a as UnderlineInputBorder).borderRadius, this.borderRadius, t) |
|||
); |
|||
} |
|||
|
|||
return base.lerpFrom(a, t); |
|||
} |
|||
|
|||
public override ShapeBorder lerpTo(ShapeBorder b, float t) { |
|||
if (b is UnderlineInputBorder) { |
|||
return new UnderlineInputBorder( |
|||
borderSide: BorderSide.lerp(this.borderSide, (b as UnderlineInputBorder).borderSide, t), |
|||
borderRadius: BorderRadius.lerp(this.borderRadius, (b as UnderlineInputBorder).borderRadius, t) |
|||
); |
|||
} |
|||
|
|||
return base.lerpTo(b, t); |
|||
} |
|||
|
|||
public override void paint(Canvas canvas, Rect rect, |
|||
float gapStart, |
|||
float gapExtent = 0.0f, |
|||
float gapPercentage = 0.0f, |
|||
TextDirection? textDirection = null |
|||
) { |
|||
if (this.borderRadius.bottomLeft != Radius.zero || this.borderRadius.bottomRight != Radius.zero) { |
|||
canvas.clipPath(this.getOuterPath(rect)); |
|||
} |
|||
|
|||
canvas.drawLine(rect.bottomLeft, rect.bottomRight, this.borderSide.toPaint()); |
|||
} |
|||
|
|||
public static bool operator ==(UnderlineInputBorder left, UnderlineInputBorder other) { |
|||
return left.borderSide == other.borderSide; |
|||
} |
|||
|
|||
public static bool operator !=(UnderlineInputBorder left, UnderlineInputBorder other) { |
|||
return left.borderSide != other.borderSide; |
|||
} |
|||
|
|||
public override int GetHashCode() { |
|||
return this.borderSide.GetHashCode(); |
|||
} |
|||
} |
|||
|
|||
public class OutlineInputBorder : InputBorder { |
|||
public OutlineInputBorder( |
|||
BorderSide borderSide = null, |
|||
BorderRadius borderRadius = null, |
|||
float gapPadding = 4.0f |
|||
) : base(borderSide: borderSide ?? new BorderSide()) { |
|||
D.assert(gapPadding >= 0.0f); |
|||
this.borderRadius = borderRadius ?? BorderRadius.all(Radius.circular(4.0f)); |
|||
} |
|||
|
|||
static bool _cornersAreCircular(BorderRadius borderRadius) { |
|||
return borderRadius.topLeft.x == borderRadius.topLeft.y |
|||
&& borderRadius.bottomLeft.x == borderRadius.bottomLeft.y |
|||
&& borderRadius.topRight.x == borderRadius.topRight.y |
|||
&& borderRadius.bottomRight.x == borderRadius.bottomRight.y; |
|||
} |
|||
|
|||
public readonly float gapPadding; |
|||
|
|||
public readonly BorderRadius borderRadius; |
|||
|
|||
public override bool isOutline { |
|||
get { return true; } |
|||
} |
|||
|
|||
public OutlineInputBorder copyWith( |
|||
BorderSide borderSide, |
|||
BorderRadius borderRadius, |
|||
float? gapPadding |
|||
) { |
|||
return new OutlineInputBorder( |
|||
borderSide: borderSide ?? this.borderSide, |
|||
borderRadius: borderRadius ?? this.borderRadius, |
|||
gapPadding: gapPadding ?? this.gapPadding |
|||
); |
|||
} |
|||
|
|||
public override InputBorder copyWith(BorderSide borderSide) { |
|||
return new OutlineInputBorder( |
|||
borderSide: borderSide ?? this.borderSide, |
|||
borderRadius: this.borderRadius, |
|||
gapPadding: this.gapPadding |
|||
); |
|||
} |
|||
|
|||
public override EdgeInsets dimensions { |
|||
get { return EdgeInsets.all(this.borderSide.width); } |
|||
} |
|||
|
|||
public override ShapeBorder scale(float t) { |
|||
return new OutlineInputBorder( |
|||
borderSide: this.borderSide.scale(t), |
|||
borderRadius: this.borderRadius * t, |
|||
gapPadding: this.gapPadding * t |
|||
); |
|||
} |
|||
|
|||
public override ShapeBorder lerpFrom(ShapeBorder a, float t) { |
|||
if (a is OutlineInputBorder) { |
|||
OutlineInputBorder outline = a as OutlineInputBorder; |
|||
return new OutlineInputBorder( |
|||
borderRadius: BorderRadius.lerp(outline.borderRadius, this.borderRadius, t), |
|||
borderSide: BorderSide.lerp(outline.borderSide, this.borderSide, t), |
|||
gapPadding: outline.gapPadding |
|||
); |
|||
} |
|||
|
|||
return base.lerpFrom(a, t); |
|||
} |
|||
|
|||
public override ShapeBorder lerpTo(ShapeBorder b, float t) { |
|||
if (b is OutlineInputBorder) { |
|||
OutlineInputBorder outline = b as OutlineInputBorder; |
|||
return new OutlineInputBorder( |
|||
borderRadius: BorderRadius.lerp(this.borderRadius, outline.borderRadius, t), |
|||
borderSide: BorderSide.lerp(this.borderSide, outline.borderSide, t), |
|||
gapPadding: outline.gapPadding |
|||
); |
|||
} |
|||
|
|||
return base.lerpTo(b, t); |
|||
} |
|||
|
|||
public override Path getInnerPath(Rect rect) { |
|||
Path path = new Path(); |
|||
path.addRRect(this.borderRadius.toRRect(rect).deflate(this.borderSide.width)); |
|||
return path; |
|||
} |
|||
|
|||
public override Path getOuterPath(Rect rect) { |
|||
Path path = new Path(); |
|||
path.addRRect(this.borderRadius.toRRect(rect)); |
|||
return path; |
|||
} |
|||
|
|||
Path _gapBorderPath(Canvas canvas, RRect center, float start, float extent) { |
|||
Rect tlCorner = Rect.fromLTWH( |
|||
center.left, |
|||
center.top, |
|||
center.tlRadiusX * 2.0f, |
|||
center.tlRadiusY * 2.0f |
|||
); |
|||
Rect trCorner = Rect.fromLTWH( |
|||
center.right - center.trRadiusX * 2.0f, |
|||
center.top, |
|||
center.trRadiusX * 2.0f, |
|||
center.trRadiusY * 2.0f |
|||
); |
|||
Rect brCorner = Rect.fromLTWH( |
|||
center.right - center.brRadiusX * 2.0f, |
|||
center.bottom - center.brRadiusY * 2.0f, |
|||
center.brRadiusX * 2.0f, |
|||
center.brRadiusY * 2.0f |
|||
); |
|||
Rect blCorner = Rect.fromLTWH( |
|||
center.left, |
|||
center.bottom - center.brRadiusY * 2.0f, |
|||
center.blRadiusX * 2.0f, |
|||
center.blRadiusY * 2.0f |
|||
); |
|||
|
|||
const float cornerArcSweep = Mathf.PI / 2.0f; |
|||
float tlCornerArcSweep = start < center.tlRadiusX |
|||
? Mathf.Asin(start / center.tlRadiusX) |
|||
: Mathf.PI / 2.0f; |
|||
|
|||
Path path = new Path(); |
|||
path.addArc(tlCorner, Mathf.PI, tlCornerArcSweep); |
|||
path.moveTo(center.left + center.tlRadiusX, center.top); |
|||
|
|||
if (start > center.tlRadiusX) { |
|||
path.lineTo(center.left + start, center.top); |
|||
} |
|||
|
|||
const float trCornerArcStart = (3 * Mathf.PI) / 2.0f; |
|||
const float trCornerArcSweep = cornerArcSweep; |
|||
if (start + extent < center.width - center.trRadiusX) { |
|||
path.relativeMoveTo(extent, 0.0f); |
|||
path.lineTo(center.right - center.trRadiusX, center.top); |
|||
path.addArc(trCorner, trCornerArcStart, trCornerArcSweep); |
|||
} |
|||
else if (start + extent < center.width) { |
|||
float dx = center.width - (start + extent); |
|||
float sweep = Mathf.Acos(dx / center.trRadiusX); |
|||
path.addArc(trCorner, trCornerArcStart + sweep, trCornerArcSweep - sweep); |
|||
} |
|||
|
|||
path.moveTo(center.right, center.top + center.trRadiusY); |
|||
path.lineTo(center.right, center.bottom - center.brRadiusY); |
|||
path.addArc(brCorner, 0.0f, cornerArcSweep); |
|||
path.lineTo(center.left + center.blRadiusX, center.bottom); |
|||
path.addArc(blCorner, Mathf.PI / 2.0f, cornerArcSweep); |
|||
path.lineTo(center.left, center.top + center.trRadiusY); |
|||
return path; |
|||
} |
|||
|
|||
public override void paint(Canvas canvas, Rect rect, |
|||
float gapStart, |
|||
float gapExtent = 0.0f, |
|||
float gapPercentage = 0.0f, |
|||
TextDirection? textDirection = null |
|||
) { |
|||
D.assert(gapPercentage >= 0.0f && gapPercentage <= 1.0f); |
|||
D.assert(_cornersAreCircular(this.borderRadius)); |
|||
|
|||
Paint paint = this.borderSide.toPaint(); |
|||
RRect outer = this.borderRadius.toRRect(rect); |
|||
RRect center = outer.deflate(this.borderSide.width / 2.0f); |
|||
if (gapExtent <= 0.0f || gapPercentage == 0.0f) { |
|||
canvas.drawRRect(center, paint); |
|||
} |
|||
else { |
|||
float extent = MathUtils.lerpFloat(0.0f, gapExtent + this.gapPadding * 2.0f, gapPercentage); |
|||
switch (textDirection) { |
|||
case TextDirection.rtl: { |
|||
Path path = this._gapBorderPath(canvas, center, gapStart + this.gapPadding - extent, extent); |
|||
canvas.drawPath(path, paint); |
|||
break; |
|||
} |
|||
case TextDirection.ltr: { |
|||
Path path = this._gapBorderPath(canvas, center, gapStart - this.gapPadding, extent); |
|||
canvas.drawPath(path, paint); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
public static bool operator ==(OutlineInputBorder left, OutlineInputBorder other) { |
|||
return other.borderSide == left.borderSide |
|||
&& other.borderRadius == left.borderRadius |
|||
&& other.gapPadding == left.gapPadding; |
|||
} |
|||
|
|||
public static bool operator !=(OutlineInputBorder left, OutlineInputBorder other) { |
|||
return !(left == other); |
|||
} |
|||
|
|||
public override int GetHashCode() { |
|||
var hashCode = this.borderSide.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.borderRadius.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.gapPadding.GetHashCode(); |
|||
return hashCode; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6431f8efd0b444ea9982ff6d0a0e74f4 |
|||
timeCreated: 1552619063 |
1001
Runtime/material/input_decorator.cs
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
|
|||
fileFormatVersion: 2 |
|||
guid: 2106361ab28b4560a12fdbae0f1b1c8f |
|||
timeCreated: 1552548801 |
|
|||
using System; |
|||
using Unity.UIWidgets.animation; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using UnityEngine; |
|||
using Canvas = Unity.UIWidgets.ui.Canvas; |
|||
using Color = Unity.UIWidgets.ui.Color; |
|||
|
|||
namespace Unity.UIWidgets.material { |
|||
class _ProgressIndicatorContants { |
|||
public const float _kLinearProgressIndicatorHeight = 6.0f; |
|||
public const float _kMinCircularProgressIndicatorSize = 36.0f; |
|||
public const int _kIndeterminateLinearDuration = 1800; |
|||
|
|||
public static readonly Animatable<float> _kStrokeHeadTween = new CurveTween( |
|||
curve: new Interval(0.0f, 0.5f, curve: Curves.fastOutSlowIn) |
|||
).chain(new CurveTween( |
|||
curve: new SawTooth(5) |
|||
)); |
|||
|
|||
public static readonly Animatable<float> _kStrokeTailTween = new CurveTween( |
|||
curve: new Interval(0.5f, 1.0f, curve: Curves.fastOutSlowIn) |
|||
).chain(new CurveTween( |
|||
curve: new SawTooth(5) |
|||
)); |
|||
|
|||
public static readonly Animatable<int> _kStepTween = new StepTween(begin: 0, end: 5); |
|||
|
|||
public static readonly Animatable<float> _kRotationTween = new CurveTween(curve: new SawTooth(5)); |
|||
} |
|||
|
|||
public abstract class ProgressIndicator : StatefulWidget { |
|||
public ProgressIndicator( |
|||
Key key = null, |
|||
float? value = null, |
|||
Color backgroundColor = null, |
|||
Animation<Color> valueColor = null |
|||
) : base(key: key) { |
|||
this.value = value; |
|||
this.backgroundColor = backgroundColor; |
|||
this.valueColor = valueColor; |
|||
} |
|||
|
|||
public readonly float? value; |
|||
|
|||
public readonly Color backgroundColor; |
|||
|
|||
public readonly Animation<Color> valueColor; |
|||
|
|||
public Color _getBackgroundColor(BuildContext context) { |
|||
return this.backgroundColor ?? Theme.of(context).backgroundColor; |
|||
} |
|||
|
|||
public Color _getValueColor(BuildContext context) { |
|||
return this.valueColor?.value ?? Theme.of(context).accentColor; |
|||
} |
|||
|
|||
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
|||
base.debugFillProperties(properties); |
|||
properties.add(new PercentProperty("value", this.value ?? 0.0f, showName: false, |
|||
ifNull: "<indeterminate>")); |
|||
} |
|||
} |
|||
|
|||
class _LinearProgressIndicatorPainter : AbstractCustomPainter { |
|||
public _LinearProgressIndicatorPainter( |
|||
Color backgroundColor = null, |
|||
Color valueColor = null, |
|||
float? value = null, |
|||
float? animationValue = null, |
|||
TextDirection? textDirection = null |
|||
) { |
|||
D.assert(textDirection != null); |
|||
this.backgroundColor = backgroundColor; |
|||
this.valueColor = valueColor; |
|||
this.value = value; |
|||
this.animationValue = animationValue; |
|||
this.textDirection = textDirection; |
|||
} |
|||
|
|||
public readonly Color backgroundColor; |
|||
public readonly Color valueColor; |
|||
public readonly float? value; |
|||
public readonly float? animationValue; |
|||
public readonly TextDirection? textDirection; |
|||
|
|||
static readonly Curve line1Head = new Interval( |
|||
0.0f, |
|||
750.0f / _ProgressIndicatorContants._kIndeterminateLinearDuration, |
|||
curve: new Cubic(0.2f, 0.0f, 0.8f, 1.0f) |
|||
); |
|||
|
|||
static readonly Curve line1Tail = new Interval( |
|||
333.0f / _ProgressIndicatorContants._kIndeterminateLinearDuration, |
|||
(333.0f + 750.0f) / _ProgressIndicatorContants._kIndeterminateLinearDuration, |
|||
curve: new Cubic(0.4f, 0.0f, 1.0f, 1.0f) |
|||
); |
|||
|
|||
static readonly Curve line2Head = new Interval( |
|||
1000.0f / _ProgressIndicatorContants._kIndeterminateLinearDuration, |
|||
(1000.0f + 567.0f) / _ProgressIndicatorContants._kIndeterminateLinearDuration, |
|||
curve: new Cubic(0.0f, 0.0f, 0.65f, 1.0f) |
|||
); |
|||
|
|||
static readonly Curve line2Tail = new Interval( |
|||
1267.0f / _ProgressIndicatorContants._kIndeterminateLinearDuration, |
|||
(1267.0f + 533.0f) / _ProgressIndicatorContants._kIndeterminateLinearDuration, |
|||
curve: new Cubic(0.10f, 0.0f, 0.45f, 1.0f) |
|||
); |
|||
|
|||
public override void paint(Canvas canvas, Size size) { |
|||
Paint paint = new Paint(); |
|||
paint.color = this.backgroundColor; |
|||
paint.style = PaintingStyle.fill; |
|||
canvas.drawRect(Offset.zero & size, paint); |
|||
|
|||
paint.color = this.valueColor; |
|||
|
|||
void drawBar(float x, float width) { |
|||
if (width <= 0.0f) { |
|||
return; |
|||
} |
|||
|
|||
float left; |
|||
switch (this.textDirection) { |
|||
case TextDirection.rtl: |
|||
left = size.width - width - x; |
|||
break; |
|||
case TextDirection.ltr: |
|||
left = x; |
|||
break; |
|||
default: |
|||
throw new Exception("Unknown text direction: " + this.textDirection); |
|||
} |
|||
|
|||
canvas.drawRect(new Offset(left, 0.0f) & new Size(width, size.height), paint); |
|||
} |
|||
|
|||
if (this.value != null) { |
|||
drawBar(0.0f, this.value.Value.clamp(0.0f, 1.0f) * size.width); |
|||
} |
|||
else { |
|||
float x1 = size.width * line1Tail.transform(this.animationValue ?? 0.0f); |
|||
float width1 = size.width * line1Head.transform(this.animationValue ?? 0.0f) - x1; |
|||
|
|||
float x2 = size.width * line2Tail.transform(this.animationValue ?? 0.0f); |
|||
float width2 = size.width * line2Head.transform(this.animationValue ?? 0.0f) - x2; |
|||
|
|||
drawBar(x1, width1); |
|||
drawBar(x2, width2); |
|||
} |
|||
} |
|||
|
|||
public override bool shouldRepaint(CustomPainter oldPainter) { |
|||
D.assert(oldPainter is _LinearProgressIndicatorPainter); |
|||
_LinearProgressIndicatorPainter painter = oldPainter as _LinearProgressIndicatorPainter; |
|||
return painter.backgroundColor != this.backgroundColor |
|||
|| painter.valueColor != this.valueColor |
|||
|| painter.value != this.value |
|||
|| painter.animationValue != this.animationValue |
|||
|| painter.textDirection != this.textDirection; |
|||
} |
|||
} |
|||
|
|||
public class LinearProgressIndicator : ProgressIndicator { |
|||
public LinearProgressIndicator( |
|||
Key key = null, |
|||
float? value = null, |
|||
Color backgroundColor = null, |
|||
Animation<Color> valueColor = null |
|||
) : base( |
|||
key: key, |
|||
value: value, |
|||
backgroundColor: backgroundColor, |
|||
valueColor: valueColor |
|||
) { |
|||
} |
|||
|
|||
public override State createState() { |
|||
return new _LinearProgressIndicatorState(); |
|||
} |
|||
} |
|||
|
|||
class _LinearProgressIndicatorState : SingleTickerProviderStateMixin<LinearProgressIndicator> { |
|||
AnimationController _controller; |
|||
|
|||
public _LinearProgressIndicatorState() { |
|||
} |
|||
|
|||
public override void initState() { |
|||
base.initState(); |
|||
this._controller = new AnimationController( |
|||
duration: new TimeSpan(0, 0, 0, 0, _ProgressIndicatorContants._kIndeterminateLinearDuration), |
|||
vsync: this |
|||
); |
|||
if (this.widget.value == null) { |
|||
this._controller.repeat(); |
|||
} |
|||
} |
|||
|
|||
public override void didUpdateWidget(StatefulWidget oldWidget) { |
|||
base.didUpdateWidget(oldWidget); |
|||
if (this.widget.value == null && !this._controller.isAnimating) { |
|||
this._controller.repeat(); |
|||
} |
|||
else if (this.widget.value != null && this._controller.isAnimating) { |
|||
this._controller.stop(); |
|||
} |
|||
} |
|||
|
|||
public override void dispose() { |
|||
this._controller.dispose(); |
|||
base.dispose(); |
|||
} |
|||
|
|||
Widget _buildIndicator(BuildContext context, float animationValue, TextDirection textDirection) { |
|||
return new Container( |
|||
constraints: new BoxConstraints( |
|||
minWidth: float.PositiveInfinity, |
|||
minHeight: _ProgressIndicatorContants._kLinearProgressIndicatorHeight |
|||
), |
|||
child: new CustomPaint( |
|||
painter: new _LinearProgressIndicatorPainter( |
|||
backgroundColor: this.widget._getBackgroundColor(context), |
|||
valueColor: this.widget._getValueColor(context), |
|||
value: this.widget.value, // may be null
|
|||
animationValue: animationValue, // ignored if widget.value is not null
|
|||
textDirection: textDirection |
|||
) |
|||
) |
|||
); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
TextDirection textDirection = Directionality.of(context); |
|||
|
|||
if (this.widget.value != null) { |
|||
return this._buildIndicator(context, this._controller.value, textDirection); |
|||
} |
|||
|
|||
return new AnimatedBuilder( |
|||
animation: this._controller.view, |
|||
builder: (BuildContext _context, Widget child) => { |
|||
return this._buildIndicator(_context, this._controller.value, textDirection); |
|||
} |
|||
); |
|||
} |
|||
} |
|||
|
|||
class _CircularProgressIndicatorPainter : AbstractCustomPainter { |
|||
public _CircularProgressIndicatorPainter( |
|||
Color valueColor = null, |
|||
float? value = null, |
|||
float? headValue = null, |
|||
float? tailValue = null, |
|||
int? stepValue = null, |
|||
float? rotationValue = null, |
|||
float? strokeWidth = null |
|||
) { |
|||
this.valueColor = valueColor; |
|||
this.value = value; |
|||
this.headValue = headValue; |
|||
this.tailValue = tailValue; |
|||
this.stepValue = stepValue; |
|||
this.rotationValue = rotationValue; |
|||
this.strokeWidth = strokeWidth; |
|||
this.arcStart = value != null |
|||
? _startAngle |
|||
: _startAngle + tailValue * 3 / 2 * Mathf.PI + rotationValue * Mathf.PI * 1.7f - |
|||
stepValue * 0.8f * Mathf.PI; |
|||
this.arcSweep = value != null |
|||
? value.Value.clamp(0.0f, 1.0f) * _sweep |
|||
: Mathf.Max(headValue * 3 / 2 * Mathf.PI - tailValue * 3 / 2 * Mathf.PI ?? 0.0f, _epsilon); |
|||
} |
|||
|
|||
public readonly Color valueColor; |
|||
public readonly float? value; |
|||
public readonly float? headValue; |
|||
public readonly float? tailValue; |
|||
public readonly int? stepValue; |
|||
public readonly float? rotationValue; |
|||
public readonly float? strokeWidth; |
|||
public readonly float? arcStart; |
|||
public readonly float? arcSweep; |
|||
|
|||
const float _twoPi = Mathf.PI * 2.0f; |
|||
const float _epsilon = .001f; |
|||
|
|||
const float _sweep = _twoPi - _epsilon; |
|||
const float _startAngle = -Mathf.PI / 2.0f; |
|||
|
|||
public override void paint(Canvas canvas, Size size) { |
|||
Paint paint = new Paint(); |
|||
paint.color = this.valueColor; |
|||
paint.strokeWidth = this.strokeWidth ?? 0.0f; |
|||
paint.style = PaintingStyle.stroke; |
|||
|
|||
if (this.value == null) // Indeterminate
|
|||
{ |
|||
paint.strokeCap = StrokeCap.square; |
|||
} |
|||
|
|||
canvas.drawArc(Offset.zero & size, this.arcStart ?? 0.0f, this.arcSweep ?? 0.0f, false, paint); |
|||
} |
|||
|
|||
public override bool shouldRepaint(CustomPainter oldPainter) { |
|||
D.assert(oldPainter is _CircularProgressIndicatorPainter); |
|||
_CircularProgressIndicatorPainter painter = oldPainter as _CircularProgressIndicatorPainter; |
|||
return painter.valueColor != this.valueColor |
|||
|| painter.value != this.value |
|||
|| painter.headValue != this.headValue |
|||
|| painter.tailValue != this.tailValue |
|||
|| painter.stepValue != this.stepValue |
|||
|| painter.rotationValue != this.rotationValue |
|||
|| painter.strokeWidth != this.strokeWidth; |
|||
} |
|||
} |
|||
|
|||
public class CircularProgressIndicator : ProgressIndicator { |
|||
public CircularProgressIndicator( |
|||
Key key = null, |
|||
float? value = null, |
|||
Color backgroundColor = null, |
|||
Animation<Color> valueColor = null, |
|||
float strokeWidth = 4.0f |
|||
) : base( |
|||
key: key, |
|||
value: value, |
|||
backgroundColor: backgroundColor, |
|||
valueColor: valueColor |
|||
) { |
|||
this.strokeWidth = strokeWidth; |
|||
} |
|||
|
|||
public readonly float? strokeWidth; |
|||
|
|||
public override State createState() { |
|||
return new _CircularProgressIndicatorState(); |
|||
} |
|||
} |
|||
|
|||
|
|||
class _CircularProgressIndicatorState : SingleTickerProviderStateMixin<CircularProgressIndicator> { |
|||
protected AnimationController _controller; |
|||
|
|||
public _CircularProgressIndicatorState() { |
|||
} |
|||
|
|||
public override void initState() { |
|||
base.initState(); |
|||
this._controller = new AnimationController( |
|||
duration: new TimeSpan(0, 0, 0, 5), |
|||
vsync: this |
|||
); |
|||
if (this.widget.value == null) { |
|||
this._controller.repeat(); |
|||
} |
|||
} |
|||
|
|||
public override void didUpdateWidget(StatefulWidget oldWidget) { |
|||
base.didUpdateWidget(oldWidget); |
|||
if (this.widget.value == null && !this._controller.isAnimating) { |
|||
this._controller.repeat(); |
|||
} |
|||
else if (this.widget.value != null && this._controller.isAnimating) { |
|||
this._controller.stop(); |
|||
} |
|||
} |
|||
|
|||
public override void dispose() { |
|||
this._controller.dispose(); |
|||
base.dispose(); |
|||
} |
|||
|
|||
Widget _buildIndicator(BuildContext context, float headValue, float tailValue, int stepValue, |
|||
float rotationValue) { |
|||
return new Container( |
|||
constraints: new BoxConstraints( |
|||
minWidth: _ProgressIndicatorContants._kMinCircularProgressIndicatorSize, |
|||
minHeight: _ProgressIndicatorContants._kMinCircularProgressIndicatorSize |
|||
), |
|||
child: new CustomPaint( |
|||
painter: new _CircularProgressIndicatorPainter( |
|||
valueColor: this.widget._getValueColor(context), |
|||
value: this.widget.value, |
|||
headValue: headValue, |
|||
tailValue: tailValue, |
|||
stepValue: stepValue, |
|||
rotationValue: rotationValue, |
|||
strokeWidth: this.widget.strokeWidth |
|||
) |
|||
) |
|||
); |
|||
} |
|||
|
|||
protected Widget _buildAnimation() { |
|||
return new AnimatedBuilder( |
|||
animation: this._controller, |
|||
builder: (BuildContext context, Widget child) => { |
|||
return this._buildIndicator( |
|||
context, |
|||
_ProgressIndicatorContants._kStrokeHeadTween.evaluate(this._controller), |
|||
_ProgressIndicatorContants._kStrokeTailTween.evaluate(this._controller), |
|||
_ProgressIndicatorContants._kStepTween.evaluate(this._controller), |
|||
_ProgressIndicatorContants._kRotationTween.evaluate(this._controller) |
|||
); |
|||
} |
|||
); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
if (this.widget.value != null) { |
|||
return this._buildIndicator(context, 0.0f, 0.0f, 0, 0.0f); |
|||
} |
|||
|
|||
return this._buildAnimation(); |
|||
} |
|||
} |
|||
|
|||
class _RefreshProgressIndicatorPainter : _CircularProgressIndicatorPainter { |
|||
public _RefreshProgressIndicatorPainter( |
|||
Color valueColor = null, |
|||
float? value = null, |
|||
float? headValue = null, |
|||
float? tailValue = null, |
|||
int? stepValue = null, |
|||
float? rotationValue = null, |
|||
float? strokeWidth = null, |
|||
float? arrowheadScale = null |
|||
) : base( |
|||
valueColor: valueColor, |
|||
value: value, |
|||
headValue: headValue, |
|||
tailValue: tailValue, |
|||
stepValue: stepValue, |
|||
rotationValue: rotationValue, |
|||
strokeWidth: strokeWidth |
|||
) { |
|||
this.arrowheadScale = arrowheadScale; |
|||
} |
|||
|
|||
public readonly float? arrowheadScale; |
|||
|
|||
void paintArrowhead(Canvas canvas, Size size) { |
|||
// ux, uy: a unit vector whose direction parallels the base of the arrowhead.
|
|||
// (So ux, -uy points in the direction the arrowhead points.)
|
|||
float arcEnd = this.arcStart + this.arcSweep ?? 0.0f; |
|||
float ux = Mathf.Cos(arcEnd); |
|||
float uy = Mathf.Sin(arcEnd); |
|||
|
|||
D.assert(size.width == size.height); |
|||
float radius = size.width / 2.0f; |
|||
float? arrowheadPointX = radius + ux * radius + -uy * this.strokeWidth * 2.0f * this.arrowheadScale; |
|||
float? arrowheadPointY = radius + uy * radius + ux * this.strokeWidth * 2.0f * this.arrowheadScale; |
|||
float? arrowheadRadius = this.strokeWidth * 1.5f * this.arrowheadScale; |
|||
float? innerRadius = radius - arrowheadRadius; |
|||
float? outerRadius = radius + arrowheadRadius; |
|||
|
|||
Path path = new Path(); |
|||
path.moveTo(radius + ux * innerRadius ?? 0.0f, radius + uy * innerRadius ?? 0.0f); |
|||
path.lineTo(radius + ux * outerRadius ?? 0.0f, radius + uy * outerRadius ?? 0.0f); |
|||
path.lineTo(arrowheadPointX ?? 0.0f, arrowheadPointY ?? 0.0f); |
|||
path.close(); |
|||
Paint paint = new Paint(); |
|||
paint.color = this.valueColor; |
|||
paint.strokeWidth = this.strokeWidth ?? 0.0f; |
|||
paint.style = PaintingStyle.fill; |
|||
canvas.drawPath(path, paint); |
|||
} |
|||
|
|||
public override void paint(Canvas canvas, Size size) { |
|||
base.paint(canvas, size); |
|||
if (this.arrowheadScale > 0.0) { |
|||
this.paintArrowhead(canvas, size); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public class RefreshProgressIndicator : CircularProgressIndicator { |
|||
public RefreshProgressIndicator( |
|||
Key key = null, |
|||
float? value = null, |
|||
Color backgroundColor = null, |
|||
Animation<Color> valueColor = null, |
|||
float strokeWidth = 2.0f |
|||
) : base( |
|||
key: key, |
|||
value: value, |
|||
backgroundColor: backgroundColor, |
|||
valueColor: valueColor, |
|||
strokeWidth: strokeWidth |
|||
) { |
|||
} |
|||
|
|||
public override State createState() { |
|||
return new _RefreshProgressIndicatorState(); |
|||
} |
|||
} |
|||
|
|||
class _RefreshProgressIndicatorState : _CircularProgressIndicatorState { |
|||
const float _indicatorSize = 40.0f; |
|||
|
|||
public _RefreshProgressIndicatorState() { |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
if (this.widget.value != null) { |
|||
this._controller.setValue(this.widget.value / 10.0f ?? 0.0f); |
|||
} |
|||
else if (!this._controller.isAnimating) { |
|||
this._controller.repeat(); |
|||
} |
|||
|
|||
return this._buildAnimation(); |
|||
} |
|||
|
|||
Widget _buildIndicator(BuildContext context, float headValue, float tailValue, int stepValue, |
|||
float rotationValue) { |
|||
float arrowheadScale = |
|||
this.widget.value == null ? 0.0f : (this.widget.value * 2.0f).Value.clamp(0.0f, 1.0f); |
|||
return new Container( |
|||
width: _indicatorSize, |
|||
height: _indicatorSize, |
|||
margin: EdgeInsets.all(4.0f), |
|||
child: new Material( |
|||
type: MaterialType.circle, |
|||
color: this.widget.backgroundColor ?? Theme.of(context).canvasColor, |
|||
elevation: 2.0f, |
|||
child: new Padding( |
|||
padding: EdgeInsets.all(12.0f), |
|||
child: new CustomPaint( |
|||
painter: new _RefreshProgressIndicatorPainter( |
|||
valueColor: this.widget._getValueColor(context), |
|||
value: null, // Draw the indeterminate progress indicator.
|
|||
headValue: headValue, |
|||
tailValue: tailValue, |
|||
stepValue: stepValue, |
|||
rotationValue: rotationValue, |
|||
strokeWidth: this.widget.strokeWidth, |
|||
arrowheadScale: arrowheadScale |
|||
) |
|||
) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 42b0b0b180624c38b2dec573a232bd8a |
|||
timeCreated: 1552530632 |
|
|||
using System; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace Unity.UIWidgets.material { |
|||
public class TabBarTheme : Diagnosticable, IEquatable<TabBarTheme> { |
|||
public TabBarTheme( |
|||
Decoration indicator = null, |
|||
TabBarIndicatorSize? indicatorSize = null, |
|||
Color labelColor = null, |
|||
Color unselectedLabelColor = null) { |
|||
this.indicator = indicator; |
|||
this.indicatorSize = indicatorSize; |
|||
this.labelColor = labelColor; |
|||
this.unselectedLabelColor = unselectedLabelColor; |
|||
} |
|||
|
|||
public readonly Decoration indicator; |
|||
|
|||
public readonly TabBarIndicatorSize? indicatorSize; |
|||
|
|||
public readonly Color labelColor; |
|||
|
|||
public readonly Color unselectedLabelColor; |
|||
|
|||
public TabBarTheme copyWith( |
|||
Decoration indicator = null, |
|||
TabBarIndicatorSize? indicatorSize = null, |
|||
Color labelColor = null, |
|||
Color unselectedLabelColor = null |
|||
) { |
|||
return new TabBarTheme( |
|||
indicator: indicator ?? this.indicator, |
|||
indicatorSize: indicatorSize ?? this.indicatorSize, |
|||
labelColor: labelColor ?? this.labelColor, |
|||
unselectedLabelColor: unselectedLabelColor ?? this.unselectedLabelColor); |
|||
} |
|||
|
|||
public static TabBarTheme of(BuildContext context) { |
|||
return Theme.of(context).tabBarTheme; |
|||
} |
|||
|
|||
public static TabBarTheme lerp(TabBarTheme a, TabBarTheme b, float t) { |
|||
D.assert(a != null); |
|||
D.assert(b != null); |
|||
return new TabBarTheme( |
|||
indicator: Decoration.lerp(a.indicator, b.indicator, t), |
|||
indicatorSize: t < 0.5 ? a.indicatorSize : b.indicatorSize, |
|||
labelColor: Color.lerp(a.labelColor, b.labelColor, t), |
|||
unselectedLabelColor: Color.lerp(a.unselectedLabelColor, b.unselectedLabelColor, t) |
|||
); |
|||
} |
|||
|
|||
public override int GetHashCode() { |
|||
unchecked { |
|||
var hashCode = this.indicator != null ? this.indicator.GetHashCode() : 0; |
|||
hashCode = (hashCode * 397) ^ (this.indicatorSize != null ? this.indicatorSize.GetHashCode() : 0); |
|||
hashCode = (hashCode * 397) ^ (this.labelColor != null ? this.labelColor.GetHashCode() : 0); |
|||
hashCode = (hashCode * 397) ^ |
|||
(this.unselectedLabelColor != null ? this.unselectedLabelColor.GetHashCode() : 0); |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
|
|||
public bool Equals(TabBarTheme other) { |
|||
if (ReferenceEquals(null, other)) { |
|||
return false; |
|||
} |
|||
|
|||
if (ReferenceEquals(this, other)) { |
|||
return true; |
|||
} |
|||
|
|||
return other.indicator == this.indicator && |
|||
other.indicatorSize == this.indicatorSize && |
|||
other.labelColor == this.labelColor && |
|||
other.unselectedLabelColor == this.unselectedLabelColor; |
|||
} |
|||
|
|||
public override bool Equals(object obj) { |
|||
if (ReferenceEquals(null, obj)) { |
|||
return false; |
|||
} |
|||
|
|||
if (ReferenceEquals(this, obj)) { |
|||
return true; |
|||
} |
|||
|
|||
if (obj.GetType() != this.GetType()) { |
|||
return false; |
|||
} |
|||
|
|||
return this.Equals((TabBarTheme) obj); |
|||
} |
|||
|
|||
public static bool operator ==(TabBarTheme left, TabBarTheme right) { |
|||
return Equals(left, right); |
|||
} |
|||
|
|||
public static bool operator !=(TabBarTheme left, TabBarTheme right) { |
|||
return !Equals(left, right); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e5dde8f06134e4f07a597b48fa14a6eb |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using Unity.UIWidgets.animation; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.scheduler; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace Unity.UIWidgets.material { |
|||
public class TabController : ChangeNotifier { |
|||
public TabController( |
|||
int initialIndex = 0, |
|||
int? length = null, |
|||
TickerProvider vsync = null) { |
|||
D.assert(length != null && length >= 0); |
|||
D.assert(initialIndex >= 0 && (length == 0 || initialIndex < length)); |
|||
D.assert(vsync != null); |
|||
this.length = length.Value; |
|||
|
|||
this._index = initialIndex; |
|||
this._previousIndex = initialIndex; |
|||
this._animationController = length < 2 |
|||
? null |
|||
: new AnimationController( |
|||
value: initialIndex, |
|||
upperBound: length.Value - 1, |
|||
vsync: vsync); |
|||
} |
|||
|
|||
public Animation<float> animation { |
|||
get { return this._animationController?.view ?? Animations.kAlwaysCompleteAnimation; } |
|||
} |
|||
|
|||
readonly AnimationController _animationController; |
|||
|
|||
public readonly int length; |
|||
|
|||
void _changeIndex(int value, TimeSpan? duration = null, Curve curve = null) { |
|||
D.assert(value >= 0 && (value < this.length || this.length == 0)); |
|||
D.assert(duration == null ? curve == null : true); |
|||
D.assert(this._indexIsChangingCount >= 0); |
|||
|
|||
if (value == this._index || this.length < 2) { |
|||
return; |
|||
} |
|||
|
|||
this._previousIndex = this.index; |
|||
this._index = value; |
|||
if (duration != null) { |
|||
this._indexIsChangingCount++; |
|||
this.notifyListeners(); |
|||
this._animationController.animateTo( |
|||
this._index, duration: duration, curve: curve).whenCompleteOrCancel(() => { |
|||
this._indexIsChangingCount--; |
|||
this.notifyListeners(); |
|||
}); |
|||
} |
|||
else { |
|||
this._indexIsChangingCount++; |
|||
this._animationController.setValue(this._index); |
|||
this._indexIsChangingCount--; |
|||
this.notifyListeners(); |
|||
} |
|||
} |
|||
|
|||
public int index { |
|||
get { return this._index; } |
|||
set { this._changeIndex(value); } |
|||
} |
|||
|
|||
int _index; |
|||
|
|||
public int previousIndex { |
|||
get { return this._previousIndex; } |
|||
} |
|||
|
|||
int _previousIndex; |
|||
|
|||
public bool indexIsChanging { |
|||
get { return this._indexIsChangingCount != 0; } |
|||
} |
|||
|
|||
int _indexIsChangingCount = 0; |
|||
|
|||
public void animateTo(int value, TimeSpan? duration = null, Curve curve = null) { |
|||
duration = duration ?? Constants.kTabScrollDuration; |
|||
curve = curve ?? Curves.ease; |
|||
this._changeIndex(value, duration: duration, curve: curve); |
|||
} |
|||
|
|||
public float offset { |
|||
get { return this.length > 1 ? this._animationController.value - this._index : 0.0f; } |
|||
set { |
|||
D.assert(this.length > 1); |
|||
D.assert(value >= -1.0f && value <= 1.0f); |
|||
D.assert(!this.indexIsChanging); |
|||
if (value == this.offset) { |
|||
return; |
|||
} |
|||
|
|||
this._animationController.setValue(value + this._index); |
|||
} |
|||
} |
|||
|
|||
public override void dispose() { |
|||
this._animationController?.dispose(); |
|||
base.dispose(); |
|||
} |
|||
} |
|||
|
|||
class _TabControllerScope : InheritedWidget { |
|||
public _TabControllerScope( |
|||
Key key = null, |
|||
TabController controller = null, |
|||
bool? enabled = null, |
|||
Widget child = null |
|||
) : base(key: key, child: child) { |
|||
this.controller = controller; |
|||
this.enabled = enabled; |
|||
} |
|||
|
|||
public readonly TabController controller; |
|||
|
|||
public readonly bool? enabled; |
|||
|
|||
public override bool updateShouldNotify(InheritedWidget old) { |
|||
_TabControllerScope _old = (_TabControllerScope) old; |
|||
return this.enabled != _old.enabled |
|||
|| this.controller != _old.controller; |
|||
} |
|||
} |
|||
|
|||
class DefaultTabController : StatefulWidget { |
|||
public DefaultTabController( |
|||
Key key = null, |
|||
int? length = null, |
|||
int initialIndex = 0, |
|||
Widget child = null |
|||
) : base(key: key) { |
|||
D.assert(length != null); |
|||
D.assert(child != null); |
|||
this.length = length; |
|||
this.initialIndex = initialIndex; |
|||
this.child = child; |
|||
} |
|||
|
|||
public readonly int? length; |
|||
|
|||
public readonly int initialIndex; |
|||
|
|||
public readonly Widget child; |
|||
|
|||
public static TabController of(BuildContext context) { |
|||
_TabControllerScope scope = |
|||
(_TabControllerScope) context.inheritFromWidgetOfExactType(typeof(_TabControllerScope)); |
|||
return scope?.controller; |
|||
} |
|||
|
|||
public override State createState() { |
|||
return new _DefaultTabControllerState(); |
|||
} |
|||
} |
|||
|
|||
class _DefaultTabControllerState : SingleTickerProviderStateMixin<DefaultTabController> { |
|||
TabController _controller; |
|||
|
|||
public override void initState() { |
|||
base.initState(); |
|||
this._controller = new TabController( |
|||
vsync: this, |
|||
length: this.widget.length, |
|||
initialIndex: this.widget.initialIndex |
|||
); |
|||
} |
|||
|
|||
public override void dispose() { |
|||
this._controller.dispose(); |
|||
base.dispose(); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new _TabControllerScope( |
|||
controller: this._controller, |
|||
enabled: TickerMode.of(context), |
|||
child: this.widget.child |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f6cf1d3578f4a4effa3b0988822e3b2e |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.ui; |
|||
|
|||
namespace Unity.UIWidgets.material { |
|||
public class UnderlineTabIndicator : Decoration { |
|||
public UnderlineTabIndicator( |
|||
BorderSide borderSide = null, |
|||
EdgeInsets insets = null) { |
|||
borderSide = borderSide ?? new BorderSide(width: 2.0f, color: Colors.white); |
|||
insets = insets ?? EdgeInsets.zero; |
|||
this.borderSide = borderSide; |
|||
this.insets = insets; |
|||
} |
|||
|
|||
public readonly BorderSide borderSide; |
|||
|
|||
public readonly EdgeInsets insets; |
|||
|
|||
public override Decoration lerpFrom(Decoration a, float t) { |
|||
if (a is UnderlineTabIndicator) { |
|||
UnderlineTabIndicator _a = (UnderlineTabIndicator) a; |
|||
return new UnderlineTabIndicator( |
|||
borderSide: BorderSide.lerp(_a.borderSide, this.borderSide, t), |
|||
insets: EdgeInsets.lerp(_a.insets, this.insets, t) |
|||
); |
|||
} |
|||
|
|||
return base.lerpFrom(a, t); |
|||
} |
|||
|
|||
public override Decoration lerpTo(Decoration b, float t) { |
|||
if (b is UnderlineTabIndicator) { |
|||
UnderlineTabIndicator _b = (UnderlineTabIndicator) b; |
|||
return new UnderlineTabIndicator( |
|||
borderSide: BorderSide.lerp(this.borderSide, _b.borderSide, t), |
|||
insets: EdgeInsets.lerp(this.insets, _b.insets, t) |
|||
); |
|||
} |
|||
|
|||
return base.lerpTo(b, t); |
|||
} |
|||
|
|||
|
|||
public override BoxPainter createBoxPainter(VoidCallback onChanged) { |
|||
return new _UnderlinePainter(this, onChanged); |
|||
} |
|||
} |
|||
|
|||
|
|||
class _UnderlinePainter : BoxPainter { |
|||
public _UnderlinePainter( |
|||
UnderlineTabIndicator decoration = null, |
|||
VoidCallback onChanged = null |
|||
) : base(onChanged: onChanged) { |
|||
D.assert(decoration != null); |
|||
this.decoration = decoration; |
|||
} |
|||
|
|||
public readonly UnderlineTabIndicator decoration; |
|||
|
|||
public BorderSide borderSide { |
|||
get { return this.decoration.borderSide; } |
|||
} |
|||
|
|||
public EdgeInsets insets { |
|||
get { return this.decoration.insets; } |
|||
} |
|||
|
|||
Rect _indicatorRectFor(Rect rect) { |
|||
D.assert(rect != null); |
|||
Rect indicator = this.insets.deflateRect(rect); |
|||
return Rect.fromLTWH( |
|||
indicator.left, |
|||
indicator.bottom - this.borderSide.width, |
|||
indicator.width, |
|||
this.borderSide.width); |
|||
} |
|||
|
|||
public override void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) { |
|||
D.assert(configuration != null); |
|||
D.assert(configuration.size != null); |
|||
Rect rect = offset & configuration.size; |
|||
Rect indicator = this._indicatorRectFor(rect).deflate(this.borderSide.width / 2.0f); |
|||
Paint paint = this.borderSide.toPaint(); |
|||
paint.strokeCap = StrokeCap.square; |
|||
canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 07582ba5529ac435f98f69a5eea30831 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
1001
Runtime/material/tabs.cs
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
|
|||
fileFormatVersion: 2 |
|||
guid: 27058ed141c4f4476a7db65aacfda644 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.ui; |
|||
|
|||
namespace Unity.UIWidgets.widgets { |
|||
class Form : StatefulWidget { |
|||
public Form( |
|||
Key key = null, |
|||
Widget child = null, |
|||
bool autovalidate = false, |
|||
WillPopCallback onWillPop = null, |
|||
VoidCallback onChanged = null |
|||
) : base(key: key) { |
|||
D.assert(child != null); |
|||
this.child = child; |
|||
this.autovalidate = autovalidate; |
|||
this.onWillPop = onWillPop; |
|||
this.onChanged = onChanged; |
|||
} |
|||
|
|||
public static FormState of(BuildContext context) { |
|||
_FormScope scope = (_FormScope) context.inheritFromWidgetOfExactType(typeof(_FormScope)); |
|||
return scope?._formState; |
|||
} |
|||
|
|||
public readonly Widget child; |
|||
|
|||
public readonly bool autovalidate; |
|||
|
|||
public readonly WillPopCallback onWillPop; |
|||
|
|||
public readonly VoidCallback onChanged; |
|||
|
|||
public override State createState() { |
|||
return new FormState(); |
|||
} |
|||
} |
|||
|
|||
class FormState : State<Form> { |
|||
int _generation = 0; |
|||
public readonly HashSet<FormFieldState<dynamic>> _fields = new HashSet<FormFieldState<dynamic>>(); |
|||
|
|||
public FormState() { |
|||
} |
|||
|
|||
public void _fieldDidChange() { |
|||
if (this.widget.onChanged != null) { |
|||
this.widget.onChanged(); |
|||
} |
|||
|
|||
this._forceRebuild(); |
|||
} |
|||
|
|||
void _forceRebuild() { |
|||
this.setState(() => { ++this._generation; }); |
|||
} |
|||
|
|||
public void _register(FormFieldState<dynamic> field) { |
|||
this._fields.Add(field); |
|||
} |
|||
|
|||
public void _unregister(FormFieldState<dynamic> field) { |
|||
this._fields.Remove(field); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
if (this.widget.autovalidate) { |
|||
this._validate(); |
|||
} |
|||
|
|||
return new WillPopScope( |
|||
onWillPop: this.widget.onWillPop, |
|||
child: new _FormScope( |
|||
formState: this, |
|||
generation: this._generation, |
|||
child: this.widget.child |
|||
) |
|||
); |
|||
} |
|||
|
|||
void save() { |
|||
foreach (FormFieldState<dynamic> field in this._fields) { |
|||
field.save(); |
|||
} |
|||
} |
|||
|
|||
void reset() { |
|||
foreach (FormFieldState<dynamic> field in this._fields) { |
|||
field.reset(); |
|||
} |
|||
|
|||
this._fieldDidChange(); |
|||
} |
|||
|
|||
bool validate() { |
|||
this._forceRebuild(); |
|||
return this._validate(); |
|||
} |
|||
|
|||
bool _validate() { |
|||
bool hasError = false; |
|||
foreach (FormFieldState<dynamic> field in this._fields) { |
|||
hasError = !field.validate() || hasError; |
|||
} |
|||
|
|||
return !hasError; |
|||
} |
|||
} |
|||
|
|||
class _FormScope : InheritedWidget { |
|||
public _FormScope( |
|||
Key key = null, |
|||
Widget child = null, |
|||
FormState formState = null, |
|||
int? generation = null |
|||
) : |
|||
base(key: key, child: child) { |
|||
this._formState = formState; |
|||
this._generation = generation; |
|||
} |
|||
|
|||
public readonly FormState _formState; |
|||
|
|||
public readonly int? _generation; |
|||
|
|||
public Form form { |
|||
get { return this._formState.widget; } |
|||
} |
|||
|
|||
public override bool updateShouldNotify(InheritedWidget _old) { |
|||
_FormScope old = _old as _FormScope; |
|||
return this._generation != old._generation; |
|||
} |
|||
} |
|||
|
|||
public delegate string FormFieldValidator<T>(T value); |
|||
|
|||
public delegate void FormFieldSetter<T>(T newValue); |
|||
|
|||
public delegate Widget FormFieldBuilder<T>(FormFieldState<T> field) where T : class; |
|||
|
|||
public class FormField<T> : StatefulWidget where T : class { |
|||
public FormField( |
|||
Key key = null, |
|||
FormFieldBuilder<T> builder = null, |
|||
FormFieldSetter<T> onSaved = null, |
|||
FormFieldValidator<T> validator = null, |
|||
T initialValue = null, |
|||
bool autovalidate = false, |
|||
bool enabled = true |
|||
) : base(key: key) { |
|||
D.assert(builder != null); |
|||
} |
|||
|
|||
public readonly FormFieldSetter<T> onSaved; |
|||
|
|||
public readonly FormFieldValidator<T> validator; |
|||
|
|||
public readonly FormFieldBuilder<T> builder; |
|||
|
|||
public readonly T initialValue; |
|||
|
|||
public readonly bool autovalidate; |
|||
|
|||
public readonly bool enabled; |
|||
|
|||
public override State createState() { |
|||
return new FormFieldState<T>(); |
|||
} |
|||
} |
|||
|
|||
public class FormFieldState<T> : State<FormField<T>> where T : class { |
|||
T _value; |
|||
string _errorText; |
|||
|
|||
public T value { |
|||
get { return this._value; } |
|||
} |
|||
|
|||
public string errorText { |
|||
get { return this._errorText; } |
|||
} |
|||
|
|||
public bool hasError { |
|||
get { return this._errorText != null; } |
|||
} |
|||
|
|||
public void save() { |
|||
if (this.widget.onSaved != null) { |
|||
this.widget.onSaved(this.value); |
|||
} |
|||
} |
|||
|
|||
public void reset() { |
|||
this.setState(() => { |
|||
this._value = this.widget.initialValue; |
|||
this._errorText = null; |
|||
}); |
|||
} |
|||
|
|||
public bool validate() { |
|||
this.setState(() => { this._validate(); }); |
|||
return !this.hasError; |
|||
} |
|||
|
|||
bool _validate() { |
|||
if (this.widget.validator != null) { |
|||
this._errorText = this.widget.validator(this._value); |
|||
} |
|||
|
|||
return !this.hasError; |
|||
} |
|||
|
|||
public virtual void didChange(T value) { |
|||
this.setState(() => { this._value = value; }); |
|||
Form.of(this.context)?._fieldDidChange(); |
|||
} |
|||
|
|||
protected void setValue(T value) { |
|||
this._value = value; |
|||
} |
|||
|
|||
public override void initState() { |
|||
base.initState(); |
|||
this._value = this.widget.initialValue; |
|||
} |
|||
|
|||
public override void deactivate() { |
|||
Form.of(this.context)?._unregister(this as FormFieldState<dynamic>); |
|||
base.deactivate(); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
if (this.widget.autovalidate && this.widget.enabled) { |
|||
this._validate(); |
|||
} |
|||
|
|||
Form.of(context)?._register(this as FormFieldState<dynamic>); |
|||
return this.widget.builder(this); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 3ce8dad5676b40ec862b142dd03b9f64 |
|||
timeCreated: 1552545243 |
|
|||
fileFormatVersion: 2 |
|||
guid: 47c0eb9f305f0431a9a06da1a3f19875 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using Unity.UIWidgets.foundation; |
|||
|
|||
namespace Unity.UIWidgets.widgets { |
|||
class WillPopScope : StatefulWidget { |
|||
public WillPopScope( |
|||
Key key = null, |
|||
Widget child = null, |
|||
WillPopCallback onWillPop = null |
|||
) : base(key: key) { |
|||
D.assert(child != null); |
|||
this.onWillPop = onWillPop; |
|||
this.child = child; |
|||
} |
|||
|
|||
public readonly Widget child; |
|||
|
|||
public readonly WillPopCallback onWillPop; |
|||
|
|||
public override State createState() { |
|||
return new _WillPopScopeState(); |
|||
} |
|||
} |
|||
|
|||
class _WillPopScopeState : State<WillPopScope> { |
|||
ModalRoute _route; |
|||
|
|||
public _WillPopScopeState() { |
|||
} |
|||
|
|||
public override void didChangeDependencies() { |
|||
base.didChangeDependencies(); |
|||
if (this.widget.onWillPop != null) { |
|||
this._route?.removeScopedWillPopCallback(this.widget.onWillPop); |
|||
} |
|||
|
|||
this._route = ModalRoute.of(this.context); |
|||
if (this.widget.onWillPop != null) { |
|||
this._route?.addScopedWillPopCallback(this.widget.onWillPop); |
|||
} |
|||
} |
|||
|
|||
public override void didUpdateWidget(StatefulWidget _oldWidget) { |
|||
base.didUpdateWidget(_oldWidget); |
|||
D.assert(this._route == ModalRoute.of(this.context)); |
|||
WillPopScope oldWidget = _oldWidget as WillPopScope; |
|||
if (this.widget.onWillPop != oldWidget.onWillPop && this._route != null) { |
|||
if (oldWidget.onWillPop != null) { |
|||
this._route.removeScopedWillPopCallback(oldWidget.onWillPop); |
|||
} |
|||
|
|||
if (this.widget.onWillPop != null) { |
|||
this._route.addScopedWillPopCallback(this.widget.onWillPop); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public override void dispose() { |
|||
if (this.widget.onWillPop != null) { |
|||
this._route?.removeScopedWillPopCallback(this.widget.onWillPop); |
|||
} |
|||
|
|||
base.dispose(); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return this.widget.child; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 624e6292cdfc4b43ac439df81ae8efee |
|||
timeCreated: 1552547854 |
|
|||
fileFormatVersion: 2 |
|||
guid: 60513bb9173ce47ad8d4c7840bcfe836 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue