1
1
using System ;
2
+ using System . Collections . Generic ;
2
3
using Unity . UIWidgets . animation ;
3
4
using Unity . UIWidgets . async ;
4
5
using Unity . UIWidgets . foundation ;
9
10
using Unity . UIWidgets . ui ;
10
11
using Unity . UIWidgets . widgets ;
11
12
using UnityEngine ;
12
- using Canvas = Unity . UIWidgets . ui . Canvas ;
13
13
using Color = Unity . UIWidgets . ui . Color ;
14
14
using Rect = Unity . UIWidgets . ui . Rect ;
15
15
@@ -253,6 +253,11 @@ public override void updateRenderObject(BuildContext context, RenderObject rende
253
253
}
254
254
255
255
class _RenderSlider : RenderBox {
256
+ static float _positionAnimationDurationMilliSeconds = 75 ;
257
+ static float _minimumInteractionTimeMilliSeconds = 500 ;
258
+
259
+ const float _minPreferredTrackWidth = 144.0f ;
260
+
256
261
public _RenderSlider (
257
262
float ? value = null ,
258
263
int ? divisions = null ,
@@ -310,14 +315,46 @@ public _RenderSlider(
310
315
curve : Curves . easeInOut ) ;
311
316
}
312
317
313
- const float _positionAnimationDurationMilliSeconds = 75 ;
314
- const float _overlayRadius = 16.0f ;
315
- const float _overlayDiameter = _overlayRadius * 2.0f ;
316
- const float _trackHeight = 2.0f ;
317
- const float _preferredTrackWidth = 144.0f ;
318
- const float _preferredTotalWidth = _preferredTrackWidth + _overlayDiameter ;
319
- const float _minimumInteractionTimeMilliSeconds = 500 ;
320
- static readonly Animatable < float > _overlayRadiusTween = new FloatTween ( begin : 0.0f , end : _overlayRadius ) ;
318
+ float _maxSliderPartWidth {
319
+ get {
320
+ float maxValue = 0 ;
321
+ foreach ( Size size in this . _sliderPartSizes ) {
322
+ if ( size . width > maxValue ) {
323
+ maxValue = size . width ;
324
+ }
325
+ }
326
+
327
+ return maxValue ;
328
+ }
329
+ }
330
+
331
+ float _maxSliderPartHeight {
332
+ get {
333
+ float maxValue = 0 ;
334
+ foreach ( Size size in this . _sliderPartSizes ) {
335
+ if ( size . width > maxValue ) {
336
+ maxValue = size . width ;
337
+ }
338
+ }
339
+
340
+ return maxValue ;
341
+ }
342
+ }
343
+
344
+ List < Size > _sliderPartSizes {
345
+ get {
346
+ return new List < Size > {
347
+ this . _sliderTheme . overlayShape . getPreferredSize ( this . isInteractive , this . isDiscrete ) ,
348
+ this . _sliderTheme . thumbShape . getPreferredSize ( this . isInteractive , this . isDiscrete ) ,
349
+ this . _sliderTheme . tickMarkShape . getPreferredSize ( isEnabled : this . isInteractive ,
350
+ sliderTheme : this . sliderTheme )
351
+ } ;
352
+ }
353
+ }
354
+
355
+ float _minPreferredTrackHeight {
356
+ get { return this . _sliderTheme . trackHeight ; }
357
+ }
321
358
322
359
_SliderState _state ;
323
360
Animation < float > _overlayAnimation ;
@@ -329,8 +366,15 @@ public _RenderSlider(
329
366
bool _active = false ;
330
367
float _currentDragValue = 0.0f ;
331
368
332
- float _trackLength {
333
- get { return this . size . width - _overlayDiameter ; }
369
+ Rect _trackRect {
370
+ get {
371
+ return this . _sliderTheme . trackShape . getPreferredRect (
372
+ parentBox : this ,
373
+ offset : Offset . zero ,
374
+ sliderTheme : this . _sliderTheme ,
375
+ isDiscrete : false
376
+ ) ;
377
+ }
334
378
}
335
379
336
380
bool isInteractive {
@@ -548,14 +592,14 @@ float _getValueFromVisualPosition(float visualPosition) {
548
592
549
593
float _getValueFromGlobalPosition ( Offset globalPosition ) {
550
594
float visualPosition =
551
- ( this . globalToLocal ( globalPosition ) . dx - _overlayRadius ) / this . _trackLength ;
595
+ ( this . globalToLocal ( globalPosition ) . dx - this . _trackRect . left ) / this . _trackRect . width ;
552
596
return this . _getValueFromVisualPosition ( visualPosition ) ;
553
597
}
554
598
555
599
float _discretize ( float value ) {
556
600
float result = value . clamp ( 0.0f , 1.0f ) ;
557
601
if ( this . isDiscrete ) {
558
- result = ( result * this . divisions . Value ) . round ( ) / this . divisions . Value ;
602
+ result = ( result * this . divisions . Value ) . round ( ) * 1.0f / this . divisions . Value ;
559
603
}
560
604
561
605
return result ;
@@ -584,7 +628,8 @@ void _startInteraction(Offset globalPosition) {
584
628
this . _state . valueIndicatorController . status == AnimationStatus . completed ) {
585
629
this . _state . valueIndicatorController . reverse ( ) ;
586
630
}
587
- } ) ;
631
+ }
632
+ ) ;
588
633
}
589
634
}
590
635
}
@@ -610,7 +655,7 @@ void _handleDragStart(DragStartDetails details) {
610
655
611
656
void _handleDragUpdate ( DragUpdateDetails details ) {
612
657
if ( this . isInteractive ) {
613
- float valueDelta = details . primaryDelta . Value / this . _trackLength ;
658
+ float valueDelta = details . primaryDelta . Value / this . _trackRect . width ;
614
659
this . _currentDragValue += valueDelta ;
615
660
this . onChanged ( this . _discretize ( this . _currentDragValue ) ) ;
616
661
}
@@ -642,20 +687,19 @@ public override void handleEvent(PointerEvent evt, HitTestEntry entry) {
642
687
643
688
644
689
protected override float computeMinIntrinsicWidth ( float height ) {
645
- return Mathf . Max ( _overlayDiameter ,
646
- this . _sliderTheme . thumbShape . getPreferredSize ( this . isInteractive , this . isDiscrete ) . width ) ;
690
+ return _minPreferredTrackWidth + this . _maxSliderPartWidth ;
647
691
}
648
692
649
693
protected override float computeMaxIntrinsicWidth ( float height ) {
650
- return _preferredTotalWidth ;
694
+ return _minPreferredTrackWidth + this . _maxSliderPartWidth ;
651
695
}
652
696
653
697
protected override float computeMinIntrinsicHeight ( float width ) {
654
- return _overlayDiameter ;
698
+ return Mathf . Max ( this . _minPreferredTrackHeight , this . _maxSliderPartHeight ) ;
655
699
}
656
700
657
701
protected override float computeMaxIntrinsicHeight ( float width ) {
658
- return _overlayDiameter ;
702
+ return Mathf . Max ( this . _minPreferredTrackHeight , this . _maxSliderPartHeight ) ;
659
703
}
660
704
661
705
protected override bool sizedByParent {
@@ -666,114 +710,78 @@ protected override void performResize() {
666
710
this . size = new Size (
667
711
this . constraints . hasBoundedWidth
668
712
? this . constraints . maxWidth
669
- : _preferredTotalWidth ,
713
+ : _minPreferredTrackWidth + this . _maxSliderPartWidth ,
670
714
this . constraints . hasBoundedHeight
671
715
? this . constraints . maxHeight
672
- : _overlayDiameter
716
+ : Mathf . Max ( this . _minPreferredTrackHeight , this . _maxSliderPartHeight )
673
717
) ;
674
718
}
675
719
676
- void _paintTickMarks (
677
- Canvas canvas ,
678
- Rect trackLeft ,
679
- Rect trackRight ,
680
- Paint leftPaint ,
681
- Paint rightPaint ) {
682
- if ( this . isDiscrete ) {
683
- const float tickRadius = _trackHeight / 2.0f ;
684
- float trackWidth = trackRight . right - trackLeft . left ;
685
- float dx = ( trackWidth - _trackHeight ) / this . divisions . Value ;
686
-
687
- if ( dx >= 3.0 * _trackHeight ) {
688
- for ( int i = 0 ; i <= this . divisions . Value ; i += 1 ) {
689
- float left = trackLeft . left + i * dx ;
690
- Offset center = new Offset ( left + tickRadius , trackLeft . top + tickRadius ) ;
691
- if ( trackLeft . contains ( center ) ) {
692
- canvas . drawCircle ( center , tickRadius , leftPaint ) ;
693
- }
694
- else if ( trackRight . contains ( center ) ) {
695
- canvas . drawCircle ( center , tickRadius , rightPaint ) ;
696
- }
697
- }
698
- }
699
- }
700
- }
701
-
702
- void _paintOverlay (
703
- Canvas canvas ,
704
- Offset center ) {
705
- Paint overlayPaint = new Paint { color = this . _sliderTheme . overlayColor } ;
706
- float radius = _overlayRadiusTween . evaluate ( this . _overlayAnimation ) ;
707
- canvas . drawCircle ( center , radius , overlayPaint ) ;
708
- }
709
-
710
720
public override void paint ( PaintingContext context , Offset offset ) {
711
- Canvas canvas = context . canvas ;
712
-
713
- float trackLength = this . size . width - 2 * _overlayRadius ;
714
721
float value = this . _state . positionController . value ;
715
- ColorTween activeTrackEnableColor = new ColorTween ( begin : this . _sliderTheme . disabledActiveTrackColor ,
716
- end : this . _sliderTheme . activeTrackColor ) ;
717
- ColorTween inactiveTrackEnableColor = new ColorTween ( begin : this . _sliderTheme . disabledInactiveTrackColor ,
718
- end : this . _sliderTheme . inactiveTrackColor ) ;
719
- ColorTween activeTickMarkEnableColor = new ColorTween ( begin : this . _sliderTheme . disabledActiveTickMarkColor ,
720
- end : this . _sliderTheme . activeTickMarkColor ) ;
721
- ColorTween inactiveTickMarkEnableColor =
722
- new ColorTween ( begin : this . _sliderTheme . disabledInactiveTickMarkColor ,
723
- end : this . _sliderTheme . inactiveTickMarkColor ) ;
724
-
725
- Paint activeTrackPaint = new Paint { color = activeTrackEnableColor . evaluate ( this . _enableAnimation ) } ;
726
- Paint inactiveTrackPaint = new Paint { color = inactiveTrackEnableColor . evaluate ( this . _enableAnimation ) } ;
727
- Paint activeTickMarkPaint = new Paint { color = activeTickMarkEnableColor . evaluate ( this . _enableAnimation ) } ;
728
- Paint inactiveTickMarkPaint = new Paint
729
- { color = inactiveTickMarkEnableColor . evaluate ( this . _enableAnimation ) } ;
730
-
731
722
float visualPosition = value ;
732
- Paint leftTrackPaint = activeTrackPaint ;
733
- Paint rightTrackPaint = inactiveTrackPaint ;
734
- Paint leftTickMarkPaint = activeTickMarkPaint ;
735
- Paint rightTickMarkPaint = inactiveTickMarkPaint ;
736
-
737
- float trackRadius = _trackHeight / 2.0f ;
738
- float thumbGap = 2.0f ;
739
-
740
- float trackVerticalCenter = offset . dy + ( this . size . height ) / 2.0f ;
741
- float trackLeft = offset . dx + _overlayRadius ;
742
- float trackTop = trackVerticalCenter - trackRadius ;
743
- float trackBottom = trackVerticalCenter + trackRadius ;
744
- float trackRight = trackLeft + trackLength ;
745
- float trackActive = trackLeft + trackLength * visualPosition ;
746
- float thumbRadius =
747
- this . _sliderTheme . thumbShape . getPreferredSize ( this . isInteractive , this . isDiscrete ) . width / 2.0f ;
748
- float trackActiveLeft = Mathf . Max ( 0.0f ,
749
- trackActive - thumbRadius - thumbGap * ( 1.0f - this . _enableAnimation . value ) ) ;
750
- float trackActiveRight =
751
- Mathf . Min ( trackActive + thumbRadius + thumbGap * ( 1.0f - this . _enableAnimation . value ) , trackRight ) ;
752
- Rect trackLeftRect = Rect . fromLTRB ( trackLeft , trackTop , trackActiveLeft , trackBottom ) ;
753
- Rect trackRightRect = Rect . fromLTRB ( trackActiveRight , trackTop , trackRight , trackBottom ) ;
754
-
755
- Offset thumbCenter = new Offset ( trackActive , trackVerticalCenter ) ;
756
-
757
- if ( visualPosition > 0.0 ) {
758
- canvas . drawRect ( trackLeftRect , leftTrackPaint ) ;
759
- }
760
723
761
- if ( visualPosition < 1.0 ) {
762
- canvas . drawRect ( trackRightRect , rightTrackPaint ) ;
763
- }
724
+ Rect trackRect = this . _sliderTheme . trackShape . getPreferredRect (
725
+ parentBox : this ,
726
+ offset : offset ,
727
+ sliderTheme : this . _sliderTheme ,
728
+ isDiscrete : this . isDiscrete
729
+ ) ;
764
730
765
- this . _paintOverlay ( canvas , thumbCenter ) ;
731
+ Offset thumbCenter = new Offset ( trackRect . left + visualPosition * trackRect . width , trackRect . center . dy ) ;
766
732
767
- this . _paintTickMarks (
768
- canvas ,
769
- trackLeftRect ,
770
- trackRightRect ,
771
- leftTickMarkPaint ,
772
- rightTickMarkPaint
733
+ this . _sliderTheme . trackShape . paint (
734
+ context ,
735
+ offset ,
736
+ parentBox : this ,
737
+ sliderTheme : this . _sliderTheme ,
738
+ enableAnimation : this . _enableAnimation ,
739
+ thumbCenter : thumbCenter ,
740
+ isDiscrete : this . isDiscrete ,
741
+ isEnabled : this . isInteractive
773
742
) ;
774
743
775
- if ( this . isInteractive && this . label != null &&
776
- this . _valueIndicatorAnimation . status != AnimationStatus . dismissed ) {
744
+ if ( ! this . _overlayAnimation . isDismissed ) {
745
+ this . _sliderTheme . overlayShape . paint (
746
+ context ,
747
+ thumbCenter ,
748
+ activationAnimation : this . _overlayAnimation ,
749
+ enableAnimation : this . _enableAnimation ,
750
+ isDiscrete : this . isDiscrete ,
751
+ labelPainter : this . _labelPainter ,
752
+ parentBox : this ,
753
+ sliderTheme : this . _sliderTheme ,
754
+ value : this . _value
755
+ ) ;
756
+ }
757
+
758
+ if ( this . isDiscrete ) {
759
+ float tickMarkWidth = this . _sliderTheme . tickMarkShape . getPreferredSize (
760
+ isEnabled : this . isInteractive ,
761
+ sliderTheme : this . _sliderTheme
762
+ ) . width ;
763
+
764
+ if ( ( trackRect . width - tickMarkWidth ) / this . divisions . Value >= 3.0f * tickMarkWidth ) {
765
+ for ( int i = 0 ; i <= this . divisions ; i ++ ) {
766
+ float tickValue = i / this . divisions . Value ;
767
+ float tickX = trackRect . left +
768
+ tickValue * ( trackRect . width - tickMarkWidth ) + tickMarkWidth / 2 ;
769
+ float tickY = trackRect . center . dy ;
770
+ Offset tickMarkOffset = new Offset ( tickX , tickY ) ;
771
+ this . _sliderTheme . tickMarkShape . paint (
772
+ context ,
773
+ tickMarkOffset ,
774
+ parentBox : this ,
775
+ sliderTheme : this . _sliderTheme ,
776
+ enableAnimation : this . _enableAnimation ,
777
+ thumbCenter : thumbCenter ,
778
+ isEnabled : this . isInteractive
779
+ ) ;
780
+ }
781
+ }
782
+ }
783
+
784
+ if ( this . isInteractive && this . label != null && ! this . _valueIndicatorAnimation . isDismissed ) {
777
785
if ( this . showValueIndicator ) {
778
786
this . _sliderTheme . valueIndicatorShape . paint (
779
787
context ,
0 commit comments