29
29
import static com .google .android .material .slider .LabelFormatter .LABEL_WITHIN_BOUNDS ;
30
30
import static com .google .android .material .slider .SliderOrientation .HORIZONTAL ;
31
31
import static com .google .android .material .slider .SliderOrientation .VERTICAL ;
32
+ import static com .google .android .material .slider .TickVisibilityMode .TICK_VISIBILITY_AUTO_HIDE ;
33
+ import static com .google .android .material .slider .TickVisibilityMode .TICK_VISIBILITY_AUTO_LIMIT ;
34
+ import static com .google .android .material .slider .TickVisibilityMode .TICK_VISIBILITY_HIDDEN ;
32
35
import static com .google .android .material .theme .overlay .MaterialThemeOverlay .wrap ;
33
36
import static java .lang .Float .compare ;
34
37
import static java .lang .Math .abs ;
157
160
* discrete mode. This is a short hand for setting both the {@code tickColorActive} and {@code
158
161
* tickColorInactive} to the same thing. This takes precedence over {@code tickColorActive}
159
162
* and {@code tickColorInactive}.
160
- * <li>{@code tickVisible}: Whether to show the tick marks. Only used when the slider is in
161
- * discrete mode.
163
+ * <li>{@code tickVisible} (<b>deprecated</b>, use {@code tickVisibilityMode} instead): Whether to
164
+ * show the tick marks. Only used when the slider is in discrete mode.
165
+ * <li>{@code tickVisibilityMode}: Mode to specify the visibility of tick marks. Only used when
166
+ * the slider is in discrete mode.
162
167
* <li>{@code trackColorActive}: The color of the active part of the track.
163
168
* <li>{@code trackColorInactive}: The color of the inactive part of the track.
164
169
* <li>{@code trackColor}: The color of the whole track. This is a short hand for setting both the
210
215
* @attr ref com.google.android.material.R.styleable#Slider_tickColorActive
211
216
* @attr ref com.google.android.material.R.styleable#Slider_tickColorInactive
212
217
* @attr ref com.google.android.material.R.styleable#Slider_tickVisible
218
+ * @attr ref com.google.android.material.R.styleable#Slider_tickVisibilityMode
213
219
* @attr ref com.google.android.material.R.styleable#Slider_trackColor
214
220
* @attr ref com.google.android.material.R.styleable#Slider_trackColorActive
215
221
* @attr ref com.google.android.material.R.styleable#Slider_trackColorInactive
@@ -366,7 +372,7 @@ abstract class BaseSlider<
366
372
private int focusedThumbIdx = -1 ;
367
373
private float stepSize = 0.0f ;
368
374
private float [] ticksCoordinates ;
369
- private boolean tickVisible = true ;
375
+ private int tickVisibilityMode ;
370
376
private int tickActiveRadius ;
371
377
private int tickInactiveRadius ;
372
378
private int trackWidth ;
@@ -583,7 +589,11 @@ private void processAttributes(Context context, AttributeSet attrs, int defStyle
583
589
? haloColor
584
590
: AppCompatResources .getColorStateList (context , R .color .material_slider_halo_color ));
585
591
586
- tickVisible = a .getBoolean (R .styleable .Slider_tickVisible , true );
592
+ tickVisibilityMode =
593
+ a .hasValue (R .styleable .Slider_tickVisibilityMode )
594
+ ? a .getInt (R .styleable .Slider_tickVisibilityMode , -1 )
595
+ : convertToTickVisibilityMode (a .getBoolean (R .styleable .Slider_tickVisible , true ));
596
+
587
597
boolean hasTickColor = a .hasValue (R .styleable .Slider_tickColor );
588
598
int tickColorInactiveRes =
589
599
hasTickColor ? R .styleable .Slider_tickColor : R .styleable .Slider_tickColorInactive ;
@@ -1774,22 +1784,58 @@ public void setTickInactiveTintList(@NonNull ColorStateList tickColor) {
1774
1784
/**
1775
1785
* Returns whether the tick marks are visible. Only used when the slider is in discrete mode.
1776
1786
*
1777
- * @see #setTickVisible(boolean)
1778
1787
* @attr ref com.google.android.material.R.styleable#Slider_tickVisible
1779
1788
*/
1780
1789
public boolean isTickVisible () {
1781
- return tickVisible ;
1790
+ switch (tickVisibilityMode ) {
1791
+ case TICK_VISIBILITY_AUTO_LIMIT :
1792
+ return true ;
1793
+ case TICK_VISIBILITY_AUTO_HIDE :
1794
+ return getDesiredTickCount () <= getMaxTickCount ();
1795
+ case TICK_VISIBILITY_HIDDEN :
1796
+ return false ;
1797
+ default :
1798
+ throw new IllegalStateException ("Unexpected tickVisibilityMode: " + tickVisibilityMode );
1799
+ }
1782
1800
}
1783
1801
1784
1802
/**
1785
1803
* Sets whether the tick marks are visible. Only used when the slider is in discrete mode.
1786
1804
*
1787
1805
* @param tickVisible The visibility of tick marks.
1788
1806
* @attr ref com.google.android.material.R.styleable#Slider_tickVisible
1807
+ * @deprecated Use {@link #setTickVisibilityMode(int)} instead.
1789
1808
*/
1809
+ @ Deprecated
1790
1810
public void setTickVisible (boolean tickVisible ) {
1791
- if (this .tickVisible != tickVisible ) {
1792
- this .tickVisible = tickVisible ;
1811
+ setTickVisibilityMode (convertToTickVisibilityMode (tickVisible ));
1812
+ }
1813
+
1814
+ @ TickVisibilityMode
1815
+ private int convertToTickVisibilityMode (boolean tickVisible ) {
1816
+ return tickVisible ? TICK_VISIBILITY_AUTO_LIMIT : TICK_VISIBILITY_HIDDEN ;
1817
+ }
1818
+
1819
+ /**
1820
+ * Returns the current tick visibility mode.
1821
+ *
1822
+ * @see #setTickVisibilityMode(int)
1823
+ * @attr ref com.google.android.material.R.styleable#Slider_tickVisibilityMode
1824
+ */
1825
+ @ TickVisibilityMode
1826
+ public int getTickVisibilityMode () {
1827
+ return tickVisibilityMode ;
1828
+ }
1829
+
1830
+ /**
1831
+ * Sets the tick visibility mode. Only used when the slider is in discrete mode.
1832
+ *
1833
+ * @see #getTickVisibilityMode()
1834
+ * @attr ref com.google.android.material.R.styleable#Slider_tickVisibilityMode
1835
+ */
1836
+ public void setTickVisibilityMode (@ TickVisibilityMode int tickVisibilityMode ) {
1837
+ if (this .tickVisibilityMode != tickVisibilityMode ) {
1838
+ this .tickVisibilityMode = tickVisibilityMode ;
1793
1839
postInvalidate ();
1794
1840
}
1795
1841
}
@@ -2412,37 +2458,70 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
2412
2458
updateHaloHotspot ();
2413
2459
}
2414
2460
2415
- private void maybeCalculateTicksCoordinates () {
2461
+ private void updateTicksCoordinates () {
2462
+ validateConfigurationIfDirty ();
2463
+
2416
2464
if (stepSize <= 0.0f ) {
2465
+ updateTicksCoordinates (/* tickCount= */ 0 );
2417
2466
return ;
2418
2467
}
2419
2468
2420
- validateConfigurationIfDirty ();
2469
+ final int tickCount ;
2470
+ switch (tickVisibilityMode ) {
2471
+ case TICK_VISIBILITY_AUTO_LIMIT :
2472
+ tickCount = min (getDesiredTickCount (), getMaxTickCount ());
2473
+ break ;
2474
+ case TICK_VISIBILITY_AUTO_HIDE :
2475
+ int desiredTickCount = getDesiredTickCount ();
2476
+ tickCount = desiredTickCount <= getMaxTickCount () ? desiredTickCount : 0 ;
2477
+ break ;
2478
+ case TICK_VISIBILITY_HIDDEN :
2479
+ tickCount = 0 ;
2480
+ break ;
2481
+ default :
2482
+ throw new IllegalStateException ("Unexpected tickVisibilityMode: " + tickVisibilityMode );
2483
+ }
2484
+
2485
+ updateTicksCoordinates (tickCount );
2486
+ }
2487
+
2488
+ private void updateTicksCoordinates (int tickCount ) {
2489
+ if (tickCount == 0 ) {
2490
+ ticksCoordinates = null ;
2491
+ return ;
2492
+ }
2421
2493
2422
- int tickCount = (int ) ((valueTo - valueFrom ) / stepSize + 1 );
2423
- // Limit the tickCount if they will be too dense.
2424
- tickCount = min (tickCount , trackWidth / minTickSpacing + 1 );
2425
2494
if (ticksCoordinates == null || ticksCoordinates .length != tickCount * 2 ) {
2426
2495
ticksCoordinates = new float [tickCount * 2 ];
2427
2496
}
2428
2497
2429
2498
float interval = trackWidth / (float ) (tickCount - 1 );
2499
+ float trackCenterY = calculateTrackCenter ();
2500
+
2430
2501
for (int i = 0 ; i < tickCount * 2 ; i += 2 ) {
2431
2502
ticksCoordinates [i ] = trackSidePadding + i / 2f * interval ;
2432
- ticksCoordinates [i + 1 ] = calculateTrackCenter () ;
2503
+ ticksCoordinates [i + 1 ] = trackCenterY ;
2433
2504
}
2434
2505
2435
2506
if (isVertical ()) {
2436
2507
rotationMatrix .mapPoints (ticksCoordinates );
2437
2508
}
2438
2509
}
2439
2510
2511
+ private int getDesiredTickCount () {
2512
+ return (int ) ((valueTo - valueFrom ) / stepSize + 1 );
2513
+ }
2514
+
2515
+ private int getMaxTickCount () {
2516
+ return trackWidth / minTickSpacing + 1 ;
2517
+ }
2518
+
2440
2519
private void updateTrackWidth (int width ) {
2441
2520
// Update the visible track width.
2442
2521
trackWidth = max (width - trackSidePadding * 2 , 0 );
2443
2522
2444
2523
// Update the visible tick coordinates.
2445
- maybeCalculateTicksCoordinates ();
2524
+ updateTicksCoordinates ();
2446
2525
}
2447
2526
2448
2527
private void updateHaloHotspot () {
@@ -2457,10 +2536,7 @@ private void updateHaloHotspot() {
2457
2536
rotationMatrix .mapPoints (haloBounds );
2458
2537
}
2459
2538
background .setHotspotBounds (
2460
- (int ) haloBounds [0 ],
2461
- (int ) haloBounds [1 ],
2462
- (int ) haloBounds [2 ],
2463
- (int ) haloBounds [3 ]);
2539
+ (int ) haloBounds [0 ], (int ) haloBounds [1 ], (int ) haloBounds [2 ], (int ) haloBounds [3 ]);
2464
2540
}
2465
2541
}
2466
2542
}
@@ -2478,7 +2554,7 @@ protected void onDraw(@NonNull Canvas canvas) {
2478
2554
validateConfigurationIfDirty ();
2479
2555
2480
2556
// Update the visible tick coordinates.
2481
- maybeCalculateTicksCoordinates ();
2557
+ updateTicksCoordinates ();
2482
2558
}
2483
2559
2484
2560
super .onDraw (canvas );
@@ -2673,15 +2749,11 @@ private void drawTrackIcons(
2673
2749
}
2674
2750
2675
2751
// draw track start icons
2676
- calculateBoundsAndDrawTrackIcon (
2677
- canvas , activeTrackBounds , trackIconActiveStart , true );
2678
- calculateBoundsAndDrawTrackIcon (
2679
- canvas , inactiveTrackBounds , trackIconInactiveStart , true );
2752
+ calculateBoundsAndDrawTrackIcon (canvas , activeTrackBounds , trackIconActiveStart , true );
2753
+ calculateBoundsAndDrawTrackIcon (canvas , inactiveTrackBounds , trackIconInactiveStart , true );
2680
2754
// draw track end icons
2681
- calculateBoundsAndDrawTrackIcon (
2682
- canvas , activeTrackBounds , trackIconActiveEnd , false );
2683
- calculateBoundsAndDrawTrackIcon (
2684
- canvas , inactiveTrackBounds , trackIconInactiveEnd , false );
2755
+ calculateBoundsAndDrawTrackIcon (canvas , activeTrackBounds , trackIconActiveEnd , false );
2756
+ calculateBoundsAndDrawTrackIcon (canvas , inactiveTrackBounds , trackIconInactiveEnd , false );
2685
2757
}
2686
2758
2687
2759
private boolean hasTrackIcons () {
@@ -2705,9 +2777,7 @@ private void calculateBoundsAndDrawTrackIcon(
2705
2777
}
2706
2778
2707
2779
private void drawTrackIcon (
2708
- @ NonNull Canvas canvas ,
2709
- @ NonNull RectF iconBounds ,
2710
- @ NonNull Drawable icon ) {
2780
+ @ NonNull Canvas canvas , @ NonNull RectF iconBounds , @ NonNull Drawable icon ) {
2711
2781
if (isVertical ()) {
2712
2782
rotationMatrix .mapRect (iconBounds );
2713
2783
}
@@ -2837,7 +2907,7 @@ private float[] getCornerRadii(float leftSide, float rightSide) {
2837
2907
}
2838
2908
2839
2909
private void maybeDrawTicks (@ NonNull Canvas canvas ) {
2840
- if (! tickVisible || stepSize <= 0.0f ) {
2910
+ if (ticksCoordinates == null || ticksCoordinates . length == 0 ) {
2841
2911
return ;
2842
2912
}
2843
2913
@@ -3499,7 +3569,8 @@ private boolean isInHorizontalScrollingContainer() {
3499
3569
ViewParent p = getParent ();
3500
3570
while (p instanceof ViewGroup ) {
3501
3571
ViewGroup parent = (ViewGroup ) p ;
3502
- boolean canScrollHorizontally = parent .canScrollHorizontally (1 ) || parent .canScrollHorizontally (-1 );
3572
+ boolean canScrollHorizontally =
3573
+ parent .canScrollHorizontally (1 ) || parent .canScrollHorizontally (-1 );
3503
3574
if (canScrollHorizontally && parent .shouldDelayChildPressedState ()) {
3504
3575
return true ;
3505
3576
}
0 commit comments