Yuncong Zhang
6 年前
当前提交
84bc0348
共有 12 个文件被更改,包括 1058 次插入 和 12 次删除
-
146Runtime/material/bottom_sheet.cs
-
2Runtime/material/scaffold.cs
-
2Samples/UIWidgetsGallery/demo/material/backdrop_demo.cs
-
18Samples/UIWidgetsGallery/gallery/demos.cs
-
113Runtime/material/bottom_app_bar.cs
-
3Runtime/material/bottom_app_bar.cs.meta
-
183Runtime/material/radio.cs
-
3Runtime/material/radio.cs.meta
-
71Runtime/painting/notched_shapes.cs
-
3Runtime/painting/notched_shapes.cs.meta
-
523Samples/UIWidgetsGallery/demo/material/bottom_app_bar_demo.cs
-
3Samples/UIWidgetsGallery/demo/material/bottom_app_bar_demo.cs.meta
|
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace Unity.UIWidgets.material { |
|||
public class BottomAppBar : StatefulWidget { |
|||
public BottomAppBar( |
|||
Key key = null, |
|||
Color color = null, |
|||
float elevation = 8.0f, |
|||
NotchedShape shape = null, |
|||
Clip clipBehavior = Clip.none, |
|||
float notchMargin = 4.0f, |
|||
Widget child = null |
|||
) : base(key: key) { |
|||
D.assert(elevation != null); |
|||
D.assert(elevation >= 0.0f); |
|||
D.assert(clipBehavior != null); |
|||
this.child = child; |
|||
this.color = color; |
|||
this.elevation = elevation; |
|||
this.shape = shape; |
|||
this.clipBehavior = clipBehavior; |
|||
this.notchMargin = notchMargin; |
|||
} |
|||
|
|||
public readonly Widget child; |
|||
|
|||
public readonly Color color; |
|||
|
|||
public readonly float elevation; |
|||
|
|||
public readonly NotchedShape shape; |
|||
|
|||
public readonly Clip clipBehavior; |
|||
|
|||
public readonly float notchMargin; |
|||
|
|||
public override State createState() { |
|||
return new _BottomAppBarState(); |
|||
} |
|||
} |
|||
|
|||
class _BottomAppBarState : State<BottomAppBar> { |
|||
ValueListenable<ScaffoldGeometry> geometryListenable; |
|||
|
|||
public override void didChangeDependencies() { |
|||
base.didChangeDependencies(); |
|||
this.geometryListenable = Scaffold.geometryOf(this.context); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
CustomClipper<Path> clipper = this.widget.shape != null |
|||
? (CustomClipper<Path>) new _BottomAppBarClipper( |
|||
geometry: this.geometryListenable, |
|||
shape: this.widget.shape, |
|||
notchMargin: this.widget.notchMargin |
|||
) |
|||
: new ShapeBorderClipper(shape: new RoundedRectangleBorder()); |
|||
return new PhysicalShape( |
|||
clipper: clipper, |
|||
elevation: this.widget.elevation, |
|||
color: this.widget.color ?? Theme.of(context).bottomAppBarColor, |
|||
clipBehavior: this.widget.clipBehavior, |
|||
child: new Material( |
|||
type: MaterialType.transparency, |
|||
child: this.widget.child == null |
|||
? null |
|||
: new SafeArea(child: this.widget.child) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
class _BottomAppBarClipper : CustomClipper<Path> { |
|||
public _BottomAppBarClipper( |
|||
ValueListenable<ScaffoldGeometry> geometry, |
|||
NotchedShape shape, |
|||
float notchMargin |
|||
) : base(reclip: geometry) { |
|||
D.assert(geometry != null); |
|||
D.assert(shape != null); |
|||
D.assert(notchMargin != null); |
|||
this.geometry = geometry; |
|||
this.shape = shape; |
|||
this.notchMargin = notchMargin; |
|||
} |
|||
|
|||
public readonly ValueListenable<ScaffoldGeometry> geometry; |
|||
public readonly NotchedShape shape; |
|||
public readonly float notchMargin; |
|||
|
|||
public override Path getClip(Size size) { |
|||
Rect appBar = Offset.zero & size; |
|||
if (this.geometry.value.floatingActionButtonArea == null) { |
|||
Path path = new Path(); |
|||
path.addRect(appBar); |
|||
return path; |
|||
} |
|||
|
|||
Rect button = this.geometry.value.floatingActionButtonArea |
|||
.translate(0.0f, (this.geometry.value.bottomNavigationBarTop * -1.0f) ?? 0.0f); |
|||
|
|||
return this.shape.getOuterPath(appBar, button.inflate(this.notchMargin)); |
|||
} |
|||
|
|||
public override bool shouldReclip(CustomClipper<Path> oldClipper) { |
|||
return (oldClipper as _BottomAppBarClipper).geometry != this.geometry; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: aa89369405044a62a19225b2c20815f6 |
|||
timeCreated: 1553156127 |
|
|||
using System; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.scheduler; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
|
|||
namespace Unity.UIWidgets.material { |
|||
class RadioUtils { |
|||
public const float _kOuterRadius = 8.0f; |
|||
public const float _kInnerRadius = 4.5f; |
|||
} |
|||
|
|||
public class Radio<T> : StatefulWidget where T : class { |
|||
public Radio( |
|||
Key key = null, |
|||
T value = null, |
|||
T groupValue = null, |
|||
ValueChanged<T> onChanged = null, |
|||
Color activeColor = null, |
|||
MaterialTapTargetSize? materialTapTargetSize = null |
|||
) : base(key: key) { |
|||
D.assert(value != null); |
|||
D.assert(groupValue != null); |
|||
D.assert(onChanged != null); |
|||
this.value = value; |
|||
this.groupValue = groupValue; |
|||
this.onChanged = onChanged; |
|||
this.activeColor = activeColor; |
|||
this.materialTapTargetSize = materialTapTargetSize; |
|||
} |
|||
|
|||
public readonly T value; |
|||
|
|||
public readonly T groupValue; |
|||
|
|||
public readonly ValueChanged<T> onChanged; |
|||
|
|||
public readonly Color activeColor; |
|||
|
|||
public readonly MaterialTapTargetSize? materialTapTargetSize; |
|||
|
|||
public override State createState() { |
|||
return new _RadioState<T>(); |
|||
} |
|||
} |
|||
|
|||
class _RadioState<T> : TickerProviderStateMixin<Radio<T>> where T : class { |
|||
bool _enabled { |
|||
get { return this.widget.onChanged != null; } |
|||
} |
|||
|
|||
Color _getInactiveColor(ThemeData themeData) { |
|||
return this._enabled ? themeData.unselectedWidgetColor : themeData.disabledColor; |
|||
} |
|||
|
|||
void _handleChanged(bool? selected) { |
|||
if (selected == true) { |
|||
this.widget.onChanged(this.widget.value); |
|||
} |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
D.assert(MaterialD.debugCheckHasMaterial(context)); |
|||
ThemeData themeData = Theme.of(context); |
|||
Size size; |
|||
switch (this.widget.materialTapTargetSize ?? themeData.materialTapTargetSize) { |
|||
case MaterialTapTargetSize.padded: |
|||
size = new Size(2 * Constants.kRadialReactionRadius + 8.0f, |
|||
2 * Constants.kRadialReactionRadius + 8.0f); |
|||
break; |
|||
case MaterialTapTargetSize.shrinkWrap: |
|||
size = new Size(2 * Constants.kRadialReactionRadius, 2 * Constants.kRadialReactionRadius); |
|||
break; |
|||
default: |
|||
throw new Exception("Unknown material tap target size"); |
|||
} |
|||
|
|||
BoxConstraints additionalConstraints = BoxConstraints.tight(size); |
|||
return new _RadioRenderObjectWidget( |
|||
selected: this.widget.value == this.widget.groupValue, |
|||
activeColor: this.widget.activeColor ?? themeData.toggleableActiveColor, |
|||
inactiveColor: this._getInactiveColor(themeData), |
|||
onChanged: this._enabled ? this._handleChanged : (ValueChanged<bool?>) null, |
|||
additionalConstraints: additionalConstraints, |
|||
vsync: this |
|||
); |
|||
} |
|||
} |
|||
|
|||
class _RadioRenderObjectWidget : LeafRenderObjectWidget { |
|||
public _RadioRenderObjectWidget( |
|||
Key key = null, |
|||
bool? selected = null, |
|||
Color activeColor = null, |
|||
Color inactiveColor = null, |
|||
BoxConstraints additionalConstraints = null, |
|||
ValueChanged<bool?> onChanged = null, |
|||
TickerProvider vsync = null |
|||
) : base(key: key) { |
|||
D.assert(selected != null); |
|||
D.assert(activeColor != null); |
|||
D.assert(inactiveColor != null); |
|||
D.assert(additionalConstraints != null); |
|||
D.assert(vsync != null); |
|||
this.selected = selected; |
|||
this.activeColor = activeColor; |
|||
this.inactiveColor = inactiveColor; |
|||
this.additionalConstraints = additionalConstraints; |
|||
this.onChanged = onChanged; |
|||
this.vsync = vsync; |
|||
} |
|||
|
|||
public readonly bool? selected; |
|||
public readonly Color activeColor; |
|||
public readonly Color inactiveColor; |
|||
public readonly BoxConstraints additionalConstraints; |
|||
public readonly ValueChanged<bool?> onChanged; |
|||
public readonly TickerProvider vsync; |
|||
|
|||
public override RenderObject createRenderObject(BuildContext context) { |
|||
return new _RenderRadio( |
|||
value: this.selected, |
|||
activeColor: this.activeColor, |
|||
inactiveColor: this.inactiveColor, |
|||
onChanged: this.onChanged, |
|||
vsync: this.vsync, |
|||
additionalConstraints: this.additionalConstraints |
|||
); |
|||
} |
|||
|
|||
public override void updateRenderObject(BuildContext context, RenderObject _renderObject) { |
|||
_RenderRadio renderObject = _renderObject as _RenderRadio; |
|||
renderObject.value = this.selected; |
|||
renderObject.activeColor = this.activeColor; |
|||
renderObject.inactiveColor = this.inactiveColor; |
|||
renderObject.onChanged = this.onChanged; |
|||
renderObject.additionalConstraints = this.additionalConstraints; |
|||
renderObject.vsync = this.vsync; |
|||
} |
|||
} |
|||
|
|||
class _RenderRadio : RenderToggleable { |
|||
public _RenderRadio( |
|||
bool? value, |
|||
Color activeColor, |
|||
Color inactiveColor, |
|||
ValueChanged<bool?> onChanged, |
|||
BoxConstraints additionalConstraints, |
|||
TickerProvider vsync |
|||
) : base( |
|||
value: value, |
|||
tristate: false, |
|||
activeColor: activeColor, |
|||
inactiveColor: inactiveColor, |
|||
onChanged: onChanged, |
|||
additionalConstraints: additionalConstraints, |
|||
vsync: vsync |
|||
) { |
|||
} |
|||
|
|||
public override void paint(PaintingContext context, Offset offset) { |
|||
Canvas canvas = context.canvas; |
|||
|
|||
this.paintRadialReaction(canvas, offset, |
|||
new Offset(Constants.kRadialReactionRadius, Constants.kRadialReactionRadius)); |
|||
|
|||
Offset center = (offset & this.size).center; |
|||
Color radioColor = this.onChanged != null ? this.activeColor : this.inactiveColor; |
|||
|
|||
Paint paint = new Paint(); |
|||
paint.color = Color.lerp(this.inactiveColor, radioColor, this.position.value); |
|||
paint.style = PaintingStyle.stroke; |
|||
paint.strokeWidth = 2.0f; |
|||
canvas.drawCircle(center, RadioUtils._kOuterRadius, paint); |
|||
|
|||
if (!this.position.isDismissed) { |
|||
paint.style = PaintingStyle.fill; |
|||
canvas.drawCircle(center, RadioUtils._kInnerRadius * this.position.value, paint); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 1328fb437a4047c49b51dfe3a2c3d106 |
|||
timeCreated: 1553154501 |
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.ui; |
|||
using UnityEngine; |
|||
using Rect = Unity.UIWidgets.ui.Rect; |
|||
|
|||
namespace Unity.UIWidgets.painting { |
|||
public abstract class NotchedShape { |
|||
public NotchedShape() { |
|||
} |
|||
|
|||
public abstract Path getOuterPath(Rect host, Rect guest); |
|||
} |
|||
|
|||
public class CircularNotchedRectangle : NotchedShape { |
|||
public CircularNotchedRectangle() { |
|||
} |
|||
|
|||
public override Path getOuterPath(Rect host, Rect guest) { |
|||
if (!host.overlaps(guest)) { |
|||
Path path = new Path(); |
|||
path.addRect(host); |
|||
return path; |
|||
} |
|||
|
|||
float notchRadius = guest.width / 2.0f; |
|||
|
|||
|
|||
const float s1 = 15.0f; |
|||
const float s2 = 1.0f; |
|||
|
|||
float r = notchRadius; |
|||
float a = -1.0f * r - s2; |
|||
float b = host.top - guest.center.dy; |
|||
|
|||
float n2 = Mathf.Sqrt(b * b * r * r * (a * a + b * b - r * r)); |
|||
float p2xA = ((a * r * r) - n2) / (a * a + b * b); |
|||
float p2xB = ((a * r * r) + n2) / (a * a + b * b); |
|||
float p2yA = Mathf.Sqrt(r * r - p2xA * p2xA); |
|||
float p2yB = Mathf.Sqrt(r * r - p2xB * p2xB); |
|||
|
|||
List<Offset> p = new List<Offset>(6); |
|||
|
|||
p[0] = new Offset(a - s1, b); |
|||
p[1] = new Offset(a, b); |
|||
float cmp = b < 0 ? -1.0f : 1.0f; |
|||
p[2] = cmp * p2yA > cmp * p2yB ? new Offset(p2xA, p2yA) : new Offset(p2xB, p2yB); |
|||
|
|||
p[3] = new Offset(-1.0f * p[2].dx, p[2].dy); |
|||
p[4] = new Offset(-1.0f * p[1].dx, p[1].dy); |
|||
p[5] = new Offset(-1.0f * p[0].dx, p[0].dy); |
|||
|
|||
for (int i = 0; i < p.Count; i += 1) { |
|||
p[i] += guest.center; |
|||
} |
|||
|
|||
Path ret = new Path(); |
|||
ret.moveTo(host.left, host.top); |
|||
ret.lineTo(p[0].dx, p[0].dy); |
|||
ret.quadTo(p[1].dx, p[1].dy, p[2].dx, p[2].dy); |
|||
// TODO: replace this lineTo() with arcToPoint when arcToPoint is ready
|
|||
ret.lineTo(p[3].dx, p[3].dy); |
|||
// ret.arcToPoint(p[3], p[3], radius: Radius.circular(notchRadius), clockwise: false);
|
|||
ret.quadTo(p[4].dx, p[4].dy, p[5].dx, p[5].dy); |
|||
ret.lineTo(host.right, host.top); |
|||
ret.lineTo(host.right, host.bottom); |
|||
ret.lineTo(host.left, host.bottom); |
|||
ret.close(); |
|||
return ret; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: c89c524fa7c242aa91900b63841be8b3 |
|||
timeCreated: 1553153571 |
|
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.gestures; |
|||
using Unity.UIWidgets.material; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using UnityEngine; |
|||
using Canvas = Unity.UIWidgets.ui.Canvas; |
|||
using Color = Unity.UIWidgets.ui.Color; |
|||
using Material = Unity.UIWidgets.material.Material; |
|||
using Rect = Unity.UIWidgets.ui.Rect; |
|||
|
|||
namespace UIWidgetsGallery.gallery { |
|||
public class BottomAppBarDemo : StatefulWidget { |
|||
public const string routeName = "/material/bottom_app_bar"; |
|||
|
|||
public override State createState() { |
|||
return new _BottomAppBarDemoState(); |
|||
} |
|||
} |
|||
|
|||
|
|||
class _BottomAppBarDemoState : State<BottomAppBarDemo> { |
|||
static readonly GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>.key(); |
|||
|
|||
|
|||
static readonly _ChoiceValue<Widget> kNoFab = new _ChoiceValue<Widget>( |
|||
title: "None", |
|||
label: "do not show a floating action button", |
|||
value: null |
|||
); |
|||
|
|||
static readonly _ChoiceValue<Widget> kCircularFab = new _ChoiceValue<Widget>( |
|||
title: "Circular", |
|||
label: "circular floating action button", |
|||
value: new FloatingActionButton( |
|||
onPressed: _showSnackbar, |
|||
child: new Icon(Icons.add), |
|||
backgroundColor: Colors.orange |
|||
) |
|||
); |
|||
|
|||
static readonly _ChoiceValue<Widget> kDiamondFab = new _ChoiceValue<Widget>( |
|||
title: "Diamond", |
|||
label: "diamond shape floating action button", |
|||
value: new _DiamondFab( |
|||
onPressed: _showSnackbar, |
|||
child: new Icon(Icons.add) |
|||
) |
|||
); |
|||
|
|||
|
|||
static readonly _ChoiceValue<bool> kShowNotchTrue = new _ChoiceValue<bool>( |
|||
title: "On", |
|||
label: "show bottom appbar notch", |
|||
value: true |
|||
); |
|||
|
|||
static readonly _ChoiceValue<bool> kShowNotchFalse = new _ChoiceValue<bool>( |
|||
title: "Off", |
|||
label: "do not show bottom appbar notch", |
|||
value: false |
|||
); |
|||
|
|||
|
|||
static readonly _ChoiceValue<FloatingActionButtonLocation> kFabEndDocked = |
|||
new _ChoiceValue<FloatingActionButtonLocation>( |
|||
title: "Attached - End", |
|||
label: "floating action button is docked at the end of the bottom app bar", |
|||
value: FloatingActionButtonLocation.endDocked |
|||
); |
|||
|
|||
static readonly _ChoiceValue<FloatingActionButtonLocation> kFabCenterDocked = |
|||
new _ChoiceValue<FloatingActionButtonLocation>( |
|||
title: "Attached - Center", |
|||
label: "floating action button is docked at the center of the bottom app bar", |
|||
value: FloatingActionButtonLocation.centerDocked |
|||
); |
|||
|
|||
static readonly _ChoiceValue<FloatingActionButtonLocation> kFabEndFloat = |
|||
new _ChoiceValue<FloatingActionButtonLocation>( |
|||
title: "Free - End", |
|||
label: "floating action button floats above the end of the bottom app bar", |
|||
value: FloatingActionButtonLocation.endFloat |
|||
); |
|||
|
|||
static readonly _ChoiceValue<FloatingActionButtonLocation> kFabCenterFloat = |
|||
new _ChoiceValue<FloatingActionButtonLocation>( |
|||
title: "Free - Center", |
|||
label: "floating action button is floats above the center of the bottom app bar", |
|||
value: FloatingActionButtonLocation.centerFloat |
|||
); |
|||
|
|||
static void _showSnackbar() { |
|||
const string text = |
|||
"When the Scaffold's floating action button location changes, " + |
|||
"the floating action button animates to its new position." + |
|||
"The BottomAppBar adapts its shape appropriately."; |
|||
_scaffoldKey.currentState.showSnackBar( |
|||
new SnackBar(content: new Text(text)) |
|||
); |
|||
} |
|||
|
|||
|
|||
static readonly List<_NamedColor> kBabColors = new List<_NamedColor> { |
|||
new _NamedColor(null, "Clear"), |
|||
new _NamedColor(new Color(0xFFFFC100), "Orange"), |
|||
new _NamedColor(new Color(0xFF91FAFF), "Light Blue"), |
|||
new _NamedColor(new Color(0xFF00D1FF), "Cyan"), |
|||
new _NamedColor(new Color(0xFF00BCFF), "Cerulean"), |
|||
new _NamedColor(new Color(0xFF009BEE), "Blue") |
|||
}; |
|||
|
|||
_ChoiceValue<Widget> _fabShape = kCircularFab; |
|||
_ChoiceValue<bool> _showNotch = kShowNotchTrue; |
|||
_ChoiceValue<FloatingActionButtonLocation> _fabLocation = kFabEndDocked; |
|||
Color _babColor = kBabColors.First().color; |
|||
|
|||
void _onShowNotchChanged(_ChoiceValue<bool> value) { |
|||
this.setState(() => { this._showNotch = value; }); |
|||
} |
|||
|
|||
void _onFabShapeChanged(_ChoiceValue<Widget> value) { |
|||
this.setState(() => { this._fabShape = value; }); |
|||
} |
|||
|
|||
void _onFabLocationChanged(_ChoiceValue<FloatingActionButtonLocation> value) { |
|||
this.setState(() => { this._fabLocation = value; }); |
|||
} |
|||
|
|||
void _onBabColorChanged(Color value) { |
|||
this.setState(() => { this._babColor = value; }); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new Scaffold( |
|||
key: _scaffoldKey, |
|||
appBar: new AppBar( |
|||
title: new Text("Bottom app bar"), |
|||
elevation: 0.0f, |
|||
actions: new List<Widget> { |
|||
new MaterialDemoDocumentationButton(BottomAppBarDemo.routeName), |
|||
new IconButton( |
|||
icon: new Icon(Icons.sentiment_very_satisfied), |
|||
onPressed: () => { |
|||
this.setState(() => { |
|||
this._fabShape = this._fabShape == kCircularFab ? kDiamondFab : kCircularFab; |
|||
}); |
|||
} |
|||
) |
|||
} |
|||
), |
|||
body: new ListView( |
|||
padding: EdgeInsets.only(bottom: 88.0f), |
|||
children: new List<Widget> { |
|||
new _AppBarDemoHeading("FAB Shape"), |
|||
|
|||
new _RadioItem<Widget>(kCircularFab, this._fabShape, this._onFabShapeChanged), |
|||
new _RadioItem<Widget>(kDiamondFab, this._fabShape, this._onFabShapeChanged), |
|||
new _RadioItem<Widget>(kNoFab, this._fabShape, this._onFabShapeChanged), |
|||
|
|||
new Divider(), |
|||
new _AppBarDemoHeading("Notch"), |
|||
|
|||
new _RadioItem<bool>(kShowNotchTrue, this._showNotch, this._onShowNotchChanged), |
|||
new _RadioItem<bool>(kShowNotchFalse, this._showNotch, this._onShowNotchChanged), |
|||
|
|||
new Divider(), |
|||
new _AppBarDemoHeading("FAB Position"), |
|||
|
|||
new _RadioItem<FloatingActionButtonLocation>(kFabEndDocked, this._fabLocation, |
|||
this._onFabLocationChanged), |
|||
new _RadioItem<FloatingActionButtonLocation>(kFabCenterDocked, this._fabLocation, |
|||
this._onFabLocationChanged), |
|||
new _RadioItem<FloatingActionButtonLocation>(kFabEndFloat, this._fabLocation, |
|||
this._onFabLocationChanged), |
|||
new _RadioItem<FloatingActionButtonLocation>(kFabCenterFloat, this._fabLocation, |
|||
this._onFabLocationChanged), |
|||
|
|||
new Divider(), |
|||
new _AppBarDemoHeading("App bar color"), |
|||
|
|||
new _ColorsItem(kBabColors, this._babColor, this._onBabColorChanged) |
|||
} |
|||
), |
|||
floatingActionButton: |
|||
this._fabShape.value, |
|||
floatingActionButtonLocation: |
|||
this._fabLocation.value, |
|||
bottomNavigationBar: new _DemoBottomAppBar( |
|||
color: this._babColor, |
|||
fabLocation: this._fabLocation.value, |
|||
shape: this._selectNotch() |
|||
) |
|||
); |
|||
} |
|||
|
|||
NotchedShape _selectNotch() { |
|||
if (!this._showNotch.value) { |
|||
return null; |
|||
} |
|||
|
|||
if (this._fabShape == kCircularFab) { |
|||
return new CircularNotchedRectangle(); |
|||
} |
|||
|
|||
if (this._fabShape == kDiamondFab) { |
|||
return new _DiamondNotchedRectangle(); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
|
|||
class _ChoiceValue<T> { |
|||
public _ChoiceValue(T value, string title, string label) { |
|||
this.value = value; |
|||
this.title = title; |
|||
this.label = label; |
|||
} |
|||
|
|||
public readonly T value; |
|||
public readonly string title; |
|||
string label; // For the Semantics widget that contains title
|
|||
|
|||
public override string ToString() { |
|||
return $"{this.GetType()}('{this.title}')"; |
|||
} |
|||
} |
|||
|
|||
class _RadioItem<T> : StatelessWidget { |
|||
public _RadioItem(_ChoiceValue<T> value, _ChoiceValue<T> groupValue, ValueChanged<_ChoiceValue<T>> onChanged) { |
|||
this.value = value; |
|||
this.groupValue = groupValue; |
|||
this.onChanged = onChanged; |
|||
} |
|||
|
|||
_ChoiceValue<T> value; |
|||
_ChoiceValue<T> groupValue; |
|||
ValueChanged<_ChoiceValue<T>> onChanged; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
ThemeData theme = Theme.of(context); |
|||
return new Container( |
|||
height: 56.0f, |
|||
padding: EdgeInsets.only(left: 16.0f), |
|||
alignment: Alignment.centerLeft, |
|||
child: new Row( |
|||
children: new List<Widget> { |
|||
new Radio<_ChoiceValue<T>>( |
|||
value: this.value, |
|||
groupValue: this.groupValue, |
|||
onChanged: this.onChanged |
|||
), |
|||
new Expanded( |
|||
child: new GestureDetector( |
|||
behavior: HitTestBehavior.opaque, |
|||
onTap: () => { this.onChanged(this.value); }, |
|||
child: new Text(this.value.title, |
|||
style: theme.textTheme.subhead |
|||
) |
|||
) |
|||
) |
|||
} |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
class _NamedColor { |
|||
public _NamedColor(Color color, string name) { |
|||
this.color = color; |
|||
this.name = name; |
|||
} |
|||
|
|||
public readonly Color color; |
|||
public readonly string name; |
|||
} |
|||
|
|||
class _ColorsItem : StatelessWidget { |
|||
public _ColorsItem(List<_NamedColor> colors, Color selectedColor, ValueChanged<Color> onChanged) { |
|||
this.colors = colors; |
|||
this.selectedColor = selectedColor; |
|||
this.onChanged = onChanged; |
|||
} |
|||
|
|||
List<_NamedColor> colors; |
|||
public readonly Color selectedColor; |
|||
ValueChanged<Color> onChanged; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new Row( |
|||
mainAxisAlignment: MainAxisAlignment.spaceEvenly, |
|||
children: this.colors.Select<_NamedColor, Widget>((_NamedColor namedColor) => { |
|||
return new RawMaterialButton( |
|||
onPressed: () => { this.onChanged(namedColor.color); }, |
|||
constraints: BoxConstraints.tightFor( |
|||
width: 32.0f, |
|||
height: 32.0f |
|||
), |
|||
fillColor: namedColor.color, |
|||
shape: new CircleBorder( |
|||
side: new BorderSide( |
|||
color: namedColor.color == this.selectedColor ? Colors.black : new Color(0xFFD5D7DA), |
|||
width: 2.0f |
|||
) |
|||
) |
|||
); |
|||
}).ToList() |
|||
); |
|||
} |
|||
} |
|||
|
|||
class _AppBarDemoHeading : StatelessWidget { |
|||
public _AppBarDemoHeading(string text) { |
|||
this.text = text; |
|||
} |
|||
|
|||
public readonly string text; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
ThemeData theme = Theme.of(context); |
|||
return new Container( |
|||
height: 48.0f, |
|||
padding: EdgeInsets.only(left: 56.0f), |
|||
alignment: Alignment.centerLeft, |
|||
child: new Text(this.text, |
|||
style: theme.textTheme.body1.copyWith( |
|||
color: theme.primaryColor |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
class _DemoBottomAppBar : StatelessWidget { |
|||
public _DemoBottomAppBar( |
|||
Color color = null, |
|||
FloatingActionButtonLocation fabLocation = null, |
|||
NotchedShape shape = null |
|||
) { |
|||
this.color = color; |
|||
this.fabLocation = fabLocation; |
|||
this.shape = shape; |
|||
} |
|||
|
|||
public readonly Color color; |
|||
public readonly FloatingActionButtonLocation fabLocation; |
|||
public readonly NotchedShape shape; |
|||
|
|||
static readonly List<FloatingActionButtonLocation> kCenterLocations = new List<FloatingActionButtonLocation> { |
|||
FloatingActionButtonLocation.centerDocked, |
|||
FloatingActionButtonLocation.centerFloat |
|||
}; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
List<Widget> rowContents = new List<Widget> { |
|||
new IconButton( |
|||
icon: new Icon(Icons.menu), |
|||
onPressed: () => { |
|||
BottomSheetUtils.showModalBottomSheet<object>( |
|||
context: context, |
|||
builder: (BuildContext _context) => new _DemoDrawer() |
|||
); |
|||
} |
|||
) |
|||
}; |
|||
|
|||
if (kCenterLocations.Contains(this.fabLocation)) { |
|||
rowContents.Add( |
|||
new Expanded(child: new SizedBox()) |
|||
); |
|||
} |
|||
|
|||
rowContents.AddRange(new List<Widget> { |
|||
new IconButton( |
|||
icon: new Icon(Icons.search), |
|||
onPressed: () => { |
|||
Scaffold.of(context).showSnackBar( |
|||
new SnackBar(content: new Text("This is a dummy search action.")) |
|||
); |
|||
} |
|||
), |
|||
new IconButton( |
|||
icon: new Icon( |
|||
Theme.of(context).platform == RuntimePlatform.Android |
|||
? Icons.more_vert |
|||
: Icons.more_horiz |
|||
), |
|||
onPressed: () => { |
|||
Scaffold.of(context).showSnackBar( |
|||
new SnackBar(content: new Text("This is a dummy menu action.")) |
|||
); |
|||
} |
|||
) |
|||
}); |
|||
|
|||
return new BottomAppBar( |
|||
color: this.color, |
|||
child: new Row(children: rowContents), |
|||
shape: this.shape |
|||
); |
|||
} |
|||
} |
|||
|
|||
class _DemoDrawer : StatelessWidget { |
|||
public _DemoDrawer() { |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new Drawer( |
|||
child: new Column( |
|||
children: new List<Widget> { |
|||
new ListTile( |
|||
leading: new Icon(Icons.search), |
|||
title: new Text("Search") |
|||
), |
|||
new ListTile( |
|||
leading: new Icon(Icons.threed_rotation), |
|||
title: new Text("3D") |
|||
) |
|||
} |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
class _DiamondFab : StatelessWidget { |
|||
public _DiamondFab( |
|||
Widget child, |
|||
VoidCallback onPressed |
|||
) { |
|||
this.child = child; |
|||
this.onPressed = onPressed; |
|||
} |
|||
|
|||
public readonly Widget child; |
|||
public readonly VoidCallback onPressed; |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
return new Material( |
|||
shape: new _DiamondBorder(), |
|||
color: Colors.orange, |
|||
child: new InkWell( |
|||
onTap: this.onPressed == null ? (GestureTapCallback) null : () => { this.onPressed(); }, |
|||
child: new Container( |
|||
width: 56.0f, |
|||
height: 56.0f, |
|||
child: IconTheme.merge( |
|||
data: new IconThemeData(color: Theme.of(context).accentIconTheme.color), |
|||
child: this.child |
|||
) |
|||
) |
|||
), |
|||
elevation: 6.0f |
|||
); |
|||
} |
|||
} |
|||
|
|||
class _DiamondNotchedRectangle : NotchedShape { |
|||
public _DiamondNotchedRectangle() { |
|||
} |
|||
|
|||
public override Path getOuterPath(Rect host, Rect guest) { |
|||
if (!host.overlaps(guest)) { |
|||
Path path = new Path(); |
|||
path.addRect(host); |
|||
return path; |
|||
} |
|||
|
|||
D.assert(guest.width > 0.0f); |
|||
|
|||
Rect intersection = guest.intersect(host); |
|||
float notchToCenter = |
|||
intersection.height * (guest.height / 2.0f) |
|||
/ (guest.width / 2.0f); |
|||
|
|||
Path ret = new Path(); |
|||
ret.moveTo(host.left, host.top); |
|||
ret.lineTo(guest.center.dx - notchToCenter, host.top); |
|||
ret.lineTo(guest.left + guest.width / 2.0f, guest.bottom); |
|||
ret.lineTo(guest.center.dx + notchToCenter, host.top); |
|||
ret.lineTo(host.right, host.top); |
|||
ret.lineTo(host.right, host.bottom); |
|||
ret.lineTo(host.left, host.bottom); |
|||
ret.close(); |
|||
return ret; |
|||
} |
|||
} |
|||
|
|||
class _DiamondBorder : ShapeBorder { |
|||
public _DiamondBorder() { |
|||
} |
|||
|
|||
public override EdgeInsets dimensions { |
|||
get { return EdgeInsets.only(); } |
|||
} |
|||
|
|||
public override Path getInnerPath(Rect rect) { |
|||
return this.getOuterPath(rect); |
|||
} |
|||
|
|||
public override Path getOuterPath(Rect rect) { |
|||
Path path = new Path(); |
|||
path.moveTo(rect.left + rect.width / 2.0f, rect.top); |
|||
path.lineTo(rect.right, rect.top + rect.height / 2.0f); |
|||
path.lineTo(rect.left + rect.width / 2.0f, rect.bottom); |
|||
path.lineTo(rect.left, rect.top + rect.height / 2.0f); |
|||
path.close(); |
|||
return path; |
|||
} |
|||
|
|||
public override void paint(Canvas canvas, Rect rect) { |
|||
} |
|||
|
|||
public override ShapeBorder scale(float t) { |
|||
return null; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 7c1d20efeafe42699212e2147c0828af |
|||
timeCreated: 1553149093 |
撰写
预览
正在加载...
取消
保存
Reference in new issue