Yuncong Zhang
6 年前
当前提交
c2febf37
共有 36 个文件被更改,包括 3348 次插入 和 72 次删除
-
6Runtime/Plugins/platform/ios/UIWidgetsViewController.mm
-
8Runtime/engine/UIWidgetsPanel.cs
-
32Runtime/foundation/debug.cs
-
40Runtime/gestures/binding.cs
-
6Runtime/gestures/converter.cs
-
7Runtime/gestures/monodrag.cs
-
38Runtime/gestures/recognizer.cs
-
26Runtime/material/list_tile.cs
-
18Runtime/material/theme_data.cs
-
12Runtime/rendering/image.cs
-
18Runtime/widgets/binding.cs
-
92Samples/UIWidgetsGallery/gallery/demos.cs
-
1001Runtime/material/chip.cs
-
3Runtime/material/chip.cs.meta
-
298Runtime/material/chip_theme.cs
-
3Runtime/material/chip_theme.cs.meta
-
132Runtime/material/circle_avatar.cs
-
3Runtime/material/circle_avatar.cs.meta
-
3Samples/UIWidgetsGallery/demo/animation.meta
-
15Samples/UIWidgetsGallery/demo/animation_demo.cs
-
3Samples/UIWidgetsGallery/demo/animation_demo.cs.meta
-
322Samples/UIWidgetsGallery/demo/material/chip_demo.cs
-
3Samples/UIWidgetsGallery/demo/material/chip_demo.cs.meta
-
42Samples/UIWidgetsGallery/demo/material/modal_bottom_sheet_demo.cs
-
3Samples/UIWidgetsGallery/demo/material/modal_bottom_sheet_demo.cs.meta
-
102Samples/UIWidgetsGallery/demo/material/persistent_bottom_sheet_demo.cs
-
3Samples/UIWidgetsGallery/demo/material/persistent_bottom_sheet_demo.cs.meta
-
184Samples/UIWidgetsGallery/demo/material/tabs_fab_demo.cs
-
3Samples/UIWidgetsGallery/demo/material/tabs_fab_demo.cs.meta
-
3Samples/UIWidgetsGallery/demo/animation/home.cs.meta
-
615Samples/UIWidgetsGallery/demo/animation/home.cs
-
201Samples/UIWidgetsGallery/demo/animation/sections.cs
-
3Samples/UIWidgetsGallery/demo/animation/sections.cs.meta
-
169Samples/UIWidgetsGallery/demo/animation/widgets.cs
-
3Samples/UIWidgetsGallery/demo/animation/widgets.cs.meta
1001
Runtime/material/chip.cs
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
|
|||
fileFormatVersion: 2 |
|||
guid: d4ca6b86209d4615b9aba98d6d112673 |
|||
timeCreated: 1555477997 |
|
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.service; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using TextStyle = Unity.UIWidgets.painting.TextStyle; |
|||
|
|||
namespace Unity.UIWidgets.material { |
|||
public class ChipTheme : InheritedWidget { |
|||
public ChipTheme( |
|||
Key key = null, |
|||
ChipThemeData data = null, |
|||
Widget child = null |
|||
) : base(key: key, child: child) { |
|||
D.assert(child != null); |
|||
D.assert(data != null); |
|||
this.data = data; |
|||
} |
|||
|
|||
public readonly ChipThemeData data; |
|||
|
|||
public static ChipThemeData of(BuildContext context) { |
|||
ChipTheme inheritedTheme = (ChipTheme) context.inheritFromWidgetOfExactType(typeof(ChipTheme)); |
|||
return inheritedTheme?.data ?? Theme.of(context).chipTheme; |
|||
} |
|||
|
|||
public override bool updateShouldNotify(InheritedWidget _oldWidget) { |
|||
ChipTheme oldWidget = _oldWidget as ChipTheme; |
|||
return this.data != oldWidget.data; |
|||
} |
|||
} |
|||
|
|||
public class ChipThemeData : Diagnosticable { |
|||
public ChipThemeData( |
|||
Color backgroundColor = null, |
|||
Color deleteIconColor = null, |
|||
Color disabledColor = null, |
|||
Color selectedColor = null, |
|||
Color secondarySelectedColor = null, |
|||
EdgeInsets labelPadding = null, |
|||
EdgeInsets padding = null, |
|||
ShapeBorder shape = null, |
|||
TextStyle labelStyle = null, |
|||
TextStyle secondaryLabelStyle = null, |
|||
Brightness? brightness = null, |
|||
float? elevation = null, |
|||
float? pressElevation = null |
|||
) { |
|||
D.assert(backgroundColor != null); |
|||
D.assert(disabledColor != null); |
|||
D.assert(selectedColor != null); |
|||
D.assert(secondarySelectedColor != null); |
|||
D.assert(labelPadding != null); |
|||
D.assert(padding != null); |
|||
D.assert(shape != null); |
|||
D.assert(labelStyle != null); |
|||
D.assert(secondaryLabelStyle != null); |
|||
D.assert(brightness != null); |
|||
this.backgroundColor = backgroundColor; |
|||
this.deleteIconColor = deleteIconColor; |
|||
this.disabledColor = disabledColor; |
|||
this.selectedColor = selectedColor; |
|||
this.secondarySelectedColor = secondarySelectedColor; |
|||
this.labelPadding = labelPadding; |
|||
this.padding = padding; |
|||
this.shape = shape; |
|||
this.labelStyle = labelStyle; |
|||
this.secondaryLabelStyle = secondaryLabelStyle; |
|||
this.brightness = brightness; |
|||
this.elevation = elevation; |
|||
this.pressElevation = pressElevation; |
|||
} |
|||
|
|||
public static ChipThemeData fromDefaults( |
|||
Brightness? brightness = null, |
|||
Color primaryColor = null, |
|||
Color secondaryColor = null, |
|||
TextStyle labelStyle = null |
|||
) { |
|||
D.assert(primaryColor != null || brightness != null, |
|||
"One of primaryColor or brightness must be specified"); |
|||
D.assert(primaryColor == null || brightness == null, |
|||
"Only one of primaryColor or brightness may be specified"); |
|||
D.assert(secondaryColor != null); |
|||
D.assert(labelStyle != null); |
|||
|
|||
if (primaryColor != null) { |
|||
brightness = ThemeData.estimateBrightnessForColor(primaryColor); |
|||
} |
|||
|
|||
const int backgroundAlpha = 0x1f; // 12%
|
|||
const int deleteIconAlpha = 0xde; // 87%
|
|||
const int disabledAlpha = 0x0c; // 38% * 12% = 5%
|
|||
const int selectAlpha = 0x3d; // 12% + 12% = 24%
|
|||
const int textLabelAlpha = 0xde; // 87%
|
|||
ShapeBorder shape = new StadiumBorder(); |
|||
EdgeInsets labelPadding = EdgeInsets.symmetric(horizontal: 8.0f); |
|||
EdgeInsets padding = EdgeInsets.all(4.0f); |
|||
|
|||
primaryColor = primaryColor ?? (brightness == Brightness.light ? Colors.black : Colors.white); |
|||
Color backgroundColor = primaryColor.withAlpha(backgroundAlpha); |
|||
Color deleteIconColor = primaryColor.withAlpha(deleteIconAlpha); |
|||
Color disabledColor = primaryColor.withAlpha(disabledAlpha); |
|||
Color selectedColor = primaryColor.withAlpha(selectAlpha); |
|||
Color secondarySelectedColor = secondaryColor.withAlpha(selectAlpha); |
|||
TextStyle secondaryLabelStyle = labelStyle.copyWith( |
|||
color: secondaryColor.withAlpha(textLabelAlpha) |
|||
); |
|||
labelStyle = labelStyle.copyWith(color: primaryColor.withAlpha(textLabelAlpha)); |
|||
|
|||
return new ChipThemeData( |
|||
backgroundColor: backgroundColor, |
|||
deleteIconColor: deleteIconColor, |
|||
disabledColor: disabledColor, |
|||
selectedColor: selectedColor, |
|||
secondarySelectedColor: secondarySelectedColor, |
|||
labelPadding: labelPadding, |
|||
padding: padding, |
|||
shape: shape, |
|||
labelStyle: labelStyle, |
|||
secondaryLabelStyle: secondaryLabelStyle, |
|||
brightness: brightness |
|||
); |
|||
} |
|||
|
|||
public readonly Color backgroundColor; |
|||
|
|||
public readonly Color deleteIconColor; |
|||
|
|||
public readonly Color disabledColor; |
|||
|
|||
public readonly Color selectedColor; |
|||
|
|||
public readonly Color secondarySelectedColor; |
|||
|
|||
public readonly EdgeInsets labelPadding; |
|||
|
|||
public readonly EdgeInsets padding; |
|||
|
|||
public readonly ShapeBorder shape; |
|||
|
|||
public readonly TextStyle labelStyle; |
|||
|
|||
public readonly TextStyle secondaryLabelStyle; |
|||
|
|||
public readonly Brightness? brightness; |
|||
|
|||
public readonly float? elevation; |
|||
|
|||
public readonly float? pressElevation; |
|||
|
|||
public ChipThemeData copyWith( |
|||
Color backgroundColor = null, |
|||
Color deleteIconColor = null, |
|||
Color disabledColor = null, |
|||
Color selectedColor = null, |
|||
Color secondarySelectedColor = null, |
|||
EdgeInsets labelPadding = null, |
|||
EdgeInsets padding = null, |
|||
ShapeBorder shape = null, |
|||
TextStyle labelStyle = null, |
|||
TextStyle secondaryLabelStyle = null, |
|||
Brightness? brightness = null, |
|||
float? elevation = null, |
|||
float? pressElevation = null |
|||
) { |
|||
return new ChipThemeData( |
|||
backgroundColor: backgroundColor ?? this.backgroundColor, |
|||
deleteIconColor: deleteIconColor ?? this.deleteIconColor, |
|||
disabledColor: disabledColor ?? this.disabledColor, |
|||
selectedColor: selectedColor ?? this.selectedColor, |
|||
secondarySelectedColor: secondarySelectedColor ?? this.secondarySelectedColor, |
|||
labelPadding: labelPadding ?? this.labelPadding, |
|||
padding: padding ?? this.padding, |
|||
shape: shape ?? this.shape, |
|||
labelStyle: labelStyle ?? this.labelStyle, |
|||
secondaryLabelStyle: secondaryLabelStyle ?? this.secondaryLabelStyle, |
|||
brightness: brightness ?? this.brightness, |
|||
elevation: elevation ?? this.elevation, |
|||
pressElevation: pressElevation ?? this.pressElevation |
|||
); |
|||
} |
|||
|
|||
public static ChipThemeData lerp(ChipThemeData a, ChipThemeData b, float t) { |
|||
D.assert(t != null); |
|||
if (a == null && b == null) { |
|||
return null; |
|||
} |
|||
|
|||
return new ChipThemeData( |
|||
backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t), |
|||
deleteIconColor: Color.lerp(a?.deleteIconColor, b?.deleteIconColor, t), |
|||
disabledColor: Color.lerp(a?.disabledColor, b?.disabledColor, t), |
|||
selectedColor: Color.lerp(a?.selectedColor, b?.selectedColor, t), |
|||
secondarySelectedColor: Color.lerp(a?.secondarySelectedColor, b?.secondarySelectedColor, t), |
|||
labelPadding: EdgeInsets.lerp(a?.labelPadding, b?.labelPadding, t), |
|||
padding: EdgeInsets.lerp(a?.padding, b?.padding, t), |
|||
shape: ShapeBorder.lerp(a?.shape, b?.shape, t), |
|||
labelStyle: TextStyle.lerp(a?.labelStyle, b?.labelStyle, t), |
|||
secondaryLabelStyle: TextStyle.lerp(a?.secondaryLabelStyle, b?.secondaryLabelStyle, t), |
|||
brightness: t < 0.5f ? a?.brightness ?? Brightness.light : b?.brightness ?? Brightness.light, |
|||
elevation: MathUtils.lerpFloat(a?.elevation ?? 0.0f, b?.elevation ?? 0.0f, t), |
|||
pressElevation: MathUtils.lerpFloat(a?.pressElevation ?? 0.0f, b?.pressElevation ?? 0.0f, t) |
|||
); |
|||
} |
|||
|
|||
public override int GetHashCode() { |
|||
var hashCode = this.backgroundColor.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.deleteIconColor.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.disabledColor.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.selectedColor.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.secondarySelectedColor.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.labelPadding.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.padding.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.shape.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.labelStyle.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.secondaryLabelStyle.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.brightness.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.elevation.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.pressElevation.GetHashCode(); |
|||
return hashCode; |
|||
} |
|||
|
|||
public bool Equals(ChipThemeData other) { |
|||
return other.backgroundColor == this.backgroundColor |
|||
&& other.deleteIconColor == this.deleteIconColor |
|||
&& other.disabledColor == this.disabledColor |
|||
&& other.selectedColor == this.selectedColor |
|||
&& other.secondarySelectedColor == this.secondarySelectedColor |
|||
&& other.labelPadding == this.labelPadding |
|||
&& other.padding == this.padding |
|||
&& other.shape == this.shape |
|||
&& other.labelStyle == this.labelStyle |
|||
&& other.secondaryLabelStyle == this.secondaryLabelStyle |
|||
&& other.brightness == this.brightness |
|||
&& other.elevation == this.elevation |
|||
&& other.pressElevation == this.pressElevation; |
|||
} |
|||
|
|||
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((ChipThemeData) obj); |
|||
} |
|||
|
|||
public static bool operator ==(ChipThemeData left, ChipThemeData right) { |
|||
return Equals(left, right); |
|||
} |
|||
|
|||
public static bool operator !=(ChipThemeData left, ChipThemeData right) { |
|||
return !Equals(left, right); |
|||
} |
|||
|
|||
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
|||
base.debugFillProperties(properties); |
|||
ThemeData defaultTheme = ThemeData.fallback(); |
|||
ChipThemeData defaultData = fromDefaults( |
|||
secondaryColor: defaultTheme.primaryColor, |
|||
brightness: defaultTheme.brightness, |
|||
labelStyle: defaultTheme.textTheme.body2 |
|||
); |
|||
properties.add(new DiagnosticsProperty<Color>("backgroundColor", this.backgroundColor, |
|||
defaultValue: defaultData.backgroundColor)); |
|||
properties.add(new DiagnosticsProperty<Color>("deleteIconColor", this.deleteIconColor, |
|||
defaultValue: defaultData.deleteIconColor)); |
|||
properties.add(new DiagnosticsProperty<Color>("disabledColor", this.disabledColor, |
|||
defaultValue: defaultData.disabledColor)); |
|||
properties.add(new DiagnosticsProperty<Color>("selectedColor", this.selectedColor, |
|||
defaultValue: defaultData.selectedColor)); |
|||
properties.add(new DiagnosticsProperty<Color>("secondarySelectedColor", this.secondarySelectedColor, |
|||
defaultValue: defaultData.secondarySelectedColor)); |
|||
properties.add(new DiagnosticsProperty<EdgeInsets>("labelPadding", this.labelPadding, |
|||
defaultValue: defaultData.labelPadding)); |
|||
properties.add( |
|||
new DiagnosticsProperty<EdgeInsets>("padding", this.padding, defaultValue: defaultData.padding)); |
|||
properties.add(new DiagnosticsProperty<ShapeBorder>("shape", this.shape, defaultValue: defaultData.shape)); |
|||
properties.add(new DiagnosticsProperty<TextStyle>("labelStyle", this.labelStyle, |
|||
defaultValue: defaultData.labelStyle)); |
|||
properties.add(new DiagnosticsProperty<TextStyle>("secondaryLabelStyle", this.secondaryLabelStyle, |
|||
defaultValue: defaultData.secondaryLabelStyle)); |
|||
properties.add(new EnumProperty<Brightness?>("brightness", this.brightness, |
|||
defaultValue: defaultData.brightness)); |
|||
properties.add(new FloatProperty("elevation", this.elevation, defaultValue: defaultData.elevation)); |
|||
properties.add(new FloatProperty("pressElevation", this.pressElevation, |
|||
defaultValue: defaultData.pressElevation)); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 4d46bfb5d5bb492e92f07114849df905 |
|||
timeCreated: 1556165564 |
|
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.service; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using TextStyle = Unity.UIWidgets.painting.TextStyle; |
|||
|
|||
namespace UIWidgetsGallery.gallery { |
|||
public class CircleAvatar : StatelessWidget { |
|||
public CircleAvatar( |
|||
Key key = null, |
|||
Widget child = null, |
|||
Color backgroundColor = null, |
|||
ImageProvider backgroundImage = null, |
|||
Color foregroundColor = null, |
|||
float? radius = null, |
|||
float? minRadius = null, |
|||
float? maxRadius = null |
|||
) : base(key: key) { |
|||
D.assert(radius == null || (minRadius == null && maxRadius == null)); |
|||
this.child = child; |
|||
this.backgroundColor = backgroundColor; |
|||
this.backgroundImage = backgroundImage; |
|||
this.foregroundColor = foregroundColor; |
|||
this.radius = radius; |
|||
this.minRadius = minRadius; |
|||
this.maxRadius = maxRadius; |
|||
} |
|||
|
|||
public readonly Widget child; |
|||
|
|||
public readonly Color backgroundColor; |
|||
|
|||
public readonly Color foregroundColor; |
|||
|
|||
public readonly ImageProvider backgroundImage; |
|||
|
|||
public readonly float? radius; |
|||
|
|||
public readonly float? minRadius; |
|||
|
|||
public readonly float? maxRadius; |
|||
|
|||
const float _defaultRadius = 20.0f; |
|||
|
|||
const float _defaultMinRadius = 0.0f; |
|||
|
|||
const float _defaultMaxRadius = float.PositiveInfinity; |
|||
|
|||
float _minDiameter { |
|||
get { |
|||
if (this.radius == null && this.minRadius == null && this.maxRadius == null) { |
|||
return _defaultRadius * 2.0f; |
|||
} |
|||
|
|||
return 2.0f * (this.radius ?? this.minRadius ?? _defaultMinRadius); |
|||
} |
|||
} |
|||
|
|||
float _maxDiameter { |
|||
get { |
|||
if (this.radius == null && this.minRadius == null && this.maxRadius == null) { |
|||
return _defaultRadius * 2.0f; |
|||
} |
|||
|
|||
return 2.0f * (this.radius ?? this.maxRadius ?? _defaultMaxRadius); |
|||
} |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
D.assert(WidgetsD.debugCheckHasMediaQuery(context)); |
|||
ThemeData theme = Theme.of(context); |
|||
TextStyle textStyle = theme.primaryTextTheme.subhead.copyWith(color: this.foregroundColor); |
|||
Color effectiveBackgroundColor = this.backgroundColor; |
|||
if (effectiveBackgroundColor == null) { |
|||
switch (ThemeData.estimateBrightnessForColor(textStyle.color)) { |
|||
case Brightness.dark: |
|||
effectiveBackgroundColor = theme.primaryColorLight; |
|||
break; |
|||
case Brightness.light: |
|||
effectiveBackgroundColor = theme.primaryColorDark; |
|||
break; |
|||
} |
|||
} |
|||
else if (this.foregroundColor == null) { |
|||
switch (ThemeData.estimateBrightnessForColor(this.backgroundColor)) { |
|||
case Brightness.dark: |
|||
textStyle = textStyle.copyWith(color: theme.primaryColorLight); |
|||
break; |
|||
case Brightness.light: |
|||
textStyle = textStyle.copyWith(color: theme.primaryColorDark); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
float minDiameter = this._minDiameter; |
|||
float maxDiameter = this._maxDiameter; |
|||
return new AnimatedContainer( |
|||
constraints: new BoxConstraints( |
|||
minHeight: minDiameter, |
|||
minWidth: minDiameter, |
|||
maxWidth: maxDiameter, |
|||
maxHeight: maxDiameter |
|||
), |
|||
duration: Constants.kThemeChangeDuration, |
|||
decoration: new BoxDecoration( |
|||
color: effectiveBackgroundColor, |
|||
image: this.backgroundImage != null |
|||
? new DecorationImage(image: this.backgroundImage, fit: BoxFit.cover) |
|||
: null, |
|||
shape: BoxShape.circle |
|||
), |
|||
child: this.child == null |
|||
? null |
|||
: new Center( |
|||
child: new MediaQuery( |
|||
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0f), |
|||
child: new IconTheme( |
|||
data: theme.iconTheme.copyWith(color: textStyle.color), |
|||
child: new DefaultTextStyle( |
|||
style: textStyle, |
|||
child: this.child |
|||
) |
|||
) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 32591e65e11049cab124c86bc8fe573c |
|||
timeCreated: 1556169017 |
|
|||
fileFormatVersion: 2 |
|||
guid: 4861503ddfc74b9ba36f159521c79b65 |
|||
timeCreated: 1554970886 |
|
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace UIWidgetsGallery.gallery { |
|||
public class AnimationDemo : StatelessWidget { |
|||
public AnimationDemo(Key key = null) : base(key: key) { |
|||
} |
|||
|
|||
public const string routeName = "/animation"; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new AnimationDemoHome(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f13faff4d2b84ce0935236f3b953849f |
|||
timeCreated: 1554969121 |
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace UIWidgetsGallery.gallery { |
|||
class ChipDemoUtils { |
|||
public static readonly List<string> _defaultMaterials = new List<string> { |
|||
"poker", |
|||
"tortilla", |
|||
"fish and", |
|||
"micro", |
|||
"wood" |
|||
}; |
|||
|
|||
public static readonly List<string> _defaultActions = new List<string> { |
|||
"flake", |
|||
"cut", |
|||
"fragment", |
|||
"splinter", |
|||
"nick", |
|||
"fry", |
|||
"solder", |
|||
"cash in", |
|||
"eat" |
|||
}; |
|||
|
|||
public static readonly Dictionary<string, string> _results = new Dictionary<string, string> { |
|||
{"flake", "flaking"}, |
|||
{"cut", "cutting"}, |
|||
{"fragment", "fragmenting"}, |
|||
{"splinter", "splintering"}, |
|||
{"nick", "nicking"}, |
|||
{"fry", "frying"}, |
|||
{"solder", "soldering"}, |
|||
{"cash in", "cashing in"}, |
|||
{"eat", "eating"} |
|||
}; |
|||
|
|||
public static readonly List<string> _defaultTools = new List<string> { |
|||
"hammer", |
|||
"chisel", |
|||
"fryer", |
|||
"fabricator", |
|||
"customer" |
|||
}; |
|||
|
|||
public static readonly Dictionary<string, string> _avatars = new Dictionary<string, string> { |
|||
{"hammer", "people/square/ali"}, |
|||
{"chisel", "people/square/sandra"}, |
|||
{"fryer", "people/square/trevor"}, |
|||
{"fabricator", "people/square/stella"}, |
|||
{"customer", "people/square/peter"} |
|||
}; |
|||
|
|||
public static readonly Dictionary<string, HashSet<string>> _toolActions = |
|||
new Dictionary<string, HashSet<string>> { |
|||
{"hammer", new HashSet<string>(new List<string> {"flake", "fragment", "splinter"})}, |
|||
{"chisel", new HashSet<string>(new List<string> {"flake", "nick", "splinter"})}, |
|||
{"fryer", new HashSet<string>(new List<string> {"fry"})}, |
|||
{"fabricator", new HashSet<string>(new List<string> {"solder"})}, |
|||
{"customer", new HashSet<string>(new List<string> {"cash in", "eat"})} |
|||
}; |
|||
|
|||
public static readonly Dictionary<string, HashSet<string>> _materialActions = |
|||
new Dictionary<string, HashSet<string>> { |
|||
{"poker", new HashSet<string>(new List<string> {"cash in"})}, |
|||
{"tortilla", new HashSet<string>(new List<string> {"fry", "eat"})}, |
|||
{"fish and", new HashSet<string>(new List<string> {"fry", "eat"})}, |
|||
{"micro", new HashSet<string>(new List<string> {"solder", "fragment"})}, |
|||
{"wood", new HashSet<string>(new List<string> {"flake", "cut", "splinter", "nick"})} |
|||
}; |
|||
} |
|||
|
|||
|
|||
class _ChipsTile : StatelessWidget { |
|||
public _ChipsTile( |
|||
Key key = null, |
|||
string label = null, |
|||
List<Widget> children = null |
|||
) : base(key: key) { |
|||
this.label = label; |
|||
this.children = children; |
|||
} |
|||
|
|||
public readonly string label; |
|||
public readonly List<Widget> children; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
List<Widget> cardChildren = new List<Widget> { |
|||
new Container( |
|||
padding: EdgeInsets.only(top: 16.0f, bottom: 4.0f), |
|||
alignment: Alignment.center, |
|||
child: new Text(this.label, textAlign: TextAlign.left) |
|||
) |
|||
}; |
|||
if (this.children.isNotEmpty()) { |
|||
cardChildren.Add(new Wrap( |
|||
children: this.children.Select<Widget, Widget>((Widget chip) => { |
|||
return new Padding( |
|||
padding: EdgeInsets.all(2.0f), |
|||
child: chip |
|||
); |
|||
}).ToList())); |
|||
} |
|||
else { |
|||
TextStyle textStyle = Theme.of(context).textTheme.caption.copyWith(fontStyle: FontStyle.italic); |
|||
cardChildren.Add( |
|||
new Container( |
|||
alignment: Alignment.center, |
|||
constraints: new BoxConstraints(minWidth: 48.0f, minHeight: 48.0f), |
|||
padding: EdgeInsets.all(8.0f), |
|||
child: new Text("None", style: textStyle) |
|||
) |
|||
); |
|||
} |
|||
|
|||
return new Card( |
|||
child: new Column( |
|||
mainAxisSize: MainAxisSize.min, |
|||
children: cardChildren |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
public class ChipDemo : StatefulWidget { |
|||
public const string routeName = "/material/chip"; |
|||
|
|||
public override State createState() { |
|||
return new _ChipDemoState(); |
|||
} |
|||
} |
|||
|
|||
class _ChipDemoState : State<ChipDemo> { |
|||
public _ChipDemoState() { |
|||
this._reset(); |
|||
} |
|||
|
|||
HashSet<string> _materials = new HashSet<string>(new List<string> { }); |
|||
string _selectedMaterial = ""; |
|||
string _selectedAction = ""; |
|||
HashSet<string> _tools = new HashSet<string>(new List<string> { }); |
|||
HashSet<string> _selectedTools = new HashSet<string>(new List<string> { }); |
|||
HashSet<string> _actions = new HashSet<string>(new List<string> { }); |
|||
bool _showShapeBorder = false; |
|||
|
|||
void _reset() { |
|||
this._materials.Clear(); |
|||
this._materials.UnionWith(ChipDemoUtils._defaultMaterials); |
|||
this._actions.Clear(); |
|||
this._actions.UnionWith(ChipDemoUtils._defaultActions); |
|||
this._tools.Clear(); |
|||
this._tools.UnionWith(ChipDemoUtils._defaultTools); |
|||
this._selectedMaterial = ""; |
|||
this._selectedAction = ""; |
|||
this._selectedTools.Clear(); |
|||
} |
|||
|
|||
void _removeMaterial(string name) { |
|||
this._materials.Remove(name); |
|||
if (this._selectedMaterial == name) { |
|||
this._selectedMaterial = ""; |
|||
} |
|||
} |
|||
|
|||
void _removeTool(string name) { |
|||
this._tools.Remove(name); |
|||
this._selectedTools.Remove(name); |
|||
} |
|||
|
|||
string _capitalize(string name) { |
|||
D.assert(name != null && name.isNotEmpty()); |
|||
return name.Substring(0, 1).ToUpper() + name.Substring(1); |
|||
} |
|||
|
|||
Color _nameToColor(string name) { |
|||
D.assert(name.Length > 1); |
|||
int hash = name.GetHashCode() & 0xffff; |
|||
float hue = (360.0f * hash / (1 << 15)) % 360.0f; |
|||
return HSVColor.fromAHSV(1.0f, hue, 0.4f, 0.90f).toColor(); |
|||
} |
|||
|
|||
AssetImage _nameToAvatar(string name) { |
|||
D.assert(ChipDemoUtils._avatars.ContainsKey(name)); |
|||
return new AssetImage( |
|||
ChipDemoUtils._avatars[name] |
|||
); |
|||
} |
|||
|
|||
string _createResult() { |
|||
if (this._selectedAction.isEmpty()) { |
|||
return ""; |
|||
} |
|||
|
|||
return this._capitalize(ChipDemoUtils._results[this._selectedAction]) + "!"; |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
List<Widget> chips = this._materials.Select<string, Widget>((string name) => { |
|||
return new Chip( |
|||
key: Key.key(name), |
|||
backgroundColor: this._nameToColor(name), |
|||
label: new Text(this._capitalize(name)), |
|||
onDeleted: () => { this.setState(() => { this._removeMaterial(name); }); } |
|||
); |
|||
}).ToList(); |
|||
|
|||
List<Widget> inputChips = this._tools.Select<string, Widget>((string name) => { |
|||
return new InputChip( |
|||
key: ValueKey<string>.key(name), |
|||
avatar: new CircleAvatar( |
|||
backgroundImage: this._nameToAvatar(name) |
|||
), |
|||
label: new Text(this._capitalize(name)), |
|||
onDeleted: () => { this.setState(() => { this._removeTool(name); }); }); |
|||
}).ToList(); |
|||
|
|||
List<Widget> choiceChips = this._materials.Select<string, Widget>((string name) => { |
|||
return new ChoiceChip( |
|||
key: ValueKey<string>.key(name), |
|||
backgroundColor: this._nameToColor(name), |
|||
label: new Text(this._capitalize(name)), |
|||
selected: this._selectedMaterial == name, |
|||
onSelected: (bool value) => { |
|||
this.setState(() => { this._selectedMaterial = value ? name : ""; }); |
|||
} |
|||
); |
|||
}).ToList(); |
|||
|
|||
List<Widget> filterChips = ChipDemoUtils._defaultTools.Select<string, Widget>((string name) => { |
|||
return new FilterChip( |
|||
key: ValueKey<string>.key(name), |
|||
label: new Text(this._capitalize(name)), |
|||
selected: this._tools.Contains(name) ? this._selectedTools.Contains(name) : false, |
|||
onSelected: !this._tools.Contains(name) |
|||
? (ValueChanged<bool>) null |
|||
: (bool value) => { |
|||
this.setState(() => { |
|||
if (!value) { |
|||
this._selectedTools.Remove(name); |
|||
} |
|||
else { |
|||
this._selectedTools.Add(name); |
|||
} |
|||
}); |
|||
} |
|||
); |
|||
}).ToList(); |
|||
|
|||
HashSet<string> allowedActions = new HashSet<string>(new List<string> { }); |
|||
if (this._selectedMaterial != null && this._selectedMaterial.isNotEmpty()) { |
|||
foreach (string tool in this._selectedTools) { |
|||
allowedActions.UnionWith(ChipDemoUtils._toolActions[tool]); |
|||
} |
|||
|
|||
allowedActions = |
|||
new HashSet<string>( |
|||
allowedActions.Intersect(ChipDemoUtils._materialActions[this._selectedMaterial])); |
|||
} |
|||
|
|||
List<Widget> actionChips = allowedActions.Select<string, Widget>((string name) => { |
|||
return new ActionChip( |
|||
label: new Text(this._capitalize(name)), |
|||
onPressed: () => { this.setState(() => { this._selectedAction = name; }); } |
|||
); |
|||
}).ToList(); |
|||
|
|||
ThemeData theme = Theme.of(context); |
|||
List<Widget> tiles = new List<Widget> { |
|||
new SizedBox(height: 8.0f, width: 0.0f), |
|||
new _ChipsTile(label: "Available Materials (Chip)", children: chips), |
|||
new _ChipsTile(label: "Available Tools (InputChip)", children: inputChips), |
|||
new _ChipsTile(label: "Choose a Material (ChoiceChip)", children: choiceChips), |
|||
new _ChipsTile(label: "Choose Tools (FilterChip)", children: filterChips), |
|||
new _ChipsTile(label: "Perform Allowed Action (ActionChip)", children: actionChips), |
|||
new Divider(), |
|||
new Padding( |
|||
padding: EdgeInsets.all(8.0f), |
|||
child: new Center( |
|||
child: new Text(this._createResult(), |
|||
style: theme.textTheme.title |
|||
) |
|||
) |
|||
) |
|||
}; |
|||
|
|||
return new Scaffold( |
|||
appBar: new AppBar( |
|||
title: new Text("Chips"), |
|||
actions: new List<Widget> { |
|||
new MaterialDemoDocumentationButton(ChipDemo.routeName), |
|||
new IconButton( |
|||
onPressed: () => { |
|||
this.setState(() => { this._showShapeBorder = !this._showShapeBorder; }); |
|||
}, |
|||
icon: new Icon(Icons.vignette) |
|||
) |
|||
} |
|||
), |
|||
body: new ChipTheme( |
|||
data: this._showShapeBorder |
|||
? theme.chipTheme.copyWith( |
|||
shape: new BeveledRectangleBorder( |
|||
side: new BorderSide(width: 0.66f, style: BorderStyle.solid, color: Colors.grey), |
|||
borderRadius: BorderRadius.circular(10.0f) |
|||
)) |
|||
: theme.chipTheme, |
|||
child: new ListView(children: tiles) |
|||
), |
|||
floatingActionButton: new FloatingActionButton( |
|||
onPressed: () => this.setState(this._reset), |
|||
child: new Icon(Icons.refresh) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: c65920c8c4b64c709b62586d0bde9579 |
|||
timeCreated: 1555411023 |
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace UIWidgetsGallery.gallery { |
|||
public class ModalBottomSheetDemo : StatelessWidget { |
|||
public const string routeName = "/material/modal-bottom-sheet"; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new Scaffold( |
|||
appBar: new AppBar( |
|||
title: new Text("Modal bottom sheet"), |
|||
actions: new List<Widget> {new MaterialDemoDocumentationButton(routeName)} |
|||
), |
|||
body: new Center( |
|||
child: new RaisedButton( |
|||
child: new Text("SHOW BOTTOM SHEET"), |
|||
onPressed: () => { |
|||
BottomSheetUtils.showModalBottomSheet<object>(context: context, |
|||
builder: (BuildContext _context) => { |
|||
return new Container( |
|||
child: new Padding( |
|||
padding: EdgeInsets.all(32.0f), |
|||
child: new Text("This is the modal bottom sheet. Tap anywhere to dismiss.", |
|||
textAlign: TextAlign.center, |
|||
style: new TextStyle( |
|||
color: Theme.of(_context).accentColor, |
|||
fontSize: 24.0f |
|||
) |
|||
) |
|||
) |
|||
); |
|||
}); |
|||
} |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 3c47b9e1a46e47858145acbe84590d05 |
|||
timeCreated: 1555059325 |
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using DialogUtils = Unity.UIWidgets.material.DialogUtils; |
|||
|
|||
namespace UIWidgetsGallery.gallery { |
|||
public class PersistentBottomSheetDemo : StatefulWidget { |
|||
public const string routeName = "/material/persistent-bottom-sheet"; |
|||
|
|||
public override State createState() { |
|||
return new _PersistentBottomSheetDemoState(); |
|||
} |
|||
} |
|||
|
|||
class _PersistentBottomSheetDemoState : State<PersistentBottomSheetDemo> { |
|||
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>.key(); |
|||
|
|||
VoidCallback _showBottomSheetCallback; |
|||
|
|||
public override void initState() { |
|||
base.initState(); |
|||
this._showBottomSheetCallback = this._showBottomSheet; |
|||
} |
|||
|
|||
void _showBottomSheet() { |
|||
this.setState(() => { |
|||
// disable the button
|
|||
this._showBottomSheetCallback = null; |
|||
}); |
|||
this._scaffoldKey.currentState.showBottomSheet((BuildContext context) => { |
|||
ThemeData themeData = Theme.of(this.context); |
|||
return new Container( |
|||
decoration: new BoxDecoration( |
|||
border: new Border(top: new BorderSide(color: themeData.disabledColor)) |
|||
), |
|||
child: new Padding( |
|||
padding: EdgeInsets.all(32.0f), |
|||
child: new Text("This is a Material persistent bottom sheet. Drag downwards to dismiss it.", |
|||
textAlign: TextAlign.center, |
|||
style: new TextStyle( |
|||
color: themeData.accentColor, |
|||
fontSize: 24.0f |
|||
) |
|||
) |
|||
) |
|||
); |
|||
}) |
|||
.closed.Then((value) => { |
|||
if (this.mounted) { |
|||
this.setState(() => { |
|||
// re-enable the button
|
|||
this._showBottomSheetCallback = this._showBottomSheet; |
|||
}); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
void _showMessage() { |
|||
DialogUtils.showDialog( |
|||
context: this.context, |
|||
builder: (BuildContext context) => { |
|||
return new AlertDialog( |
|||
content: new Text("You tapped the floating action button."), |
|||
actions: new List<Widget> { |
|||
new FlatButton( |
|||
onPressed: () => { Navigator.pop(context); }, |
|||
child: new Text("OK") |
|||
) |
|||
} |
|||
); |
|||
} |
|||
); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new Scaffold( |
|||
key: this._scaffoldKey, |
|||
appBar: new AppBar( |
|||
title: new Text("Persistent bottom sheet"), |
|||
actions: new List<Widget> { |
|||
new MaterialDemoDocumentationButton(PersistentBottomSheetDemo.routeName) |
|||
} |
|||
), |
|||
floatingActionButton: new FloatingActionButton( |
|||
onPressed: this._showMessage, |
|||
backgroundColor: Colors.redAccent, |
|||
child: new Icon( |
|||
Icons.add |
|||
) |
|||
), |
|||
body: new Center( |
|||
child: new RaisedButton( |
|||
onPressed: this._showBottomSheetCallback, |
|||
child: new Text("SHOW BOTTOM SHEET") |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: afb410d95c524a18b8761713f1335427 |
|||
timeCreated: 1555059936 |
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace UIWidgetsGallery.gallery { |
|||
class TabsFabDemoUtils { |
|||
public const string _explanatoryText = |
|||
"When the Scaffold's floating action button changes, the new button fades and " + |
|||
"turns into view. In this demo, changing tabs can cause the app to be rebuilt " + |
|||
"with a FloatingActionButton that the Scaffold distinguishes from the others " + |
|||
"by its key."; |
|||
|
|||
public static readonly List<_Page> _allPages = new List<_Page> { |
|||
new _Page(label: "Blue", colors: Colors.indigo, icon: Icons.add), |
|||
new _Page(label: "Eco", colors: Colors.green, icon: Icons.create), |
|||
new _Page(label: "No"), |
|||
new _Page(label: "Teal", colors: Colors.teal, icon: Icons.add), |
|||
new _Page(label: "Red", colors: Colors.red, icon: Icons.create) |
|||
}; |
|||
} |
|||
|
|||
class _Page { |
|||
public _Page( |
|||
string label, |
|||
MaterialColor colors = null, |
|||
IconData icon = null |
|||
) { |
|||
this.label = label; |
|||
this.colors = colors; |
|||
this.icon = icon; |
|||
} |
|||
|
|||
public readonly string label; |
|||
public readonly MaterialColor colors; |
|||
public readonly IconData icon; |
|||
|
|||
public Color labelColor { |
|||
get { return this.colors != null ? this.colors.shade300 : Colors.grey.shade300; } |
|||
} |
|||
|
|||
public bool fabDefined { |
|||
get { return this.colors != null && this.icon != null; } |
|||
} |
|||
|
|||
public Color fabColor { |
|||
get { return this.colors.shade400; } |
|||
} |
|||
|
|||
public Icon fabIcon { |
|||
get { return new Icon(this.icon); } |
|||
} |
|||
|
|||
public Key fabKey { |
|||
get { return new ValueKey<Color>(this.fabColor); } |
|||
} |
|||
} |
|||
|
|||
|
|||
public class TabsFabDemo : StatefulWidget { |
|||
public const string routeName = "/material/tabs-fab"; |
|||
|
|||
public override State createState() { |
|||
return new _TabsFabDemoState(); |
|||
} |
|||
} |
|||
|
|||
class _TabsFabDemoState : SingleTickerProviderStateMixin<TabsFabDemo> { |
|||
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>.key(); |
|||
|
|||
TabController _controller; |
|||
_Page _selectedPage; |
|||
bool _extendedButtons = false; |
|||
|
|||
public override void initState() { |
|||
base.initState(); |
|||
this._controller = new TabController(vsync: this, length: TabsFabDemoUtils._allPages.Count); |
|||
this._controller.addListener(this._handleTabSelection); |
|||
this._selectedPage = TabsFabDemoUtils._allPages[0]; |
|||
} |
|||
|
|||
public override void dispose() { |
|||
this._controller.dispose(); |
|||
base.dispose(); |
|||
} |
|||
|
|||
void _handleTabSelection() { |
|||
this.setState(() => { this._selectedPage = TabsFabDemoUtils._allPages[this._controller.index]; }); |
|||
} |
|||
|
|||
void _showExplanatoryText() { |
|||
this._scaffoldKey.currentState.showBottomSheet((BuildContext context) => { |
|||
return new Container( |
|||
decoration: new BoxDecoration( |
|||
border: new Border(top: new BorderSide(color: Theme.of(this.context).dividerColor)) |
|||
), |
|||
child: new Padding( |
|||
padding: EdgeInsets.all(32.0f), |
|||
child: new Text(TabsFabDemoUtils._explanatoryText, |
|||
style: Theme.of(this.context).textTheme.subhead) |
|||
) |
|||
); |
|||
}); |
|||
} |
|||
|
|||
Widget buildTabView(_Page page) { |
|||
return new Builder( |
|||
builder: (BuildContext context) => { |
|||
return new Container( |
|||
key: new ValueKey<string>(page.label), |
|||
padding: EdgeInsets.fromLTRB(48.0f, 48.0f, 48.0f, 96.0f), |
|||
child: new Card( |
|||
child: new Center( |
|||
child: new Text(page.label, |
|||
style: new TextStyle( |
|||
color: page.labelColor, |
|||
fontSize: 32.0f |
|||
), |
|||
textAlign: TextAlign.center |
|||
) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
); |
|||
} |
|||
|
|||
Widget buildFloatingActionButton(_Page page) { |
|||
if (!page.fabDefined) { |
|||
return null; |
|||
} |
|||
|
|||
if (this._extendedButtons) { |
|||
return FloatingActionButton.extended( |
|||
key: new ValueKey<Key>(page.fabKey), |
|||
tooltip: "Show explanation", |
|||
backgroundColor: page.fabColor, |
|||
icon: page.fabIcon, |
|||
label: new Text(page.label.ToUpper()), |
|||
onPressed: this._showExplanatoryText |
|||
); |
|||
} |
|||
|
|||
return new FloatingActionButton( |
|||
key: page.fabKey, |
|||
tooltip: "Show explanation", |
|||
backgroundColor: page.fabColor, |
|||
child: page.fabIcon, |
|||
onPressed: this._showExplanatoryText |
|||
); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new Scaffold( |
|||
key: this._scaffoldKey, |
|||
appBar: new AppBar( |
|||
title: new Text("FAB per tab"), |
|||
bottom: new TabBar( |
|||
controller: this._controller, |
|||
tabs: TabsFabDemoUtils._allPages |
|||
.Select<_Page, Widget>((_Page page) => new Tab(text: page.label.ToUpper())).ToList() |
|||
), |
|||
actions: new List<Widget> { |
|||
new MaterialDemoDocumentationButton(TabsFabDemo.routeName), |
|||
new IconButton( |
|||
icon: new Icon(Icons.sentiment_very_satisfied), |
|||
onPressed: () => { |
|||
this.setState(() => { this._extendedButtons = !this._extendedButtons; }); |
|||
} |
|||
) |
|||
} |
|||
), |
|||
floatingActionButton: this.buildFloatingActionButton(this._selectedPage), |
|||
body: new TabBarView( |
|||
controller: this._controller, |
|||
children: TabsFabDemoUtils._allPages.Select<_Page, Widget>(this.buildTabView).ToList() |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 7c2dcb794cc84a458f028f3751cf08a7 |
|||
timeCreated: 1555060923 |
|
|||
fileFormatVersion: 2 |
|||
guid: 628b4648bdda4c8d8c8fc6778c874067 |
|||
timeCreated: 1554970915 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Unity.UIWidgets.animation; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.gestures; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.physics; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using UnityEngine; |
|||
using Color = Unity.UIWidgets.ui.Color; |
|||
using Rect = Unity.UIWidgets.ui.Rect; |
|||
|
|||
namespace UIWidgetsGallery.gallery { |
|||
class AnimationHomeUtils { |
|||
public static readonly Color _kAppBackgroundColor = new Color(0xFF353662); |
|||
public static readonly TimeSpan _kScrollDuration = new TimeSpan(0, 0, 0, 0, 400); |
|||
public static readonly Curve _kScrollCurve = Curves.fastOutSlowIn; |
|||
public const float _kAppBarMinHeight = 90.0f; |
|||
public const float _kAppBarMidHeight = 256.0f; |
|||
} |
|||
|
|||
class _RenderStatusBarPaddingSliver : RenderSliver { |
|||
public _RenderStatusBarPaddingSliver( |
|||
float? maxHeight = null, |
|||
float? scrollFactor = null |
|||
) { |
|||
D.assert(maxHeight >= 0.0f); |
|||
D.assert(scrollFactor >= 1.0f); |
|||
this._maxHeight = maxHeight; |
|||
this._scrollFactor = scrollFactor; |
|||
} |
|||
|
|||
public float? maxHeight { |
|||
get { return this._maxHeight; } |
|||
set { |
|||
D.assert(this.maxHeight >= 0.0f); |
|||
if (this._maxHeight == value) { |
|||
return; |
|||
} |
|||
|
|||
this._maxHeight = value; |
|||
this.markNeedsLayout(); |
|||
} |
|||
} |
|||
|
|||
float? _maxHeight; |
|||
|
|||
public float? scrollFactor { |
|||
get { return this._scrollFactor; } |
|||
set { |
|||
D.assert(this.scrollFactor >= 1.0f); |
|||
if (this._scrollFactor == value) { |
|||
return; |
|||
} |
|||
|
|||
this._scrollFactor = value; |
|||
this.markNeedsLayout(); |
|||
} |
|||
} |
|||
|
|||
float? _scrollFactor; |
|||
|
|||
protected override void performLayout() { |
|||
float? height = |
|||
(this.maxHeight - this.constraints.scrollOffset / this.scrollFactor)?.clamp(0.0f, |
|||
this.maxHeight ?? 0.0f); |
|||
this.geometry = new SliverGeometry( |
|||
paintExtent: Mathf.Min(height ?? 0.0f, this.constraints.remainingPaintExtent), |
|||
scrollExtent: this.maxHeight ?? 0.0f, |
|||
maxPaintExtent: this.maxHeight ?? 0.0f |
|||
); |
|||
} |
|||
} |
|||
|
|||
class _StatusBarPaddingSliver : SingleChildRenderObjectWidget { |
|||
public _StatusBarPaddingSliver( |
|||
Key key = null, |
|||
float? maxHeight = null, |
|||
float scrollFactor = 5.0f |
|||
) : base(key: key) { |
|||
D.assert(maxHeight != null && maxHeight >= 0.0f); |
|||
D.assert(scrollFactor != null && scrollFactor >= 1.0f); |
|||
this.maxHeight = maxHeight; |
|||
this.scrollFactor = scrollFactor; |
|||
} |
|||
|
|||
public readonly float? maxHeight; |
|||
public readonly float scrollFactor; |
|||
|
|||
public override RenderObject createRenderObject(BuildContext context) { |
|||
return new _RenderStatusBarPaddingSliver( |
|||
maxHeight: this.maxHeight, |
|||
scrollFactor: this.scrollFactor |
|||
); |
|||
} |
|||
|
|||
public override void updateRenderObject(BuildContext context, RenderObject _renderObject) { |
|||
_RenderStatusBarPaddingSliver renderObject = _renderObject as _RenderStatusBarPaddingSliver; |
|||
renderObject.maxHeight = this.maxHeight; |
|||
renderObject.scrollFactor = this.scrollFactor; |
|||
} |
|||
|
|||
public override void debugFillProperties(DiagnosticPropertiesBuilder description) { |
|||
base.debugFillProperties(description); |
|||
description.add(new FloatProperty("maxHeight", this.maxHeight)); |
|||
description.add(new FloatProperty("scrollFactor", this.scrollFactor)); |
|||
} |
|||
} |
|||
|
|||
class _SliverAppBarDelegate : SliverPersistentHeaderDelegate { |
|||
public _SliverAppBarDelegate( |
|||
float minHeight, |
|||
float maxHeight, |
|||
Widget child |
|||
) { |
|||
this.minHeight = minHeight; |
|||
this.maxHeight = maxHeight; |
|||
this.child = child; |
|||
} |
|||
|
|||
public readonly float minHeight; |
|||
public readonly float maxHeight; |
|||
public readonly Widget child; |
|||
|
|||
public override float? minExtent { |
|||
get { return this.minHeight; } |
|||
} |
|||
|
|||
public override float? maxExtent { |
|||
get { return Mathf.Max(this.maxHeight, this.minHeight); } |
|||
} |
|||
|
|||
public override Widget build(BuildContext context, float shrinkOffset, bool overlapsContent) { |
|||
return SizedBox.expand(child: this.child); |
|||
} |
|||
|
|||
public override bool shouldRebuild(SliverPersistentHeaderDelegate _oldDelegate) { |
|||
_SliverAppBarDelegate oldDelegate = _oldDelegate as _SliverAppBarDelegate; |
|||
return this.maxHeight != oldDelegate.maxHeight |
|||
|| this.minHeight != oldDelegate.minHeight |
|||
|| this.child != oldDelegate.child; |
|||
} |
|||
|
|||
public override string ToString() { |
|||
return "_SliverAppBarDelegate"; |
|||
} |
|||
} |
|||
|
|||
class _AllSectionsLayout : MultiChildLayoutDelegate { |
|||
public _AllSectionsLayout( |
|||
Alignment translation, |
|||
float tColumnToRow, |
|||
float tCollapsed, |
|||
int cardCount, |
|||
float selectedIndex |
|||
) { |
|||
this.translation = translation; |
|||
this.tColumnToRow = tColumnToRow; |
|||
this.tCollapsed = tCollapsed; |
|||
this.cardCount = cardCount; |
|||
this.selectedIndex = selectedIndex; |
|||
} |
|||
|
|||
public readonly Alignment translation; |
|||
public readonly float tColumnToRow; |
|||
public readonly float tCollapsed; |
|||
public readonly int cardCount; |
|||
public readonly float selectedIndex; |
|||
|
|||
Rect _interpolateRect(Rect begin, Rect end) { |
|||
return Rect.lerp(begin, end, this.tColumnToRow); |
|||
} |
|||
|
|||
Offset _interpolatePoint(Offset begin, Offset end) { |
|||
return Offset.lerp(begin, end, this.tColumnToRow); |
|||
} |
|||
|
|||
public override void performLayout(Size size) { |
|||
float columnCardX = size.width / 5.0f; |
|||
float columnCardWidth = size.width - columnCardX; |
|||
float columnCardHeight = size.height / this.cardCount; |
|||
float rowCardWidth = size.width; |
|||
Offset offset = this.translation.alongSize(size); |
|||
float columnCardY = 0.0f; |
|||
float rowCardX = -(this.selectedIndex * rowCardWidth); |
|||
|
|||
float columnTitleX = size.width / 10.0f; |
|||
float rowTitleWidth = size.width * ((1 + this.tCollapsed) / 2.25f); |
|||
float rowTitleX = (size.width - rowTitleWidth) / 2.0f - this.selectedIndex * rowTitleWidth; |
|||
|
|||
const float paddedSectionIndicatorWidth = AnimationWidgetsUtils.kSectionIndicatorWidth + 8.0f; |
|||
float rowIndicatorWidth = paddedSectionIndicatorWidth + |
|||
(1.0f - this.tCollapsed) * (rowTitleWidth - paddedSectionIndicatorWidth); |
|||
float rowIndicatorX = (size.width - rowIndicatorWidth) / 2.0f - this.selectedIndex * rowIndicatorWidth; |
|||
|
|||
for (int index = 0; index < this.cardCount; index++) { |
|||
Rect columnCardRect = Rect.fromLTWH(columnCardX, columnCardY, columnCardWidth, columnCardHeight); |
|||
Rect rowCardRect = Rect.fromLTWH(rowCardX, 0.0f, rowCardWidth, size.height); |
|||
Rect cardRect = this._interpolateRect(columnCardRect, rowCardRect).shift(offset); |
|||
string cardId = $"card{index}"; |
|||
if (this.hasChild(cardId)) { |
|||
this.layoutChild(cardId, BoxConstraints.tight(cardRect.size)); |
|||
this.positionChild(cardId, cardRect.topLeft); |
|||
} |
|||
|
|||
Size titleSize = this.layoutChild($"title{index}", BoxConstraints.loose(cardRect.size)); |
|||
float columnTitleY = columnCardRect.centerLeft.dy - titleSize.height / 2.0f; |
|||
float rowTitleY = rowCardRect.centerLeft.dy - titleSize.height / 2.0f; |
|||
float centeredRowTitleX = rowTitleX + (rowTitleWidth - titleSize.width) / 2.0f; |
|||
Offset columnTitleOrigin = new Offset(columnTitleX, columnTitleY); |
|||
Offset rowTitleOrigin = new Offset(centeredRowTitleX, rowTitleY); |
|||
Offset titleOrigin = this._interpolatePoint(columnTitleOrigin, rowTitleOrigin); |
|||
this.positionChild($"title{index}", titleOrigin + offset); |
|||
|
|||
Size indicatorSize = this.layoutChild($"indicator{index}", BoxConstraints.loose(cardRect.size)); |
|||
float columnIndicatorX = cardRect.centerRight.dx - indicatorSize.width - 16.0f; |
|||
float columnIndicatorY = cardRect.bottomRight.dy - indicatorSize.height - 16.0f; |
|||
Offset columnIndicatorOrigin = new Offset(columnIndicatorX, columnIndicatorY); |
|||
Rect titleRect = Rect.fromPoints(titleOrigin, titleSize.bottomRight(titleOrigin)); |
|||
float centeredRowIndicatorX = rowIndicatorX + (rowIndicatorWidth - indicatorSize.width) / 2.0f; |
|||
float rowIndicatorY = titleRect.bottomCenter.dy + 16.0f; |
|||
Offset rowIndicatorOrigin = new Offset(centeredRowIndicatorX, rowIndicatorY); |
|||
Offset indicatorOrigin = this._interpolatePoint(columnIndicatorOrigin, rowIndicatorOrigin); |
|||
this.positionChild($"indicator{index}", indicatorOrigin + offset); |
|||
|
|||
columnCardY += columnCardHeight; |
|||
rowCardX += rowCardWidth; |
|||
rowTitleX += rowTitleWidth; |
|||
rowIndicatorX += rowIndicatorWidth; |
|||
} |
|||
} |
|||
|
|||
public override bool shouldRelayout(MultiChildLayoutDelegate _oldDelegate) { |
|||
_AllSectionsLayout oldDelegate = _oldDelegate as _AllSectionsLayout; |
|||
return this.tColumnToRow != oldDelegate.tColumnToRow |
|||
|| this.cardCount != oldDelegate.cardCount |
|||
|| this.selectedIndex != oldDelegate.selectedIndex; |
|||
} |
|||
} |
|||
|
|||
class _AllSectionsView : AnimatedWidget { |
|||
public _AllSectionsView( |
|||
Key key = null, |
|||
int? sectionIndex = null, |
|||
List<Section> sections = null, |
|||
ValueNotifier<float> selectedIndex = null, |
|||
float? minHeight = null, |
|||
float? midHeight = null, |
|||
float? maxHeight = null, |
|||
List<Widget> sectionCards = null |
|||
) : base(key: key, listenable: selectedIndex) { |
|||
sectionCards = sectionCards ?? new List<Widget>(); |
|||
D.assert(sections != null); |
|||
D.assert(sectionCards.Count == sections.Count); |
|||
D.assert(sectionIndex >= 0 && sectionIndex < sections.Count); |
|||
D.assert(selectedIndex != null); |
|||
D.assert(selectedIndex.value >= 0.0f && (float) selectedIndex.value < sections.Count); |
|||
this.sectionIndex = sectionIndex; |
|||
this.sections = sections; |
|||
this.selectedIndex = selectedIndex; |
|||
this.minHeight = minHeight; |
|||
this.midHeight = midHeight; |
|||
this.maxHeight = maxHeight; |
|||
this.sectionCards = sectionCards; |
|||
} |
|||
|
|||
public readonly int? sectionIndex; |
|||
public readonly List<Section> sections; |
|||
public readonly ValueNotifier<float> selectedIndex; |
|||
public readonly float? minHeight; |
|||
public readonly float? midHeight; |
|||
public readonly float? maxHeight; |
|||
public readonly List<Widget> sectionCards; |
|||
|
|||
float _selectedIndexDelta(int index) { |
|||
return (index - this.selectedIndex.value).abs().clamp(0.0f, 1.0f); |
|||
} |
|||
|
|||
Widget _build(BuildContext context, BoxConstraints constraints) { |
|||
Size size = constraints.biggest; |
|||
|
|||
float? tColumnToRow = |
|||
1.0f - ((size.height - this.midHeight) / |
|||
(this.maxHeight - this.midHeight))?.clamp(0.0f, 1.0f); |
|||
|
|||
|
|||
float? tCollapsed = |
|||
1.0f - ((size.height - this.minHeight) / |
|||
(this.midHeight - this.minHeight))?.clamp(0.0f, 1.0f); |
|||
|
|||
float _indicatorOpacity(int index) { |
|||
return 1.0f - this._selectedIndexDelta(index) * 0.5f; |
|||
} |
|||
|
|||
float? _titleOpacity(int index) { |
|||
return 1.0f - this._selectedIndexDelta(index) * tColumnToRow * 0.5f; |
|||
} |
|||
|
|||
float? _titleScale(int index) { |
|||
return 1.0f - this._selectedIndexDelta(index) * tColumnToRow * 0.15f; |
|||
} |
|||
|
|||
List<Widget> children = new List<Widget>(this.sectionCards); |
|||
|
|||
for (int index = 0; index < this.sections.Count; index++) { |
|||
Section section = this.sections[index]; |
|||
children.Add(new LayoutId( |
|||
id: $"title{index}", |
|||
child: new SectionTitle( |
|||
section: section, |
|||
scale: _titleScale(index), |
|||
opacity: _titleOpacity(index) |
|||
) |
|||
)); |
|||
} |
|||
|
|||
for (int index = 0; index < this.sections.Count; index++) { |
|||
children.Add(new LayoutId( |
|||
id: $"indicator{index}", |
|||
child: new SectionIndicator( |
|||
opacity: _indicatorOpacity(index) |
|||
) |
|||
)); |
|||
} |
|||
|
|||
return new CustomMultiChildLayout( |
|||
layoutDelegate: new _AllSectionsLayout( |
|||
translation: new Alignment((this.selectedIndex.value - this.sectionIndex) * 2.0f - 1.0f ?? 0.0f, |
|||
-1.0f), |
|||
tColumnToRow: tColumnToRow ?? 0.0f, |
|||
tCollapsed: tCollapsed ?? 0.0f, |
|||
cardCount: this.sections.Count, |
|||
selectedIndex: this.selectedIndex.value |
|||
), |
|||
children: children |
|||
); |
|||
} |
|||
|
|||
protected override Widget build(BuildContext context) { |
|||
return new LayoutBuilder(builder: this._build); |
|||
} |
|||
} |
|||
|
|||
class _SnappingScrollPhysics : ClampingScrollPhysics { |
|||
public _SnappingScrollPhysics( |
|||
ScrollPhysics parent = null, |
|||
float? midScrollOffset = null |
|||
) : base(parent: parent) { |
|||
D.assert(midScrollOffset != null); |
|||
} |
|||
|
|||
public readonly float midScrollOffset; |
|||
|
|||
public override ScrollPhysics applyTo(ScrollPhysics ancestor) { |
|||
return new _SnappingScrollPhysics(parent: this.buildParent(ancestor), |
|||
midScrollOffset: this.midScrollOffset); |
|||
} |
|||
|
|||
Simulation _toMidScrollOffsetSimulation(float offset, float dragVelocity) { |
|||
float velocity = Mathf.Max(dragVelocity, this.minFlingVelocity); |
|||
return new ScrollSpringSimulation(this.spring, offset, this.midScrollOffset, velocity, |
|||
tolerance: this.tolerance); |
|||
} |
|||
|
|||
Simulation _toZeroScrollOffsetSimulation(float offset, float dragVelocity) { |
|||
float velocity = Mathf.Max(dragVelocity, this.minFlingVelocity); |
|||
return new ScrollSpringSimulation(this.spring, offset, 0.0f, velocity, tolerance: this.tolerance); |
|||
} |
|||
|
|||
public override Simulation createBallisticSimulation(ScrollMetrics position, float dragVelocity) { |
|||
Simulation simulation = base.createBallisticSimulation(position, dragVelocity); |
|||
float offset = position.pixels; |
|||
|
|||
if (simulation != null) { |
|||
float simulationEnd = simulation.x(float.PositiveInfinity); |
|||
if (simulationEnd >= this.midScrollOffset) { |
|||
return simulation; |
|||
} |
|||
|
|||
if (dragVelocity > 0.0f) { |
|||
return this._toMidScrollOffsetSimulation(offset, dragVelocity); |
|||
} |
|||
|
|||
if (dragVelocity < 0.0f) { |
|||
return this._toZeroScrollOffsetSimulation(offset, dragVelocity); |
|||
} |
|||
} |
|||
else { |
|||
float snapThreshold = this.midScrollOffset / 2.0f; |
|||
if (offset >= snapThreshold && offset < this.midScrollOffset) { |
|||
return this._toMidScrollOffsetSimulation(offset, dragVelocity); |
|||
} |
|||
|
|||
if (offset > 0.0f && offset < snapThreshold) { |
|||
return this._toZeroScrollOffsetSimulation(offset, dragVelocity); |
|||
} |
|||
} |
|||
|
|||
return simulation; |
|||
} |
|||
} |
|||
|
|||
public class AnimationDemoHome : StatefulWidget { |
|||
public AnimationDemoHome(Key key = null) : base(key: key) { |
|||
} |
|||
|
|||
public const string routeName = "/animation"; |
|||
|
|||
public override State createState() { |
|||
return new _AnimationDemoHomeState(); |
|||
} |
|||
} |
|||
|
|||
class _AnimationDemoHomeState : State<AnimationDemoHome> { |
|||
ScrollController _scrollController = new ScrollController(); |
|||
PageController _headingPageController = new PageController(); |
|||
PageController _detailsPageController = new PageController(); |
|||
ScrollPhysics _headingScrollPhysics = new NeverScrollableScrollPhysics(); |
|||
ValueNotifier<float> selectedIndex = new ValueNotifier<float>(0.0f); |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new Scaffold( |
|||
backgroundColor: AnimationHomeUtils._kAppBackgroundColor, |
|||
body: new Builder( |
|||
builder: this._buildBody |
|||
) |
|||
); |
|||
} |
|||
|
|||
void _handleBackButton(float midScrollOffset) { |
|||
if (this._scrollController.offset >= midScrollOffset) { |
|||
this._scrollController.animateTo(0.0f, curve: AnimationHomeUtils._kScrollCurve, |
|||
duration: AnimationHomeUtils._kScrollDuration); |
|||
} |
|||
else { |
|||
Navigator.maybePop(this.context); |
|||
} |
|||
} |
|||
|
|||
bool _handleScrollNotification(ScrollNotification notification, float midScrollOffset) { |
|||
if (notification.depth == 0 && notification is ScrollUpdateNotification) { |
|||
ScrollPhysics physics = this._scrollController.position.pixels >= midScrollOffset |
|||
? (ScrollPhysics) new PageScrollPhysics() |
|||
: new NeverScrollableScrollPhysics(); |
|||
if (physics != this._headingScrollPhysics) { |
|||
this.setState(() => { this._headingScrollPhysics = physics; }); |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
void _maybeScroll(float midScrollOffset, int pageIndex, float xOffset) { |
|||
if (this._scrollController.offset < midScrollOffset) { |
|||
this._headingPageController.animateToPage(pageIndex, curve: AnimationHomeUtils._kScrollCurve, |
|||
duration: AnimationHomeUtils._kScrollDuration); |
|||
this._scrollController.animateTo(midScrollOffset, curve: AnimationHomeUtils._kScrollCurve, |
|||
duration: AnimationHomeUtils._kScrollDuration); |
|||
} |
|||
else { |
|||
float centerX = this._headingPageController.position.viewportDimension / 2.0f; |
|||
int newPageIndex = xOffset > centerX ? pageIndex + 1 : pageIndex - 1; |
|||
this._headingPageController.animateToPage(newPageIndex, curve: AnimationHomeUtils._kScrollCurve, |
|||
duration: AnimationHomeUtils._kScrollDuration); |
|||
} |
|||
} |
|||
|
|||
bool _handlePageNotification(ScrollNotification notification, PageController leader, PageController follower) { |
|||
if (notification.depth == 0 && notification is ScrollUpdateNotification) { |
|||
this.selectedIndex.value = leader.page; |
|||
if (follower.page != leader.page) { |
|||
follower.position.jumpTo(leader.position.pixels); // ignore: deprecated_member_use
|
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
IEnumerable<Widget> _detailItemsFor(Section section) { |
|||
IEnumerable<Widget> detailItems = section.details.Select<SectionDetail, Widget>((SectionDetail detail) => { |
|||
return new SectionDetailView(detail: detail); |
|||
}); |
|||
return ListTile.divideTiles(context: this.context, tiles: detailItems); |
|||
} |
|||
|
|||
List<Widget> _allHeadingItems(float maxHeight, float midScrollOffset) { |
|||
List<Widget> sectionCards = new List<Widget> { }; |
|||
for (int index = 0; index < AnimationSectionsUtils.allSections.Count; index++) { |
|||
sectionCards.Add(new LayoutId( |
|||
id: $"card{index}", |
|||
child: new GestureDetector( |
|||
behavior: HitTestBehavior.opaque, |
|||
child: new SectionCard(section: AnimationSectionsUtils.allSections[index]), |
|||
onTapUp: (TapUpDetails details) => { |
|||
float xOffset = details.globalPosition.dx; |
|||
this.setState(() => { this._maybeScroll(midScrollOffset, index, xOffset); }); |
|||
} |
|||
) |
|||
)); |
|||
} |
|||
|
|||
List<Widget> headings = new List<Widget> { }; |
|||
for (int index = 0; index < AnimationSectionsUtils.allSections.Count; index++) { |
|||
headings.Add(new Container( |
|||
color: AnimationHomeUtils._kAppBackgroundColor, |
|||
child: new ClipRect( |
|||
child: new _AllSectionsView( |
|||
sectionIndex: index, |
|||
sections: AnimationSectionsUtils.allSections, |
|||
selectedIndex: this.selectedIndex, |
|||
minHeight: AnimationHomeUtils._kAppBarMinHeight, |
|||
midHeight: AnimationHomeUtils._kAppBarMidHeight, |
|||
maxHeight: maxHeight, |
|||
sectionCards: sectionCards |
|||
) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
|
|||
return headings; |
|||
} |
|||
|
|||
Widget _buildBody(BuildContext context) { |
|||
MediaQueryData mediaQueryData = MediaQuery.of(context); |
|||
float statusBarHeight = mediaQueryData.padding.top; |
|||
float screenHeight = mediaQueryData.size.height; |
|||
float appBarMaxHeight = screenHeight - statusBarHeight; |
|||
|
|||
float appBarMidScrollOffset = statusBarHeight + appBarMaxHeight - AnimationHomeUtils._kAppBarMidHeight; |
|||
|
|||
return SizedBox.expand( |
|||
child: new Stack( |
|||
children: new List<Widget> { |
|||
new NotificationListener<ScrollNotification>( |
|||
onNotification: (ScrollNotification notification) => { |
|||
return this._handleScrollNotification(notification, appBarMidScrollOffset); |
|||
}, |
|||
child: new CustomScrollView( |
|||
controller: this._scrollController, |
|||
physics: new _SnappingScrollPhysics(midScrollOffset: appBarMidScrollOffset), |
|||
slivers: new List<Widget> { |
|||
new _StatusBarPaddingSliver( |
|||
maxHeight: statusBarHeight, |
|||
scrollFactor: 7.0f |
|||
), |
|||
new SliverPersistentHeader( |
|||
pinned: true, |
|||
del: new _SliverAppBarDelegate( |
|||
minHeight: AnimationHomeUtils._kAppBarMinHeight, |
|||
maxHeight: appBarMaxHeight, |
|||
child: new NotificationListener<ScrollNotification>( |
|||
onNotification: (ScrollNotification notification) => { |
|||
return this._handlePageNotification(notification, |
|||
this._headingPageController, this._detailsPageController); |
|||
}, |
|||
child: new PageView( |
|||
physics: this._headingScrollPhysics, |
|||
controller: this._headingPageController, |
|||
children: this._allHeadingItems(appBarMaxHeight, |
|||
appBarMidScrollOffset) |
|||
) |
|||
) |
|||
) |
|||
), |
|||
new SliverToBoxAdapter( |
|||
child: new SizedBox( |
|||
height: 610.0f, |
|||
child: new NotificationListener<ScrollNotification>( |
|||
onNotification: (ScrollNotification notification) => { |
|||
return this._handlePageNotification(notification, |
|||
this._detailsPageController, this._headingPageController); |
|||
}, |
|||
child: new PageView( |
|||
controller: this._detailsPageController, |
|||
children: AnimationSectionsUtils.allSections |
|||
.Select<Section, Widget>((Section section) => { |
|||
return new Column( |
|||
crossAxisAlignment: CrossAxisAlignment.stretch, |
|||
children: this._detailItemsFor(section).ToList() |
|||
); |
|||
}).ToList() |
|||
) |
|||
) |
|||
) |
|||
) |
|||
} |
|||
) |
|||
), |
|||
new Positioned( |
|||
top: statusBarHeight, |
|||
left: 0.0f, |
|||
child: new IconTheme( |
|||
data: new IconThemeData(color: Colors.white), |
|||
child: new SafeArea( |
|||
top: false, |
|||
bottom: false, |
|||
child: new IconButton( |
|||
icon: new BackButtonIcon(), |
|||
tooltip: "Back", |
|||
onPressed: () => { this._handleBackButton(appBarMidScrollOffset); } |
|||
) |
|||
) |
|||
) |
|||
) |
|||
} |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.ui; |
|||
|
|||
namespace UIWidgetsGallery.gallery { |
|||
public class AnimationSectionsUtils { |
|||
public static readonly Color _mariner = new Color(0xFF3B5F8F); |
|||
public static readonly Color _mediumPurple = new Color(0xFF8266D4); |
|||
public static readonly Color _tomato = new Color(0xFFF95B57); |
|||
public static readonly Color _mySin = new Color(0xFFF3A646); |
|||
const string _kGalleryAssetsPackage = "flutter_gallery_assets"; |
|||
|
|||
public static readonly SectionDetail _eyeglassesDetail = new SectionDetail( |
|||
imageAsset: "products/sunnies", |
|||
imageAssetPackage: _kGalleryAssetsPackage, |
|||
title: "Flutter enables interactive animation", |
|||
subtitle: "3K views - 5 days" |
|||
); |
|||
|
|||
public static readonly SectionDetail _eyeglassesImageDetail = new SectionDetail( |
|||
imageAsset: "products/sunnies", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
); |
|||
|
|||
public static readonly SectionDetail _seatingDetail = new SectionDetail( |
|||
imageAsset: "products/table", |
|||
imageAssetPackage: _kGalleryAssetsPackage, |
|||
title: "Flutter enables interactive animation", |
|||
subtitle: "3K views - 5 days" |
|||
); |
|||
|
|||
public static readonly SectionDetail _seatingImageDetail = new SectionDetail( |
|||
imageAsset: "products/table", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
); |
|||
|
|||
public static readonly SectionDetail _decorationDetail = new SectionDetail( |
|||
imageAsset: "products/earrings", |
|||
imageAssetPackage: _kGalleryAssetsPackage, |
|||
title: "Flutter enables interactive animation", |
|||
subtitle: "3K views - 5 days" |
|||
); |
|||
|
|||
public static readonly SectionDetail _decorationImageDetail = new SectionDetail( |
|||
imageAsset: "products/earrings", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
); |
|||
|
|||
public static readonly SectionDetail _protectionDetail = new SectionDetail( |
|||
imageAsset: "products/hat", |
|||
imageAssetPackage: _kGalleryAssetsPackage, |
|||
title: "Flutter enables interactive animation", |
|||
subtitle: "3K views - 5 days" |
|||
); |
|||
|
|||
public static readonly SectionDetail _protectionImageDetail = new SectionDetail( |
|||
imageAsset: "products/hat", |
|||
imageAssetPackage: _kGalleryAssetsPackage |
|||
); |
|||
|
|||
public static List<Section> allSections = new List<Section> { |
|||
new Section( |
|||
title: "SUNGLASSES", |
|||
leftColor: _mediumPurple, |
|||
rightColor: _mariner, |
|||
backgroundAsset: "products/sunnies", |
|||
backgroundAssetPackage: _kGalleryAssetsPackage, |
|||
details: new List<SectionDetail> { |
|||
_eyeglassesDetail, |
|||
_eyeglassesImageDetail, |
|||
_eyeglassesDetail, |
|||
_eyeglassesDetail, |
|||
_eyeglassesDetail, |
|||
_eyeglassesDetail |
|||
} |
|||
), |
|||
new Section( |
|||
title: "FURNITURE", |
|||
leftColor: _tomato, |
|||
rightColor: _mediumPurple, |
|||
backgroundAsset: "products/table", |
|||
backgroundAssetPackage: _kGalleryAssetsPackage, |
|||
details: new List<SectionDetail> { |
|||
_seatingDetail, |
|||
_seatingImageDetail, |
|||
_seatingDetail, |
|||
_seatingDetail, |
|||
_seatingDetail, |
|||
_seatingDetail |
|||
} |
|||
), |
|||
new Section( |
|||
title: "JEWELRY", |
|||
leftColor: _mySin, |
|||
rightColor: _tomato, |
|||
backgroundAsset: "products/earrings", |
|||
backgroundAssetPackage: _kGalleryAssetsPackage, |
|||
details: new List<SectionDetail> { |
|||
_decorationDetail, |
|||
_decorationImageDetail, |
|||
_decorationDetail, |
|||
_decorationDetail, |
|||
_decorationDetail, |
|||
_decorationDetail |
|||
} |
|||
), |
|||
new Section( |
|||
title: "HEADWEAR", |
|||
leftColor: Colors.white, |
|||
rightColor: _tomato, |
|||
backgroundAsset: "products/hat", |
|||
backgroundAssetPackage: _kGalleryAssetsPackage, |
|||
details: new List<SectionDetail> { |
|||
_protectionDetail, |
|||
_protectionImageDetail, |
|||
_protectionDetail, |
|||
_protectionDetail, |
|||
_protectionDetail, |
|||
_protectionDetail |
|||
} |
|||
) |
|||
}; |
|||
} |
|||
|
|||
|
|||
public class SectionDetail { |
|||
public SectionDetail( |
|||
string title = null, |
|||
string subtitle = null, |
|||
string imageAsset = null, |
|||
string imageAssetPackage = null |
|||
) { |
|||
this.title = title; |
|||
this.subtitle = subtitle; |
|||
this.imageAsset = imageAsset; |
|||
this.imageAssetPackage = imageAssetPackage; |
|||
} |
|||
|
|||
public readonly string title; |
|||
public readonly string subtitle; |
|||
public readonly string imageAsset; |
|||
public readonly string imageAssetPackage; |
|||
} |
|||
|
|||
public class Section { |
|||
public Section( |
|||
string title, |
|||
string backgroundAsset, |
|||
string backgroundAssetPackage, |
|||
Color leftColor, |
|||
Color rightColor, |
|||
List<SectionDetail> details |
|||
) { |
|||
this.title = title; |
|||
this.backgroundAsset = backgroundAsset; |
|||
this.backgroundAssetPackage = backgroundAssetPackage; |
|||
this.leftColor = leftColor; |
|||
this.rightColor = rightColor; |
|||
this.details = details; |
|||
} |
|||
|
|||
public readonly string title; |
|||
public readonly string backgroundAsset; |
|||
public readonly string backgroundAssetPackage; |
|||
public readonly Color leftColor; |
|||
public readonly Color rightColor; |
|||
public readonly List<SectionDetail> details; |
|||
|
|||
public static bool operator ==(Section left, Section right) { |
|||
return Equals(left, right); |
|||
} |
|||
|
|||
public static bool operator !=(Section left, Section right) { |
|||
return !Equals(left, right); |
|||
} |
|||
|
|||
public bool Equals(Section other) { |
|||
return this.title == other.title; |
|||
} |
|||
|
|||
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((Section) obj); |
|||
} |
|||
|
|||
public override int GetHashCode() { |
|||
return this.title.GetHashCode(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 5180fb461b7448de8d4d084ff3f7c761 |
|||
timeCreated: 1555049317 |
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using Image = Unity.UIWidgets.widgets.Image; |
|||
|
|||
namespace UIWidgetsGallery.gallery { |
|||
class AnimationWidgetsUtils { |
|||
public const float kSectionIndicatorWidth = 32.0f; |
|||
} |
|||
|
|||
public class SectionCard : StatelessWidget { |
|||
public SectionCard( |
|||
Key key = null, |
|||
Section section = null |
|||
) : base(key: key) { |
|||
D.assert(section != null); |
|||
this.section = section; |
|||
} |
|||
|
|||
public readonly Section section; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new DecoratedBox( |
|||
decoration: new BoxDecoration( |
|||
gradient: new LinearGradient( |
|||
begin: Alignment.centerLeft, |
|||
end: Alignment.centerRight, |
|||
colors: new List<Color> { |
|||
this.section.leftColor, this.section.rightColor |
|||
} |
|||
) |
|||
), |
|||
child: Image.asset(this.section.backgroundAsset, |
|||
color: Color.fromRGBO(255, 255, 255, 0.075f), |
|||
colorBlendMode: BlendMode.modulate, |
|||
fit: BoxFit.cover |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
public class SectionTitle : StatelessWidget { |
|||
public SectionTitle( |
|||
Key key = null, |
|||
Section section = null, |
|||
float? scale = null, |
|||
float? opacity = null |
|||
) : base(key: key) { |
|||
D.assert(section != null); |
|||
D.assert(scale != null); |
|||
D.assert(opacity != null && opacity >= 0.0f && opacity <= 1.0f); |
|||
this.section = section; |
|||
this.scale = scale; |
|||
this.opacity = opacity; |
|||
} |
|||
|
|||
public readonly Section section; |
|||
public readonly float? scale; |
|||
public readonly float? opacity; |
|||
|
|||
public static readonly TextStyle sectionTitleStyle = new TextStyle( |
|||
fontFamily: "Raleway", |
|||
inherit: false, |
|||
fontSize: 24.0f, |
|||
fontWeight: FontWeight.w500, |
|||
color: Colors.white, |
|||
textBaseline: TextBaseline.alphabetic |
|||
); |
|||
|
|||
public static readonly TextStyle sectionTitleShadowStyle = sectionTitleStyle.copyWith( |
|||
color: new Color(0x19000000) |
|||
); |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new IgnorePointer( |
|||
child: new Opacity( |
|||
opacity: this.opacity ?? 1.0f, |
|||
child: new Transform( |
|||
transform: Matrix3.makeScale(this.scale ?? 1.0f), |
|||
alignment: Alignment.center, |
|||
child: new Stack( |
|||
children: new List<Widget> { |
|||
new Positioned( |
|||
top: 4.0f, |
|||
child: new Text(this.section.title, style: sectionTitleShadowStyle) |
|||
), |
|||
new Text(this.section.title, style: sectionTitleStyle) |
|||
} |
|||
) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
public class SectionIndicator : StatelessWidget { |
|||
public SectionIndicator(Key key = null, float opacity = 1.0f) : base(key: key) { |
|||
this.opacity = opacity; |
|||
} |
|||
|
|||
public readonly float opacity; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new IgnorePointer( |
|||
child: new Container( |
|||
width: AnimationWidgetsUtils.kSectionIndicatorWidth, |
|||
height: 3.0f, |
|||
color: Colors.white.withOpacity(this.opacity) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
public class SectionDetailView : StatelessWidget { |
|||
public SectionDetailView( |
|||
Key key = null, |
|||
SectionDetail detail = null |
|||
) : base(key: key) { |
|||
D.assert(detail != null && detail.imageAsset != null); |
|||
D.assert((detail.imageAsset ?? detail.title) != null); |
|||
this.detail = detail; |
|||
} |
|||
|
|||
public readonly SectionDetail detail; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
Widget image = new DecoratedBox( |
|||
decoration: new BoxDecoration( |
|||
borderRadius: BorderRadius.circular(6.0f), |
|||
image: new DecorationImage( |
|||
image: new AssetImage( |
|||
this.detail.imageAsset |
|||
), |
|||
fit: BoxFit.cover, |
|||
alignment: Alignment.center |
|||
) |
|||
) |
|||
); |
|||
|
|||
Widget item; |
|||
if (this.detail.title == null && this.detail.subtitle == null) { |
|||
item = new Container( |
|||
height: 240.0f, |
|||
padding: EdgeInsets.all(16.0f), |
|||
child: new SafeArea( |
|||
top: false, |
|||
bottom: false, |
|||
child: image |
|||
) |
|||
); |
|||
} |
|||
else { |
|||
item = new ListTile( |
|||
title: new Text(this.detail.title), |
|||
subtitle: new Text(this.detail.subtitle), |
|||
leading: new SizedBox(width: 32.0f, height: 32.0f, child: image) |
|||
); |
|||
} |
|||
|
|||
return new DecoratedBox( |
|||
decoration: new BoxDecoration(color: Colors.grey.shade200), |
|||
child: item |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 4c84aedb64bf44338944d63be7c563ed |
|||
timeCreated: 1555049115 |
撰写
预览
正在加载...
取消
保存
Reference in new issue