浏览代码

Merge branch 'gallery' into 'master'

Gallery

See merge request upm-packages/ui-widgets/com.unity.uiwidgets!151
/main
Shenhua Gu 6 年前
当前提交
e3c90b93
共有 23 个文件被更改,包括 1092 次插入118 次删除
  1. 7
      Runtime/material/app_bar.cs
  2. 3
      Runtime/material/bottom_app_bar.cs
  3. 1
      Runtime/material/bottom_sheet.cs
  4. 23
      Runtime/material/dropdown.cs
  5. 55
      Runtime/material/input_border.cs
  6. 170
      Runtime/material/input_decorator.cs
  7. 25
      Runtime/material/outline_button.cs
  8. 2
      Runtime/material/theme.cs
  9. 2
      Runtime/rendering/object.mixin.gen.cs
  10. 2
      Runtime/rendering/proxy_box.cs
  11. 8
      Runtime/rendering/sliver_persistent_header.cs
  12. 1
      Runtime/rendering/stack.cs
  13. 1
      Runtime/widgets/basic.cs
  14. 4
      Runtime/widgets/sliver_persistent_header.cs
  15. 2
      Samples/UIWidgetsGallery/demo/colors_demo.cs
  16. 30
      Samples/UIWidgetsGallery/gallery/demo.cs
  17. 18
      Samples/UIWidgetsGallery/gallery/demos.cs
  18. 592
      Runtime/material/bottom_navigation_bar.cs
  19. 3
      Runtime/material/bottom_navigation_bar.cs.meta
  20. 27
      Runtime/widgets/bottom_navigation_bar_item.cs
  21. 3
      Runtime/widgets/bottom_navigation_bar_item.cs.meta
  22. 228
      Samples/UIWidgetsGallery/demo/material/bottom_navigation_demo.cs
  23. 3
      Samples/UIWidgetsGallery/demo/material/bottom_navigation_demo.cs.meta

7
Runtime/material/app_bar.cs


bool pinned = false,
bool snap = false
) : base(key: key) {
D.assert(automaticallyImplyLeading != null);
D.assert(forceElevated != null);
D.assert(primary != null);
D.assert(titleSpacing != null);
D.assert(floating != null);
D.assert(pinned != null);
D.assert(snap != null);
D.assert(floating || !snap, "The 'snap' argument only makes sense for floating app bars.");
this.leading = leading;
this.automaticallyImplyLeading = true;

3
Runtime/material/bottom_app_bar.cs


float notchMargin = 4.0f,
Widget child = null
) : base(key: key) {
D.assert(elevation != null);
D.assert(clipBehavior != null);
this.child = child;
this.color = color;
this.elevation = elevation;

) : base(reclip: geometry) {
D.assert(geometry != null);
D.assert(shape != null);
D.assert(notchMargin != null);
this.geometry = geometry;
this.shape = shape;
this.notchMargin = notchMargin;

1
Runtime/material/bottom_sheet.cs


public override Widget build(BuildContext context) {
MediaQueryData mediaQuery = MediaQuery.of(context);
MaterialLocalizations localizations = MaterialLocalizations.of(context);
string routeLabel = "";
return new GestureDetector(
onTap: () => Navigator.pop(context),

23
Runtime/material/dropdown.cs


public readonly T result;
public static bool operator ==(_DropdownRouteResult<T> left, _DropdownRouteResult<T> right) {
return left.result == right.result;
return left.Equals(right);
return left.result != right.result;
return !left.Equals(right);
}
public bool Equals(_DropdownRouteResult<T> other) {
return this.result == other.result;
}
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((_DropdownRouteResult<T>) obj);
}
public override int GetHashCode() {

}
class _DropdownButtonFormFieldState<T> : FormFieldState<T> where T : class {
public DropdownButtonFormField<T> widget {
public new DropdownButtonFormField<T> widget {
get { return base.widget as DropdownButtonFormField<T>; }
}

55
Runtime/material/input_border.cs


using System.Runtime.CompilerServices;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.ui;

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 right) {
return left.Equals(right);
}
public static bool operator !=(UnderlineInputBorder left, UnderlineInputBorder right) {
return !left.Equals(right);
public static bool operator !=(UnderlineInputBorder left, UnderlineInputBorder other) {
return left.borderSide != other.borderSide;
public bool Equals(UnderlineInputBorder other) {
return this.borderSide == other.borderSide;
}
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((UnderlineInputBorder) obj);
}
public override int GetHashCode() {

}
}
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 right) {
return left.Equals(right);
}
public static bool operator !=(OutlineInputBorder left, OutlineInputBorder right) {
return !left.Equals(right);
}
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((OutlineInputBorder) obj);
public static bool operator !=(OutlineInputBorder left, OutlineInputBorder other) {
return !(left == other);
public bool Equals(OutlineInputBorder other) {
return other.borderSide == this.borderSide
&& other.borderRadius == this.borderRadius
&& other.gapPadding == this.gapPadding;
}
public override int GetHashCode() {

170
Runtime/material/input_decorator.cs


using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using RSG.Promises;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.foundation;

}
}
public static bool operator ==(_InputBorderGap left, _InputBorderGap other) {
return left.start == other.start && left.extent == other.extent;
public static bool operator ==(_InputBorderGap left, _InputBorderGap right) {
return left.Equals(right);
}
public bool Equals(_InputBorderGap other) {
return this.start == other.start && this.extent == other.extent;
}
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((_InputBorderGap) obj);
}
public override int GetHashCode() {

public readonly Widget counter;
public readonly Widget container;
public static bool operator ==(_Decoration left, _Decoration other) {
return left.contentPadding == other.contentPadding
&& left.floatingLabelHeight == other.floatingLabelHeight
&& left.floatingLabelProgress == other.floatingLabelProgress
&& left.border == other.border
&& left.borderGap == other.borderGap
&& left.icon == other.icon
&& left.input == other.input
&& left.label == other.label
&& left.hint == other.hint
&& left.prefix == other.prefix
&& left.suffix == other.suffix
&& left.prefixIcon == other.prefixIcon
&& left.suffixIcon == other.suffixIcon
&& left.helperError == other.helperError
&& left.counter == other.counter
&& left.container == other.container;
public static bool operator ==(_Decoration left, _Decoration right) {
return left.Equals(right);
}
public static bool operator !=(_Decoration left, _Decoration right) {
return !left.Equals(right);
public static bool operator !=(_Decoration left, _Decoration other) {
return !(left == other);
public bool Equals(_Decoration other) {
return this.contentPadding == other.contentPadding
&& this.floatingLabelHeight == other.floatingLabelHeight
&& this.floatingLabelProgress == other.floatingLabelProgress
&& this.border == other.border
&& this.borderGap == other.borderGap
&& this.icon == other.icon
&& this.input == other.input
&& this.label == other.label
&& this.hint == other.hint
&& this.prefix == other.prefix
&& this.suffix == other.suffix
&& this.prefixIcon == other.prefixIcon
&& this.suffixIcon == other.suffixIcon
&& this.helperError == other.helperError
&& this.counter == other.counter
&& this.container == other.container;
}
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((_Decoration) obj);
}
public override int GetHashCode() {

Dictionary<_DecorationSlot, Element> slotToChild = new Dictionary<_DecorationSlot, Element>();
Dictionary<Element, _DecorationSlot> childToSlot = new Dictionary<Element, _DecorationSlot>();
public _Decorator widget {
public new _Decorator widget {
public _RenderDecoration renderObject {
public new _RenderDecoration renderObject {
get { return (_RenderDecoration) base.renderObject; }
}

);
}
public static bool operator ==(InputDecoration left, InputDecoration other) {
return other.icon == left.icon
&& other.labelText == left.labelText
&& other.labelStyle == left.labelStyle
&& other.helperText == left.helperText
&& other.helperStyle == left.helperStyle
&& other.hintText == left.hintText
&& other.hintStyle == left.hintStyle
&& other.errorText == left.errorText
&& other.errorStyle == left.errorStyle
&& other.errorMaxLines == left.errorMaxLines
&& other.hasFloatingPlaceholder == left.hasFloatingPlaceholder
&& other.isDense == left.isDense
&& other.contentPadding == left.contentPadding
&& other.isCollapsed == left.isCollapsed
&& other.prefixIcon == left.prefixIcon
&& other.prefix == left.prefix
&& other.prefixText == left.prefixText
&& other.prefixStyle == left.prefixStyle
&& other.suffixIcon == left.suffixIcon
&& other.suffix == left.suffix
&& other.suffixText == left.suffixText
&& other.suffixStyle == left.suffixStyle
&& other.counterText == left.counterText
&& other.counterStyle == left.counterStyle
&& other.filled == left.filled
&& other.fillColor == left.fillColor
&& other.errorBorder == left.errorBorder
&& other.focusedBorder == left.focusedBorder
&& other.focusedErrorBorder == left.focusedErrorBorder
&& other.disabledBorder == left.disabledBorder
&& other.enabledBorder == left.enabledBorder
&& other.border == left.border
&& other.enabled == left.enabled;
public static bool operator ==(InputDecoration left, InputDecoration right) {
return left.Equals(right);
}
public static bool operator !=(InputDecoration left, InputDecoration right) {
return !left.Equals(right);
public static bool operator !=(InputDecoration left, InputDecoration other) {
return !(left == other);
public bool Equals(InputDecoration other) {
return other.icon == this.icon
&& other.labelText == this.labelText
&& other.labelStyle == this.labelStyle
&& other.helperText == this.helperText
&& other.helperStyle == this.helperStyle
&& other.hintText == this.hintText
&& other.hintStyle == this.hintStyle
&& other.errorText == this.errorText
&& other.errorStyle == this.errorStyle
&& other.errorMaxLines == this.errorMaxLines
&& other.hasFloatingPlaceholder == this.hasFloatingPlaceholder
&& other.isDense == this.isDense
&& other.contentPadding == this.contentPadding
&& other.isCollapsed == this.isCollapsed
&& other.prefixIcon == this.prefixIcon
&& other.prefix == this.prefix
&& other.prefixText == this.prefixText
&& other.prefixStyle == this.prefixStyle
&& other.suffixIcon == this.suffixIcon
&& other.suffix == this.suffix
&& other.suffixText == this.suffixText
&& other.suffixStyle == this.suffixStyle
&& other.counterText == this.counterText
&& other.counterStyle == this.counterStyle
&& other.filled == this.filled
&& other.fillColor == this.fillColor
&& other.errorBorder == this.errorBorder
&& other.focusedBorder == this.focusedBorder
&& other.focusedErrorBorder == this.focusedErrorBorder
&& other.disabledBorder == this.disabledBorder
&& other.enabledBorder == this.enabledBorder
&& other.border == this.border
&& other.enabled == this.enabled;
}
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((InputDecoration) obj);
}
public override int GetHashCode() {

25
Runtime/material/outline_button.cs


}
}
public static bool operator ==(_OutlineBorder left, _OutlineBorder other) {
return left.side == other.side && left.shape == other.shape;
public static bool operator ==(_OutlineBorder left, _OutlineBorder right) {
return left.Equals(right);
}
public static bool operator !=(_OutlineBorder left, _OutlineBorder right) {
return !left.Equals(right);
public static bool operator !=(_OutlineBorder left, _OutlineBorder other) {
return left.side != other.side || left.shape != other.shape;
public bool Equals(_OutlineBorder other) {
return this.side == other.side && this.shape == other.shape;
}
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((_OutlineBorder) obj);
}
public override int GetHashCode() {

2
Runtime/material/theme.cs


using Unity.UIWidgets.widgets;
namespace Unity.UIWidgets.material {
static class ThemeUtils {
public static class ThemeUtils {
public static readonly TimeSpan kThemeAnimationDuration = new TimeSpan(0, 0, 0, 0, 200);
}

2
Runtime/rendering/object.mixin.gen.cs


get { return this._childCount; }
}
public bool debugValidateChild(RenderObject child) {
public new bool debugValidateChild(RenderObject child) {
D.assert(() => {
if (!(child is ChildType)) {
throw new UIWidgetsError(

2
Runtime/rendering/proxy_box.cs


Alignment alignment = null,
RenderBox child = null
) : base(child) {
D.assert(fit != null);
this._fit = fit;
this._alignment = alignment ?? Alignment.center;
}

public BoxFit fit {
get { return this._fit; }
set {
D.assert(value != null);
if (this._fit == value) {
return;
}

8
Runtime/rendering/sliver_persistent_header.cs


}
D.assert(this.child.hasSize);
D.assert(this.constraints.axis != null);
switch (this.constraints.axis) {
case Axis.vertical:
return this.child.size.height;

}
protected void layoutChild(float scrollOffset, float maxExtent, bool overlapsContent = false) {
D.assert(maxExtent != null);
D.assert(this.constraints == this.constraints);
D.assert(constraints == this.constraints);
this.updateChild(shrinkOffset, overlapsContent);
});
this._lastShrinkOffset = shrinkOffset;

public override void paint(PaintingContext context, Offset offset) {
if (this.child != null && this.geometry.visible) {
D.assert(this.constraints.axisDirection != null);
switch (GrowthDirectionUtils.applyGrowthDirectionToAxisDirection(this.constraints.axisDirection,
this.constraints.growthDirection)) {
case AxisDirection.up:

protected override void performLayout() {
float? maxExtent = this.maxExtent;
if (this._lastActualScrollOffset != null &&
((this.constraints.scrollOffset < this._lastActualScrollOffset) ||
if (((this.constraints.scrollOffset < this._lastActualScrollOffset) ||
(this._effectiveScrollOffset < maxExtent))) {
float delta = this._lastActualScrollOffset - this.constraints.scrollOffset;
bool allowFloatingExpansion = this.constraints.userScrollDirection == ScrollDirection.forward;

1
Runtime/rendering/stack.cs


}
public static RelativeRect lerp(RelativeRect a, RelativeRect b, float t) {
D.assert(t != null);
if (a == null && b == null) {
return null;
}

1
Runtime/widgets/basic.cs


Alignment alignment = null,
Widget child = null
) : base(key: key, child: child) {
D.assert(fit != null);
this.fit = fit;
this.alignment = alignment ?? Alignment.center;
}

4
Runtime/widgets/sliver_persistent_header.cs


bool floating = false
) : base(key: key) {
D.assert(del != null);
D.assert(pinned != null);
D.assert(floating != null);
this.del = del;
this.pinned = pinned;
this.floating = floating;

public _SliverPersistentHeaderElement(_SliverPersistentHeaderRenderObjectWidget widget) : base(widget) {
}
public _SliverPersistentHeaderRenderObjectWidget widget {
public new _SliverPersistentHeaderRenderObjectWidget widget {
get { return (_SliverPersistentHeaderRenderObjectWidget) base.widget; }
}

2
Samples/UIWidgetsGallery/demo/colors_demo.cs


public readonly int threshold;
public bool isValid {
get { return this.name != null && this.primary != null && this.threshold != null; }
get { return this.name != null && this.primary != null; }
}
}

30
Samples/UIWidgetsGallery/gallery/demo.cs


public readonly string documentationUrl;
public static bool operator ==(ComponentDemoTabData left, ComponentDemoTabData right) {
return right.tabName == left.tabName
&& right.description == left.description
&& right.documentationUrl == left.documentationUrl;
return left.Equals(right);
return right.tabName != left.tabName
|| right.description != left.description
|| right.documentationUrl != left.documentationUrl;
return !left.Equals(right);
}
public bool Equals(ComponentDemoTabData other) {
return other.tabName == this.tabName
&& other.description == this.description
&& other.documentationUrl == this.documentationUrl;
}
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((ComponentDemoTabData) obj);
}
public override int GetHashCode() {

18
Samples/UIWidgetsGallery/gallery/demos.cs


documentationUrl: "https://docs.flutter.io/flutter/material/BottomAppBar-class.html",
buildRoute: (BuildContext context) => new BottomAppBarDemo()
),
// new GalleryDemo(
// title: "Bottom navigation",
// subtitle: "Bottom navigation with cross-fading views",
// icon: GalleryIcons.bottom_navigation,
// category: GalleryDemoCategory._kMaterialComponents,
// routeName: BottomNavigationDemo.routeName,
// documentationUrl: "https://docs.flutter.io/flutter/material/BottomNavigationBar-class.html",
// buildRoute: (BuildContext context) => BottomNavigationDemo()
// ),
new GalleryDemo(
title: "Bottom navigation",
subtitle: "Bottom navigation with cross-fading views",
icon: GalleryIcons.bottom_navigation,
category: DemoUtils._kMaterialComponents,
routeName: BottomNavigationDemo.routeName,
documentationUrl: "https://docs.flutter.io/flutter/material/BottomNavigationBar-class.html",
buildRoute: (BuildContext context) => new BottomNavigationDemo()
),
// new GalleryDemo(
// title: "Bottom sheet: Modal",
// subtitle: "A dismissable bottom sheet",

592
Runtime/material/bottom_navigation_bar.cs


using System;
using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.scheduler;
using Unity.UIWidgets.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;
using Transform = Unity.UIWidgets.widgets.Transform;
namespace Unity.UIWidgets.material {
class BottomNavigationBarUtils {
public const float _kActiveFontSize = 14.0f;
public const float _kInactiveFontSize = 12.0f;
public const float _kTopMargin = 6.0f;
public const float _kBottomMargin = 8.0f;
}
public enum BottomNavigationBarType {
fix,
shifting
}
public class BottomNavigationBar : StatefulWidget {
public BottomNavigationBar(
Key key = null,
List<BottomNavigationBarItem> items = null,
ValueChanged<int> onTap = null,
int currentIndex = 0,
BottomNavigationBarType? type = null,
Color fixedColor = null,
float iconSize = 24.0f
) : base(key: key) {
D.assert(items != null);
D.assert(items.Count >= 2);
D.assert(items.All((BottomNavigationBarItem item) => item.title != null) == true,
"Every item must have a non-null title"
);
D.assert(0 <= currentIndex && currentIndex < items.Count);
this.items = items;
this.onTap = onTap;
this.currentIndex = currentIndex;
this.type = type ?? (items.Count <= 3 ? BottomNavigationBarType.fix : BottomNavigationBarType.shifting);
this.fixedColor = fixedColor;
this.iconSize = iconSize;
}
public readonly List<BottomNavigationBarItem> items;
public readonly ValueChanged<int> onTap;
public readonly int currentIndex;
public readonly BottomNavigationBarType? type;
public readonly Color fixedColor;
public readonly float iconSize;
public override State createState() {
return new _BottomNavigationBarState();
}
}
class _BottomNavigationTile : StatelessWidget {
public _BottomNavigationTile(
BottomNavigationBarType? type,
BottomNavigationBarItem item,
Animation<float> animation,
float? iconSize = null,
VoidCallback onTap = null,
ColorTween colorTween = null,
float? flex = null,
bool selected = false,
string indexLabel = null
) {
this.type = type;
this.item = item;
this.animation = animation;
this.iconSize = iconSize;
this.onTap = onTap;
this.colorTween = colorTween;
this.flex = flex;
this.selected = selected;
this.indexLabel = indexLabel;
}
public readonly BottomNavigationBarType? type;
public readonly BottomNavigationBarItem item;
public readonly Animation<float> animation;
public readonly float? iconSize;
public readonly VoidCallback onTap;
public readonly ColorTween colorTween;
public readonly float? flex;
public readonly bool selected;
public readonly string indexLabel;
Widget _buildIcon() {
float tweenStart;
Color iconColor;
switch (this.type) {
case BottomNavigationBarType.fix:
tweenStart = 8.0f;
iconColor = this.colorTween.evaluate(this.animation);
break;
case BottomNavigationBarType.shifting:
tweenStart = 16.0f;
iconColor = Colors.white;
break;
default:
throw new Exception("Unknown BottomNavigationBarType: " + this.type);
}
return new Align(
alignment: Alignment.topCenter,
heightFactor: 1.0f,
child: new Container(
margin: EdgeInsets.only(
top: new FloatTween(
begin: tweenStart,
end: BottomNavigationBarUtils._kTopMargin
).evaluate(this.animation)
),
child: new IconTheme(
data: new IconThemeData(
color: iconColor,
size: this.iconSize
),
child: this.selected ? this.item.activeIcon : this.item.icon
)
)
);
}
Widget _buildFixedLabel() {
float t = new FloatTween(
begin: BottomNavigationBarUtils._kInactiveFontSize / BottomNavigationBarUtils._kActiveFontSize,
end: 1.0f
).evaluate(this.animation);
return new Align(
alignment: Alignment.bottomCenter,
heightFactor: 1.0f,
child: new Container(
margin: EdgeInsets.only(bottom: BottomNavigationBarUtils._kBottomMargin),
child: DefaultTextStyle.merge(
style: new TextStyle(
fontSize: BottomNavigationBarUtils._kActiveFontSize,
color: this.colorTween.evaluate(this.animation)
),
child: new Transform(
transform: Matrix3.makeAll(t, 0, 0, 0, t, 0, 0, 0, t),
alignment: Alignment.bottomCenter,
child: this.item.title
)
)
)
);
}
Widget _buildShiftingLabel() {
return new Align(
alignment: Alignment.bottomCenter,
heightFactor: 1.0f,
child: new Container(
margin: EdgeInsets.only(
bottom: new FloatTween(
begin: 2.0f,
end: BottomNavigationBarUtils._kBottomMargin
).evaluate(this.animation)
),
child: new FadeTransition(
opacity: this.animation,
child: DefaultTextStyle.merge(
style: new TextStyle(
fontSize: BottomNavigationBarUtils._kActiveFontSize,
color: Colors.white
),
child: this.item.title
)
)
)
);
}
public override Widget build(BuildContext context) {
int size;
Widget label;
switch (this.type) {
case BottomNavigationBarType.fix:
size = 1;
label = this._buildFixedLabel();
break;
case BottomNavigationBarType.shifting:
size = ((this.flex * 1000.0f) ?? 0.0f).round();
label = this._buildShiftingLabel();
break;
default:
throw new Exception("Unknown BottomNavigationBarType: " + this.type);
}
return new Expanded(
flex: size,
child: new Stack(
children: new List<Widget> {
new InkResponse(
onTap: this.onTap == null ? (GestureTapCallback) null : () => { this.onTap(); },
child: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: new List<Widget> {this._buildIcon(), label}
)
)
}
)
);
}
}
class _BottomNavigationBarState : TickerProviderStateMixin<BottomNavigationBar> {
public List<AnimationController> _controllers = new List<AnimationController> { };
public List<CurvedAnimation> _animations;
Queue<_Circle> _circles = new Queue<_Circle>();
Color _backgroundColor;
static readonly Animatable<float> _flexTween = new FloatTween(begin: 1.0f, end: 1.5f);
public _BottomNavigationBarState() {
}
void _resetState() {
foreach (AnimationController controller in this._controllers) {
controller.dispose();
}
foreach (_Circle circle in this._circles) {
circle.dispose();
}
this._circles.Clear();
this._controllers = new List<AnimationController>(capacity: this.widget.items.Count);
for (int index = 0; index < this.widget.items.Count; index++) {
AnimationController controller = new AnimationController(
duration: ThemeUtils.kThemeAnimationDuration,
vsync: this
);
controller.addListener(this._rebuild);
this._controllers.Add(controller);
}
this._animations = new List<CurvedAnimation>(capacity: this.widget.items.Count);
for (int index = 0; index < this.widget.items.Count; index++) {
this._animations.Add(new CurvedAnimation(
parent: this._controllers[index],
curve: Curves.fastOutSlowIn,
reverseCurve: Curves.fastOutSlowIn.flipped
));
}
this._controllers[this.widget.currentIndex].setValue(1.0f);
this._backgroundColor = this.widget.items[this.widget.currentIndex].backgroundColor;
}
public override void initState() {
base.initState();
this._resetState();
}
void _rebuild() {
this.setState(() => { });
}
public override void dispose() {
foreach (AnimationController controller in this._controllers) {
controller.dispose();
}
foreach (_Circle circle in this._circles) {
circle.dispose();
}
base.dispose();
}
public float _evaluateFlex(Animation<float> animation) {
return _flexTween.evaluate(animation);
}
void _pushCircle(int index) {
if (this.widget.items[index].backgroundColor != null) {
_Circle circle = new _Circle(
state: this,
index: index,
color: this.widget.items[index].backgroundColor,
vsync: this
);
circle.controller.addStatusListener(
(AnimationStatus status) => {
switch (status) {
case AnimationStatus.completed:
this.setState(() => {
_Circle cir = this._circles.Dequeue();
this._backgroundColor = cir.color;
cir.dispose();
});
break;
case AnimationStatus.dismissed:
case AnimationStatus.forward:
case AnimationStatus.reverse:
break;
}
}
);
this._circles.Enqueue(circle);
}
}
public override void didUpdateWidget(StatefulWidget _oldWidget) {
base.didUpdateWidget(_oldWidget);
BottomNavigationBar oldWidget = _oldWidget as BottomNavigationBar;
if (this.widget.items.Count != oldWidget.items.Count) {
this._resetState();
return;
}
if (this.widget.currentIndex != oldWidget.currentIndex) {
switch (this.widget.type) {
case BottomNavigationBarType.fix:
break;
case BottomNavigationBarType.shifting:
this._pushCircle(this.widget.currentIndex);
break;
}
this._controllers[oldWidget.currentIndex].reverse();
this._controllers[this.widget.currentIndex].forward();
}
else {
if (this._backgroundColor != this.widget.items[this.widget.currentIndex].backgroundColor) {
this._backgroundColor = this.widget.items[this.widget.currentIndex].backgroundColor;
}
}
}
List<Widget> _createTiles() {
MaterialLocalizations localizations = MaterialLocalizations.of(this.context);
D.assert(localizations != null);
List<Widget> children = new List<Widget> { };
switch (this.widget.type) {
case BottomNavigationBarType.fix:
ThemeData themeData = Theme.of(this.context);
TextTheme textTheme = themeData.textTheme;
Color themeColor;
switch (themeData.brightness) {
case Brightness.light:
themeColor = themeData.primaryColor;
break;
case Brightness.dark:
themeColor = themeData.accentColor;
break;
default:
throw new Exception("Unknown brightness: " + themeData.brightness);
}
ColorTween colorTween = new ColorTween(
begin: textTheme.caption.color,
end: this.widget.fixedColor ?? themeColor
);
for (int i = 0; i < this.widget.items.Count; i += 1) {
int index = i;
children.Add(
new _BottomNavigationTile(this.widget.type, this.widget.items[i], this._animations[i],
this.widget.iconSize,
onTap: () => {
if (this.widget.onTap != null) {
this.widget.onTap(index);
}
},
colorTween: colorTween,
selected: i == this.widget.currentIndex,
indexLabel: localizations.tabLabel(tabIndex: i + 1, tabCount: this.widget.items.Count)
)
);
}
break;
case BottomNavigationBarType.shifting:
for (int i = 0; i < this.widget.items.Count; i += 1) {
int index = i;
children.Add(
new _BottomNavigationTile(this.widget.type, this.widget.items[i], this._animations[i],
this.widget.iconSize,
onTap: () => {
if (this.widget.onTap != null) {
this.widget.onTap(index);
}
},
flex:
this._evaluateFlex(this._animations[i]),
selected: i == this.widget.currentIndex,
indexLabel: localizations.tabLabel(tabIndex: i + 1, tabCount: this.widget.items.Count)
)
);
}
break;
}
return children;
}
Widget _createContainer(List<Widget> tiles) {
return DefaultTextStyle.merge(
overflow: TextOverflow.ellipsis,
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: tiles
)
);
}
public override Widget build(BuildContext context) {
D.assert(WidgetsD.debugCheckHasDirectionality(context));
D.assert(MaterialD.debugCheckHasMaterialLocalizations(context));
float additionalBottomPadding =
Mathf.Max(MediaQuery.of(context).padding.bottom - BottomNavigationBarUtils._kBottomMargin, 0.0f);
Color backgroundColor = null;
switch (this.widget.type) {
case BottomNavigationBarType.fix:
break;
case BottomNavigationBarType.shifting:
backgroundColor = this._backgroundColor;
break;
}
return new Stack(
children: new List<Widget> {
Positioned.fill(
child: new Material( // Casts shadow.
elevation: 8.0f,
color: backgroundColor
)
),
new ConstrainedBox(
constraints: new BoxConstraints(
minHeight: Constants.kBottomNavigationBarHeight + additionalBottomPadding),
child: new Stack(
children: new List<Widget> {
Positioned.fill(
child: new CustomPaint(
painter: new _RadialPainter(
circles: this._circles.ToList()
)
)
),
new Material( // Splashes.
type: MaterialType.transparency,
child: new Padding(
padding: EdgeInsets.only(bottom: additionalBottomPadding),
child: MediaQuery.removePadding(
context: context,
removeBottom: true,
child: this._createContainer(this._createTiles())
)
)
)
}
)
)
}
);
}
}
class _Circle {
public _Circle(
_BottomNavigationBarState state = null,
int? index = null,
Color color = null,
TickerProvider vsync = null
) {
D.assert(state != null);
D.assert(index != null);
D.assert(color != null);
this.state = state;
this.index = index;
this.color = color;
this.controller = new AnimationController(
duration: ThemeUtils.kThemeAnimationDuration,
vsync: vsync
);
this.animation = new CurvedAnimation(
parent: this.controller,
curve: Curves.fastOutSlowIn
);
this.controller.forward();
}
public readonly _BottomNavigationBarState state;
public readonly int? index;
public readonly Color color;
public readonly AnimationController controller;
public readonly CurvedAnimation animation;
public float horizontalLeadingOffset {
get {
float weightSum(IEnumerable<Animation<float>> animations) {
return animations.Select(this.state._evaluateFlex).Sum();
}
float allWeights = weightSum(this.state._animations);
float leadingWeights = weightSum(this.state._animations.GetRange(0, this.index ?? 0));
return (leadingWeights + this.state._evaluateFlex(this.state._animations[this.index ?? 0]) / 2.0f) /
allWeights;
}
}
public void dispose() {
this.controller.dispose();
}
}
class _RadialPainter : AbstractCustomPainter {
public _RadialPainter(
List<_Circle> circles
) {
D.assert(circles != null);
this.circles = circles;
}
public readonly List<_Circle> circles;
static float _maxRadius(Offset center, Size size) {
float maxX = Mathf.Max(center.dx, size.width - center.dx);
float maxY = Mathf.Max(center.dy, size.height - center.dy);
return Mathf.Sqrt(maxX * maxX + maxY * maxY);
}
public override bool shouldRepaint(CustomPainter _oldPainter) {
_RadialPainter oldPainter = _oldPainter as _RadialPainter;
if (this.circles == oldPainter.circles) {
return false;
}
if (this.circles.Count != oldPainter.circles.Count) {
return true;
}
for (int i = 0; i < this.circles.Count; i += 1) {
if (this.circles[i] != oldPainter.circles[i]) {
return true;
}
}
return false;
}
public override void paint(Canvas canvas, Size size) {
foreach (_Circle circle in this.circles) {
Paint paint = new Paint();
paint.color = circle.color;
Rect rect = Rect.fromLTWH(0.0f, 0.0f, size.width, size.height);
canvas.clipRect(rect);
float leftFraction = circle.horizontalLeadingOffset;
Offset center = new Offset(leftFraction * size.width, size.height / 2.0f);
FloatTween radiusTween = new FloatTween(
begin: 0.0f,
end: _maxRadius(center, size)
);
canvas.drawCircle(
center,
radiusTween.evaluate(circle.animation),
paint
);
}
}
}
}

3
Runtime/material/bottom_navigation_bar.cs.meta


fileFormatVersion: 2
guid: 6b8f793d1b8d4004b2c19c1c085752c3
timeCreated: 1553161698

27
Runtime/widgets/bottom_navigation_bar_item.cs


using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.widgets {
public class BottomNavigationBarItem {
public BottomNavigationBarItem(
Widget icon = null,
Widget title = null,
Widget activeIcon = null,
Color backgroundColor = null
) {
D.assert(icon != null);
this.icon = icon;
this.activeIcon = activeIcon ?? icon;
this.title = title;
this.backgroundColor = backgroundColor;
}
public readonly Widget icon;
public readonly Widget activeIcon;
public readonly Widget title;
public readonly Color backgroundColor;
}
}

3
Runtime/widgets/bottom_navigation_bar_item.cs.meta


fileFormatVersion: 2
guid: 7000f1f897684e08a0831ca5d920589f
timeCreated: 1553162159

228
Samples/UIWidgetsGallery/demo/material/bottom_navigation_demo.cs


using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.material;
using Unity.UIWidgets.painting;
using Unity.UIWidgets.scheduler;
using Unity.UIWidgets.service;
using Unity.UIWidgets.ui;
using Unity.UIWidgets.widgets;
namespace UIWidgetsGallery.gallery {
public class NavigationIconView {
public NavigationIconView(
Widget icon = null,
Widget activeIcon = null,
string title = null,
Color color = null,
TickerProvider vsync = null
) {
this._icon = icon;
this._color = color;
this._title = title;
this.item = new BottomNavigationBarItem(
icon: icon,
activeIcon: activeIcon,
title: new Text(title),
backgroundColor: color
);
this.controller = new AnimationController(
duration: ThemeUtils.kThemeAnimationDuration,
vsync: vsync
);
this._animation = this.controller.drive(new CurveTween(
curve: new Interval(0.5f, 1.0f, curve: Curves.fastOutSlowIn)
));
}
readonly Widget _icon;
readonly Color _color;
readonly string _title;
public readonly BottomNavigationBarItem item;
public readonly AnimationController controller;
Animation<float> _animation;
public FadeTransition transition(BottomNavigationBarType type, BuildContext context) {
Color iconColor;
if (type == BottomNavigationBarType.shifting) {
iconColor = this._color;
}
else {
ThemeData themeData = Theme.of(context);
iconColor = themeData.brightness == Brightness.light
? themeData.primaryColor
: themeData.accentColor;
}
return new FadeTransition(
opacity: this._animation,
child: new SlideTransition(
position: this._animation.drive(
new OffsetTween(
begin: new Offset(0.0f, 0.02f), // Slightly down.
end: Offset.zero
)
),
child: new IconTheme(
data: new IconThemeData(
color: iconColor,
size: 120.0f
),
child: this._icon
)
)
);
}
}
public class CustomIcon : StatelessWidget {
public override Widget build(BuildContext context) {
IconThemeData iconTheme = IconTheme.of(context);
return new Container(
margin: EdgeInsets.all(4.0f),
width: iconTheme.size - 8.0f,
height: iconTheme.size - 8.0f,
color: iconTheme.color
);
}
}
public class CustomInactiveIcon : StatelessWidget {
public override Widget build(BuildContext context) {
IconThemeData iconTheme = IconTheme.of(context);
return new Container(
margin: EdgeInsets.all(4.0f),
width: iconTheme.size - 8.0f,
height: iconTheme.size - 8.0f,
decoration: new BoxDecoration(
border: Border.all(color: iconTheme.color, width: 2.0f)
)
);
}
}
public class BottomNavigationDemo : StatefulWidget {
public const string routeName = "/material/bottom_navigation";
public override State createState() {
return new _BottomNavigationDemoState();
}
}
class _BottomNavigationDemoState : TickerProviderStateMixin<BottomNavigationDemo> {
int _currentIndex = 0;
BottomNavigationBarType _type = BottomNavigationBarType.shifting;
List<NavigationIconView> _navigationViews;
public override void initState() {
base.initState();
this._navigationViews = new List<NavigationIconView> {
new NavigationIconView(
icon: new Icon(Icons.access_alarm),
title: "Alarm",
color: Colors.deepPurple,
vsync: this
),
new NavigationIconView(
activeIcon: new CustomIcon(),
icon: new CustomInactiveIcon(),
title: "Box",
color: Colors.deepOrange,
vsync: this
),
new NavigationIconView(
activeIcon: new Icon(Icons.cloud),
icon: new Icon(Icons.cloud_queue),
title: "Cloud",
color: Colors.teal,
vsync: this
),
new NavigationIconView(
activeIcon: new Icon(Icons.favorite),
icon: new Icon(Icons.favorite_border),
title: "Favorites",
color: Colors.indigo,
vsync: this
),
new NavigationIconView(
icon: new Icon(Icons.event_available),
title: "Event",
color: Colors.pink,
vsync: this
)
};
this._navigationViews[this._currentIndex].controller.setValue(1.0f);
}
public override void dispose() {
foreach (NavigationIconView view in this._navigationViews) {
view.controller.dispose();
}
base.dispose();
}
Widget _buildTransitionsStack() {
List<FadeTransition> transitions = new List<FadeTransition> { };
foreach (NavigationIconView view in this._navigationViews) {
transitions.Add(view.transition(this._type, this.context));
}
transitions.Sort((FadeTransition a, FadeTransition b) => {
Animation<float> aAnimation = a.opacity;
Animation<float> bAnimation = b.opacity;
float aValue = aAnimation.value;
float bValue = bAnimation.value;
return aValue.CompareTo(bValue);
});
return new Stack(children: transitions.Select<FadeTransition, Widget>(w => w).ToList());
}
public override Widget build(BuildContext context) {
BottomNavigationBar botNavBar = new BottomNavigationBar(
items: this._navigationViews.Select((NavigationIconView navigationView) => navigationView.item)
.ToList(),
currentIndex: this._currentIndex,
type: this._type,
onTap: (int index) => {
this.setState(() => {
this._navigationViews[this._currentIndex].controller.reverse();
this._currentIndex = index;
this._navigationViews[this._currentIndex].controller.forward();
});
}
);
return new Scaffold(
appBar: new AppBar(
title: new Text("Bottom navigation"),
actions: new List<Widget> {
new MaterialDemoDocumentationButton(BottomNavigationDemo.routeName),
new PopupMenuButton<BottomNavigationBarType>(
onSelected: (BottomNavigationBarType value) => {
this.setState(() => { this._type = value; });
},
itemBuilder: (BuildContext _context) => new List<PopupMenuEntry<BottomNavigationBarType>> {
new PopupMenuItem<BottomNavigationBarType>(
value: BottomNavigationBarType.fix,
child: new Text("Fixed")
),
new PopupMenuItem<BottomNavigationBarType>(
value: BottomNavigationBarType.shifting,
child: new Text("Shifting")
)
}
)
}
),
body: new Center(
child: this._buildTransitionsStack()
),
bottomNavigationBar: botNavBar
);
}
}
}

3
Samples/UIWidgetsGallery/demo/material/bottom_navigation_demo.cs.meta


fileFormatVersion: 2
guid: d279028b09c04c2b8ab3fba122868004
timeCreated: 1553221768
正在加载...
取消
保存