2929import static com .google .android .material .slider .LabelFormatter .LABEL_WITHIN_BOUNDS ;
3030import static com .google .android .material .slider .SliderOrientation .HORIZONTAL ;
3131import 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 ;
3235import static com .google .android .material .theme .overlay .MaterialThemeOverlay .wrap ;
3336import static java .lang .Float .compare ;
3437import static java .lang .Math .abs ;
157160 * discrete mode. This is a short hand for setting both the {@code tickColorActive} and {@code
158161 * tickColorInactive} to the same thing. This takes precedence over {@code tickColorActive}
159162 * 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.
162167 * <li>{@code trackColorActive}: The color of the active part of the track.
163168 * <li>{@code trackColorInactive}: The color of the inactive part of the track.
164169 * <li>{@code trackColor}: The color of the whole track. This is a short hand for setting both the
210215 * @attr ref com.google.android.material.R.styleable#Slider_tickColorActive
211216 * @attr ref com.google.android.material.R.styleable#Slider_tickColorInactive
212217 * @attr ref com.google.android.material.R.styleable#Slider_tickVisible
218+ * @attr ref com.google.android.material.R.styleable#Slider_tickVisibilityMode
213219 * @attr ref com.google.android.material.R.styleable#Slider_trackColor
214220 * @attr ref com.google.android.material.R.styleable#Slider_trackColorActive
215221 * @attr ref com.google.android.material.R.styleable#Slider_trackColorInactive
@@ -366,7 +372,7 @@ abstract class BaseSlider<
366372 private int focusedThumbIdx = -1 ;
367373 private float stepSize = 0.0f ;
368374 private float [] ticksCoordinates ;
369- private boolean tickVisible = true ;
375+ private int tickVisibilityMode ;
370376 private int tickActiveRadius ;
371377 private int tickInactiveRadius ;
372378 private int trackWidth ;
@@ -583,7 +589,11 @@ private void processAttributes(Context context, AttributeSet attrs, int defStyle
583589 ? haloColor
584590 : AppCompatResources .getColorStateList (context , R .color .material_slider_halo_color ));
585591
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+
587597 boolean hasTickColor = a .hasValue (R .styleable .Slider_tickColor );
588598 int tickColorInactiveRes =
589599 hasTickColor ? R .styleable .Slider_tickColor : R .styleable .Slider_tickColorInactive ;
@@ -1774,22 +1784,58 @@ public void setTickInactiveTintList(@NonNull ColorStateList tickColor) {
17741784 /**
17751785 * Returns whether the tick marks are visible. Only used when the slider is in discrete mode.
17761786 *
1777- * @see #setTickVisible(boolean)
17781787 * @attr ref com.google.android.material.R.styleable#Slider_tickVisible
17791788 */
17801789 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+ }
17821800 }
17831801
17841802 /**
17851803 * Sets whether the tick marks are visible. Only used when the slider is in discrete mode.
17861804 *
17871805 * @param tickVisible The visibility of tick marks.
17881806 * @attr ref com.google.android.material.R.styleable#Slider_tickVisible
1807+ * @deprecated Use {@link #setTickVisibilityMode(int)} instead.
17891808 */
1809+ @ Deprecated
17901810 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 ;
17931839 postInvalidate ();
17941840 }
17951841 }
@@ -2412,37 +2458,70 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
24122458 updateHaloHotspot ();
24132459 }
24142460
2415- private void maybeCalculateTicksCoordinates () {
2461+ private void updateTicksCoordinates () {
2462+ validateConfigurationIfDirty ();
2463+
24162464 if (stepSize <= 0.0f ) {
2465+ updateTicksCoordinates (/* tickCount= */ 0 );
24172466 return ;
24182467 }
24192468
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+ }
24212493
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 );
24252494 if (ticksCoordinates == null || ticksCoordinates .length != tickCount * 2 ) {
24262495 ticksCoordinates = new float [tickCount * 2 ];
24272496 }
24282497
24292498 float interval = trackWidth / (float ) (tickCount - 1 );
2499+ float trackCenterY = calculateTrackCenter ();
2500+
24302501 for (int i = 0 ; i < tickCount * 2 ; i += 2 ) {
24312502 ticksCoordinates [i ] = trackSidePadding + i / 2f * interval ;
2432- ticksCoordinates [i + 1 ] = calculateTrackCenter () ;
2503+ ticksCoordinates [i + 1 ] = trackCenterY ;
24332504 }
24342505
24352506 if (isVertical ()) {
24362507 rotationMatrix .mapPoints (ticksCoordinates );
24372508 }
24382509 }
24392510
2511+ private int getDesiredTickCount () {
2512+ return (int ) ((valueTo - valueFrom ) / stepSize + 1 );
2513+ }
2514+
2515+ private int getMaxTickCount () {
2516+ return trackWidth / minTickSpacing + 1 ;
2517+ }
2518+
24402519 private void updateTrackWidth (int width ) {
24412520 // Update the visible track width.
24422521 trackWidth = max (width - trackSidePadding * 2 , 0 );
24432522
24442523 // Update the visible tick coordinates.
2445- maybeCalculateTicksCoordinates ();
2524+ updateTicksCoordinates ();
24462525 }
24472526
24482527 private void updateHaloHotspot () {
@@ -2457,10 +2536,7 @@ private void updateHaloHotspot() {
24572536 rotationMatrix .mapPoints (haloBounds );
24582537 }
24592538 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 ]);
24642540 }
24652541 }
24662542 }
@@ -2478,7 +2554,7 @@ protected void onDraw(@NonNull Canvas canvas) {
24782554 validateConfigurationIfDirty ();
24792555
24802556 // Update the visible tick coordinates.
2481- maybeCalculateTicksCoordinates ();
2557+ updateTicksCoordinates ();
24822558 }
24832559
24842560 super .onDraw (canvas );
@@ -2673,15 +2749,11 @@ private void drawTrackIcons(
26732749 }
26742750
26752751 // 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 );
26802754 // 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 );
26852757 }
26862758
26872759 private boolean hasTrackIcons () {
@@ -2705,9 +2777,7 @@ private void calculateBoundsAndDrawTrackIcon(
27052777 }
27062778
27072779 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 ) {
27112781 if (isVertical ()) {
27122782 rotationMatrix .mapRect (iconBounds );
27132783 }
@@ -2837,7 +2907,7 @@ private float[] getCornerRadii(float leftSide, float rightSide) {
28372907 }
28382908
28392909 private void maybeDrawTicks (@ NonNull Canvas canvas ) {
2840- if (! tickVisible || stepSize <= 0.0f ) {
2910+ if (ticksCoordinates == null || ticksCoordinates . length == 0 ) {
28412911 return ;
28422912 }
28432913
@@ -3499,7 +3569,8 @@ private boolean isInHorizontalScrollingContainer() {
34993569 ViewParent p = getParent ();
35003570 while (p instanceof ViewGroup ) {
35013571 ViewGroup parent = (ViewGroup ) p ;
3502- boolean canScrollHorizontally = parent .canScrollHorizontally (1 ) || parent .canScrollHorizontally (-1 );
3572+ boolean canScrollHorizontally =
3573+ parent .canScrollHorizontally (1 ) || parent .canScrollHorizontally (-1 );
35033574 if (canScrollHorizontally && parent .shouldDelayChildPressedState ()) {
35043575 return true ;
35053576 }
0 commit comments