您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
480 行
20 KiB
480 行
20 KiB
using System.Collections.Generic;
|
|
using uiwidgets;
|
|
using UIWidgetsGallery.gallery;
|
|
using Unity.UIWidgets.animation;
|
|
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 UnityEngine;
|
|
using Canvas = Unity.UIWidgets.ui.Canvas;
|
|
using Color = Unity.UIWidgets.ui.Color;
|
|
|
|
namespace UIWidgetsGallery.demo.material
|
|
{
|
|
internal class SliderDemo : StatefulWidget
|
|
{
|
|
public static readonly string routeName = "/material/slider";
|
|
|
|
public override State createState()
|
|
{
|
|
return new _SliderDemoState();
|
|
}
|
|
}
|
|
|
|
internal static class SliderDemoUtils
|
|
{
|
|
public static Path _downTriangle(float size, Offset thumbCenter, bool invert = false)
|
|
{
|
|
Path thumbPath = new Path();
|
|
float height = Mathf.Sqrt(3.0f) / 2.0f;
|
|
float centerHeight = size * height / 3.0f;
|
|
float halfSize = size / 2.0f;
|
|
float sign = invert ? -1.0f : 1.0f;
|
|
thumbPath.moveTo(thumbCenter.dx - halfSize, thumbCenter.dy + sign * centerHeight);
|
|
thumbPath.lineTo(thumbCenter.dx, thumbCenter.dy - 2.0f * sign * centerHeight);
|
|
thumbPath.lineTo(thumbCenter.dx + halfSize, thumbCenter.dy + sign * centerHeight);
|
|
thumbPath.close();
|
|
return thumbPath;
|
|
}
|
|
|
|
public static Path _rightTriangle(float size, Offset thumbCenter, bool invert = false)
|
|
{
|
|
Path thumbPath = new Path();
|
|
float halfSize = size / 2.0f;
|
|
float sign = invert ? -1.0f : 1.0f;
|
|
thumbPath.moveTo(thumbCenter.dx + halfSize * sign, thumbCenter.dy);
|
|
thumbPath.lineTo(thumbCenter.dx - halfSize * sign, thumbCenter.dy - size);
|
|
thumbPath.lineTo(thumbCenter.dx - halfSize * sign, thumbCenter.dy + size);
|
|
thumbPath.close();
|
|
return thumbPath;
|
|
}
|
|
|
|
public static Path _upTriangle(float size, Offset thumbCenter)
|
|
{
|
|
return _downTriangle(size, thumbCenter, invert: true);
|
|
}
|
|
|
|
public static Path _leftTriangle(float size, Offset thumbCenter)
|
|
{
|
|
return _rightTriangle(size, thumbCenter, invert: true);
|
|
}
|
|
}
|
|
|
|
internal class _CustomRangeThumbShape : RangeSliderThumbShape
|
|
{
|
|
private const float _thumbSize = 4.0f;
|
|
private const float _disabledThumbSize = 3.0f;
|
|
|
|
public override Size getPreferredSize(bool isEnabled, bool isDiscrete)
|
|
{
|
|
return isEnabled ? Size.fromRadius(_thumbSize) : Size.fromRadius(_disabledThumbSize);
|
|
}
|
|
|
|
private static readonly Animatable<float> sizeTween = new FloatTween(
|
|
begin: _disabledThumbSize,
|
|
end: _thumbSize
|
|
);
|
|
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset center,
|
|
Animation<float> activationAnimation = null,
|
|
Animation<float> enableAnimation = null,
|
|
bool isDiscrete = false,
|
|
bool isEnabled = false,
|
|
bool? isOnTop = null,
|
|
TextDirection? textDirection = null,
|
|
SliderThemeData sliderTheme = null,
|
|
Thumb? thumb = null
|
|
)
|
|
{
|
|
Canvas canvas = context.canvas;
|
|
ColorTween colorTween = new ColorTween(
|
|
begin: sliderTheme.disabledThumbColor,
|
|
end: sliderTheme.thumbColor
|
|
);
|
|
|
|
float size = _thumbSize * sizeTween.evaluate(enableAnimation);
|
|
Path thumbPath = null;
|
|
switch (textDirection)
|
|
{
|
|
case TextDirection.rtl:
|
|
switch (thumb)
|
|
{
|
|
case Thumb.start:
|
|
thumbPath = SliderDemoUtils._rightTriangle(size, center);
|
|
break;
|
|
case Thumb.end:
|
|
thumbPath = SliderDemoUtils._leftTriangle(size, center);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
case TextDirection.ltr:
|
|
switch (thumb)
|
|
{
|
|
case Thumb.start:
|
|
thumbPath = SliderDemoUtils._leftTriangle(size, center);
|
|
break;
|
|
case Thumb.end:
|
|
thumbPath = SliderDemoUtils._rightTriangle(size, center);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
canvas.drawPath(thumbPath, new Paint {color = colorTween.evaluate(enableAnimation)});
|
|
}
|
|
}
|
|
|
|
internal class _CustomThumbShape : SliderComponentShape
|
|
{
|
|
private const float _thumbSize = 4.0f;
|
|
private const float _disabledThumbSize = 3.0f;
|
|
|
|
public override Size getPreferredSize(bool isEnabled, bool isDiscrete, TextPainter textPainter)
|
|
{
|
|
return isEnabled ? Size.fromRadius(_thumbSize) : Size.fromRadius(_disabledThumbSize);
|
|
}
|
|
|
|
private static readonly Animatable<float> sizeTween = new FloatTween(
|
|
begin: _disabledThumbSize,
|
|
end: _thumbSize
|
|
);
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset center,
|
|
Animation<float> activationAnimation = null,
|
|
Animation<float> enableAnimation = null,
|
|
bool isDiscrete = false,
|
|
TextPainter labelPainter = null,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
TextDirection? textDirection = null,
|
|
float? value = null)
|
|
{
|
|
Canvas canvas = context.canvas;
|
|
ColorTween colorTween = new ColorTween(
|
|
begin: sliderTheme.disabledThumbColor,
|
|
end: sliderTheme.thumbColor
|
|
);
|
|
float size = _thumbSize * sizeTween.evaluate(enableAnimation);
|
|
Path thumbPath = SliderDemoUtils._downTriangle(size, center);
|
|
canvas.drawPath(thumbPath, new Paint {color = colorTween.evaluate(enableAnimation)});
|
|
}
|
|
}
|
|
|
|
internal class _CustomValueIndicatorShape : SliderComponentShape
|
|
{
|
|
private const float _indicatorSize = 4.0f;
|
|
private const float _disabledIndicatorSize = 3.0f;
|
|
private const float _slideUpHeight = 40.0f;
|
|
|
|
public override Size getPreferredSize(bool isEnabled, bool isDiscrete, TextPainter textPainter)
|
|
{
|
|
return Size.fromRadius(isEnabled ? _indicatorSize : _disabledIndicatorSize);
|
|
}
|
|
|
|
private static readonly Animatable<float> sizeTween = new FloatTween(
|
|
begin: _disabledIndicatorSize,
|
|
end: _indicatorSize
|
|
);
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset center,
|
|
Animation<float> activationAnimation = null,
|
|
Animation<float> enableAnimation = null,
|
|
bool isDiscrete = false,
|
|
TextPainter labelPainter = null,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
TextDirection? textDirection = null,
|
|
float? value = null)
|
|
{
|
|
Canvas canvas = context.canvas;
|
|
ColorTween enableColor = new ColorTween(
|
|
begin: sliderTheme.disabledThumbColor,
|
|
end: sliderTheme.valueIndicatorColor
|
|
);
|
|
|
|
Tween<float> slideUpTween = new FloatTween(
|
|
begin: 0.0f,
|
|
end: _slideUpHeight
|
|
);
|
|
float size = _indicatorSize * sizeTween.evaluate(enableAnimation);
|
|
Offset slideUpOffset = new Offset(0.0f, -slideUpTween.evaluate(activationAnimation));
|
|
Path thumbPath = SliderDemoUtils._upTriangle(size, center + slideUpOffset);
|
|
Color paintColor = enableColor.evaluate(enableAnimation)
|
|
.withAlpha((255.0f * activationAnimation.value).round());
|
|
canvas.drawPath(
|
|
thumbPath,
|
|
new Paint {color = paintColor}
|
|
);
|
|
canvas.drawLine(
|
|
center,
|
|
center + slideUpOffset,
|
|
new Paint
|
|
{
|
|
color = paintColor,
|
|
style = PaintingStyle.stroke,
|
|
strokeWidth = 2.0f
|
|
});
|
|
labelPainter.paint(canvas,
|
|
center + slideUpOffset + new Offset(-labelPainter.width / 2.0f, -labelPainter.height - 4.0f));
|
|
}
|
|
}
|
|
|
|
internal class _SliderDemoState : State<SliderDemo>
|
|
{
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
List<ComponentDemoTabData> demos = new List<ComponentDemoTabData>
|
|
{
|
|
new ComponentDemoTabData(
|
|
tabName: "SINGLE",
|
|
description: "Sliders containing 1 thumb",
|
|
demoWidget: new _Sliders(),
|
|
documentationUrl: "https://docs.flutter.io/flutter/material/Slider-class.html"
|
|
),
|
|
new ComponentDemoTabData(
|
|
tabName: "RANGE",
|
|
description: "Sliders containing 2 thumbs",
|
|
demoWidget: new _RangeSliders(),
|
|
documentationUrl: "https://docs.flutter.io/flutter/material/RangeSlider-class.html"
|
|
)
|
|
};
|
|
|
|
return new TabbedComponentDemoScaffold(
|
|
title: "Sliders",
|
|
demos: demos,
|
|
isScrollable: false,
|
|
showExampleCodeAction: false
|
|
);
|
|
}
|
|
}
|
|
|
|
internal class _Sliders : StatefulWidget
|
|
{
|
|
public override State createState()
|
|
{
|
|
return new _SlidersState();
|
|
}
|
|
}
|
|
|
|
internal class _SlidersState : State<_Sliders>
|
|
{
|
|
private float _continuousValue = 25.0f;
|
|
private float _discreteValue = 20.0f;
|
|
private float _discreteCustomValue = 25.0f;
|
|
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
ThemeData theme = Theme.of(context);
|
|
return new Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 40.0f),
|
|
child: new Column(
|
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
children: new List<Widget>
|
|
{
|
|
new Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: new List<Widget>
|
|
{
|
|
new SizedBox(
|
|
width: 64,
|
|
height: 48,
|
|
child: new TextField(
|
|
textAlign: TextAlign.center,
|
|
onSubmitted: (string value) =>
|
|
{
|
|
float.TryParse(value, out float newValue);
|
|
if (newValue != null && newValue != _continuousValue)
|
|
setState(() => { _continuousValue = newValue.clamp(0.0f, 100.0f); });
|
|
},
|
|
keyboardType: TextInputType.number,
|
|
controller: new TextEditingController(
|
|
text: $"{_continuousValue:F0}"
|
|
)
|
|
)
|
|
),
|
|
Slider.adaptive(
|
|
value: _continuousValue,
|
|
min: 0.0f,
|
|
max: 100.0f,
|
|
onChanged: (float value) => { setState(() => { _continuousValue = value; }); }
|
|
),
|
|
new Text("Continuous with Editable Numerical Value")
|
|
}
|
|
),
|
|
new Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: new List<Widget>
|
|
{
|
|
Slider.adaptive(value: 0.25f, onChanged: null),
|
|
new Text("Disabled")
|
|
}
|
|
),
|
|
new Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: new List<Widget>
|
|
{
|
|
Slider.adaptive(
|
|
value: _discreteValue,
|
|
min: 0.0f,
|
|
max: 200.0f,
|
|
divisions: 5,
|
|
label: $"{_discreteValue.round()}",
|
|
onChanged: (float value) => { setState(() => { _discreteValue = value; }); }
|
|
),
|
|
new Text("Discrete")
|
|
}
|
|
),
|
|
new Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: new List<Widget>
|
|
{
|
|
new SliderTheme(
|
|
data: theme.sliderTheme.copyWith(
|
|
activeTrackColor: Colors.deepPurple,
|
|
inactiveTrackColor: theme.colorScheme.onSurface.withOpacity(0.5f),
|
|
activeTickMarkColor: theme.colorScheme.onSurface.withOpacity(0.7f),
|
|
inactiveTickMarkColor: theme.colorScheme.surface.withOpacity(0.7f),
|
|
overlayColor: theme.colorScheme.onSurface.withOpacity(0.12f),
|
|
thumbColor: Colors.deepPurple,
|
|
valueIndicatorColor: Colors.deepPurpleAccent,
|
|
thumbShape: new _CustomThumbShape(),
|
|
valueIndicatorShape: new _CustomValueIndicatorShape(),
|
|
valueIndicatorTextStyle: theme.accentTextTheme.bodyText1.copyWith(
|
|
color: theme.colorScheme.onSurface)
|
|
),
|
|
child: new Slider(
|
|
value: _discreteCustomValue,
|
|
min: 0.0f,
|
|
max: 200.0f,
|
|
divisions: 5,
|
|
label: $"{_discreteCustomValue.round()}",
|
|
onChanged: (float value) =>
|
|
{
|
|
setState(() => { _discreteCustomValue = value; });
|
|
}
|
|
)
|
|
),
|
|
new Text("Discrete with Custom Theme")
|
|
}
|
|
)
|
|
}
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
internal class _RangeSliders : StatefulWidget
|
|
{
|
|
public override State createState()
|
|
{
|
|
return new _RangeSlidersState();
|
|
}
|
|
}
|
|
|
|
internal class _RangeSlidersState : State<_RangeSliders>
|
|
{
|
|
private RangeValues _continuousValues = new RangeValues(25.0f, 75.0f);
|
|
private RangeValues _discreteValues = new RangeValues(40.0f, 120.0f);
|
|
private RangeValues _discreteCustomValues = new RangeValues(40.0f, 160.0f);
|
|
|
|
public override Widget build(BuildContext context)
|
|
{
|
|
return new Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 40.0f),
|
|
child: new Column(
|
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
children: new List<Widget>
|
|
{
|
|
new Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: new List<Widget>
|
|
{
|
|
new RangeSlider(
|
|
values: _continuousValues,
|
|
min: 0.0f,
|
|
max: 100.0f,
|
|
onChanged: (RangeValues values) =>
|
|
{
|
|
setState(() => { _continuousValues = values; });
|
|
}
|
|
),
|
|
new Text("Continuous")
|
|
}
|
|
),
|
|
new Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: new List<Widget>
|
|
{
|
|
new RangeSlider(values: new RangeValues(0.25f, 0.75f), onChanged: null),
|
|
new Text("Disabled")
|
|
}
|
|
),
|
|
new Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: new List<Widget>
|
|
{
|
|
new RangeSlider(
|
|
values: _discreteValues,
|
|
min: 0.0f,
|
|
max: 200.0f,
|
|
//divisions: 5,
|
|
labels: new RangeLabels($"{_discreteValues.start.round()}",
|
|
$"{_discreteValues.end.round()}"),
|
|
onChanged: (RangeValues values) =>
|
|
{
|
|
setState(() => { _discreteValues = values; });
|
|
}
|
|
),
|
|
new Text("Discrete")
|
|
}
|
|
),
|
|
new Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: new List<Widget>
|
|
{
|
|
new SliderTheme(
|
|
data: new SliderThemeData(
|
|
activeTrackColor: Colors.deepPurple,
|
|
inactiveTrackColor: Colors.black26,
|
|
activeTickMarkColor: Colors.white70,
|
|
inactiveTickMarkColor: Colors.black,
|
|
overlayColor: Colors.black12,
|
|
thumbColor: Colors.deepPurple,
|
|
rangeThumbShape: new _CustomRangeThumbShape(),
|
|
showValueIndicator: ShowValueIndicator.never
|
|
),
|
|
child: new RangeSlider(
|
|
values: _discreteCustomValues,
|
|
min: 0.0f,
|
|
max: 200.0f,
|
|
divisions: 5,
|
|
labels: new RangeLabels($"{_discreteCustomValues.start.round()}",
|
|
$"{_discreteCustomValues.end.round()}"),
|
|
onChanged: (RangeValues values) =>
|
|
{
|
|
setState(() => { _discreteCustomValues = values; });
|
|
}
|
|
)
|
|
),
|
|
new Text("Discrete with Custom Theme")
|
|
}
|
|
)
|
|
}
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|