您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

468 行
16 KiB

using System;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.scheduler;
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;
namespace Unity.UIWidgets.cupertino {
class SliderUtils {
public const float _kPadding = 8.0f;
public static readonly Color _kTrackColor = new Color(0xFFB5B5B5);
public const float _kSliderHeight = 2.0f * (CupertinoThumbPainter.radius + _kPadding);
public const float _kSliderWidth = 176.0f; // Matches Material Design slider.
public static readonly TimeSpan _kDiscreteTransitionDuration = TimeSpan.FromMilliseconds(500);
public const float _kAdjustmentUnit = 0.1f; // Matches iOS implementation of material slider.
}
public class CupertinoSlider : StatefulWidget {
public CupertinoSlider(
Key key = null,
float? value = null,
ValueChanged<float> onChanged = null,
ValueChanged<float> onChangeStart = null,
ValueChanged<float> onChangeEnd = null,
float min = 0.0f,
float max = 1.0f,
int? divisions = null,
Color activeColor = null,
Color thumbColor = null
) : base(key: key) {
D.assert(value != null);
D.assert(onChanged != null);
D.assert(value >= min && value <= max);
D.assert(divisions == null || divisions > 0);
this.value = value.Value;
this.onChanged = onChanged;
this.onChangeStart = onChangeStart;
this.onChangeEnd = onChangeEnd;
this.min = min;
this.max = max;
this.divisions = divisions;
this.activeColor = activeColor;
this.thumbColor = thumbColor ?? CupertinoColors.white;
}
public readonly float value;
public readonly ValueChanged<float> onChanged;
public readonly ValueChanged<float> onChangeStart;
public readonly ValueChanged<float> onChangeEnd;
public readonly float min;
public readonly float max;
public readonly int? divisions;
public readonly Color activeColor;
public readonly Color thumbColor;
public override State createState() {
return new _CupertinoSliderState();
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new FloatProperty("value", value));
properties.add(new FloatProperty("min", min));
properties.add(new FloatProperty("max", max));
}
}
class _CupertinoSliderState : TickerProviderStateMixin<CupertinoSlider> {
void _handleChanged(float value) {
D.assert(widget.onChanged != null);
float lerpValue = MathUtils.lerpNullableFloat(widget.min, widget.max, value);
if (lerpValue != widget.value) {
widget.onChanged(lerpValue);
}
}
void _handleDragStart(float value) {
D.assert(widget.onChangeStart != null);
widget.onChangeStart(MathUtils.lerpNullableFloat(widget.min, widget.max, value));
}
void _handleDragEnd(float value) {
D.assert(widget.onChangeEnd != null);
widget.onChangeEnd(MathUtils.lerpNullableFloat(widget.min, widget.max, value));
}
public override Widget build(BuildContext context) {
return new _CupertinoSliderRenderObjectWidget(
value: (widget.value - widget.min) / (widget.max - widget.min),
divisions: widget.divisions,
activeColor: CupertinoDynamicColor.resolve(
widget.activeColor ?? CupertinoTheme.of(context).primaryColor,
context
),
thumbColor: widget.thumbColor,
onChanged: widget.onChanged != null ? (ValueChanged<float>) _handleChanged : null,
onChangeStart: widget.onChangeStart != null ? (ValueChanged<float>) _handleDragStart : null,
onChangeEnd: widget.onChangeEnd != null ? (ValueChanged<float>) _handleDragEnd : null,
vsync: this
);
}
}
class _CupertinoSliderRenderObjectWidget : LeafRenderObjectWidget {
public _CupertinoSliderRenderObjectWidget(
Key key = null,
float? value = null,
int? divisions = null,
Color activeColor = null,
Color thumbColor = null,
ValueChanged<float> onChanged = null,
ValueChanged<float> onChangeStart = null,
ValueChanged<float> onChangeEnd = null,
TickerProvider vsync = null
) : base(key: key) {
this.value = value;
this.divisions = divisions;
this.activeColor = activeColor;
this.onChanged = onChanged;
this.onChangeStart = onChangeStart;
this.onChangeEnd = onChangeEnd;
this.vsync = vsync;
this.thumbColor = thumbColor;
}
public readonly float? value;
public readonly int? divisions;
public readonly Color activeColor;
public readonly Color thumbColor;
public readonly ValueChanged<float> onChanged;
public readonly ValueChanged<float> onChangeStart;
public readonly ValueChanged<float> onChangeEnd;
public readonly TickerProvider vsync;
public override RenderObject createRenderObject(BuildContext context) {
return new _RenderCupertinoSlider(
value: value ?? 0.0f,
divisions: divisions,
activeColor: activeColor,
thumbColor: CupertinoDynamicColor.resolve(thumbColor, context),
trackColor: CupertinoDynamicColor.resolve(CupertinoColors.systemFill, context),
onChanged: onChanged,
onChangeStart: onChangeStart,
onChangeEnd: onChangeEnd,
vsync: vsync,
textDirection: Directionality.of(context)
);
}
public override void updateRenderObject(BuildContext context, RenderObject _renderObject) {
_RenderCupertinoSlider renderObject = _renderObject as _RenderCupertinoSlider;
renderObject.value = value ?? 0.0f;
renderObject.divisions = divisions;
renderObject.activeColor = activeColor;
renderObject.thumbColor = CupertinoDynamicColor.resolve(thumbColor, context);
renderObject.trackColor = CupertinoDynamicColor.resolve(CupertinoColors.systemFill, context);
renderObject.onChanged = onChanged;
renderObject.onChangeStart = onChangeStart;
renderObject.onChangeEnd = onChangeEnd;
renderObject.textDirection = Directionality.of(context);
}
}
class _RenderCupertinoSlider : RenderConstrainedBox {
public _RenderCupertinoSlider(
float value,
int? divisions = null,
Color activeColor = null,
Color thumbColor = null,
Color trackColor = null,
ValueChanged<float> onChanged = null,
ValueChanged<float> onChangeStart = null,
ValueChanged<float> onChangeEnd = null,
TickerProvider vsync = null,
TextDirection? textDirection = null
) : base(additionalConstraints: BoxConstraints.tightFor(width: SliderUtils._kSliderWidth,
height: SliderUtils._kSliderHeight)) {
D.assert(value >= 0.0f && value <= 1.0f && value != null) ;
_value = value;
_divisions = divisions;
_activeColor = activeColor;
_thumbColor = thumbColor;
_trackColor = trackColor;
_onChanged = onChanged;
this.onChangeStart = onChangeStart;
this.onChangeEnd = onChangeEnd;
_textDirection = textDirection;
_drag = new HorizontalDragGestureRecognizer();
_drag.onStart = _handleDragStart;
_drag.onUpdate = _handleDragUpdate;
_drag.onEnd = _handleDragEnd;
_position = new AnimationController(
value: value,
duration: SliderUtils._kDiscreteTransitionDuration,
vsync: vsync
);
_position.addListener(markNeedsPaint);
}
public float value {
get { return _value; }
set {
D.assert(value >= 0.0f && value <= 1.0f);
if (value == _value) {
return;
}
_value = value;
if (divisions != null) {
_position.animateTo(value, curve: Curves.fastOutSlowIn);
}
else {
_position.setValue(value);
}
}
}
float _value;
public int? divisions {
get { return _divisions; }
set {
if (value == _divisions) {
return;
}
_divisions = value;
markNeedsPaint();
}
}
int? _divisions;
public Color activeColor {
get { return _activeColor; }
set {
if (value == _activeColor) {
return;
}
_activeColor = value;
markNeedsPaint();
}
}
Color _activeColor;
public Color thumbColor {
get {
return _thumbColor;
}
set {
if (value == _thumbColor)
return;
_thumbColor = value;
markNeedsPaint();
}
}
Color _thumbColor;
public Color trackColor {
get {
return _trackColor;
}
set {
if (value == _trackColor)
return;
_trackColor = value;
markNeedsPaint();
}
}
Color _trackColor;
public ValueChanged<float> onChanged {
get { return _onChanged; }
set {
if (value == _onChanged) {
return;
}
_onChanged = value;
}
}
ValueChanged<float> _onChanged;
public ValueChanged<float> onChangeStart;
public ValueChanged<float> onChangeEnd;
public TextDirection? textDirection {
get {
return _textDirection;
}
set {
D.assert(value != null);
if (_textDirection == value)
return;
_textDirection = value;
markNeedsPaint();
}
}
TextDirection? _textDirection;
AnimationController _position;
HorizontalDragGestureRecognizer _drag;
float _currentDragValue = 0.0f;
float _discretizedCurrentDragValue {
get {
float dragValue = _currentDragValue.clamp(0.0f, 1.0f);
if (divisions != null) {
dragValue = Mathf.Round(dragValue * divisions.Value) / divisions.Value;
}
return dragValue;
}
}
public float _trackLeft {
get { return SliderUtils._kPadding; }
}
public float _trackRight {
get { return size.width - SliderUtils._kPadding; }
}
float _thumbCenter {
get {
float visualPosition = 0.0f;
switch (textDirection) {
case TextDirection.rtl:
visualPosition = 1.0f - _value;
break;
case TextDirection.ltr:
visualPosition = _value;
break;
}
return MathUtils.lerpNullableFloat(_trackLeft + CupertinoThumbPainter.radius, _trackRight - CupertinoThumbPainter.radius, visualPosition);
}
}
public bool isInteractive {
get { return onChanged != null; }
}
void _handleDragStart(DragStartDetails details) {
_startInteraction(details.globalPosition);
}
void _handleDragUpdate(DragUpdateDetails details) {
if (isInteractive) {
float extent = Mathf.Max(SliderUtils._kPadding,
size.width - 2.0f * (SliderUtils._kPadding + CupertinoThumbPainter.radius));
float? valueDelta = details.primaryDelta / extent;
switch (textDirection) {
case TextDirection.rtl:
_currentDragValue -= valueDelta ?? 0.0f;
break;
case TextDirection.ltr:
_currentDragValue += valueDelta ?? 0.0f;
break;
}
onChanged(_discretizedCurrentDragValue);
}
}
void _handleDragEnd(DragEndDetails details) {
_endInteraction();
}
void _startInteraction(Offset globalPosition) {
if (isInteractive) {
if (onChangeStart != null) {
onChangeStart(_discretizedCurrentDragValue);
}
_currentDragValue = _value;
onChanged(_discretizedCurrentDragValue);
}
}
void _endInteraction() {
if (onChangeEnd != null) {
onChangeEnd(_discretizedCurrentDragValue);
}
_currentDragValue = 0.0f;
}
protected override bool hitTestSelf(Offset position) {
return (position.dx - _thumbCenter).abs() < CupertinoThumbPainter.radius + SliderUtils._kPadding;
}
public override void handleEvent(PointerEvent e, HitTestEntry entry) {
D.assert(debugHandleEvent(e, entry));
if (e is PointerDownEvent pointerDownEvent && isInteractive) {
_drag.addPointer(pointerDownEvent);
}
}
CupertinoThumbPainter _thumbPainter = new CupertinoThumbPainter();
public override void paint(PaintingContext context, Offset offset) {
float visualPosition = 0.0f;
Color leftColor = null ;
Color rightColor = null;
switch (textDirection) {
case TextDirection.rtl:
visualPosition = 1.0f - _position.value;
leftColor = _activeColor;
rightColor = trackColor;
break;
case TextDirection.ltr:
visualPosition = _position.value;
leftColor = trackColor;
rightColor = _activeColor;
break;
}
float trackCenter = offset.dy + size.height / 2.0f;
float trackLeft = offset.dx + _trackLeft;
float trackTop = trackCenter - 1.0f;
float trackBottom = trackCenter + 1.0f;
float trackRight = offset.dx + _trackRight;
float trackActive = offset.dx + _thumbCenter;
Canvas canvas = context.canvas;
if (visualPosition > 0.0f) {
Paint paint = new Paint();
paint.color = rightColor;
canvas.drawRRect(RRect.fromLTRBXY(trackLeft, trackTop, trackActive, trackBottom, 1.0f, 1.0f), paint);
}
if (visualPosition < 1.0f) {
Paint paint = new Paint();
paint.color = leftColor;
canvas.drawRRect(RRect.fromLTRBXY(trackActive, trackTop, trackRight, trackBottom, 1.0f, 1.0f), paint);
}
Offset thumbCenter = new Offset(trackActive, trackCenter);
new CupertinoThumbPainter(color: thumbColor).paint(canvas, Rect.fromCircle(center: thumbCenter, radius: CupertinoThumbPainter.radius));
}
}
}