/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.widget;

import android.annotation.NonNull;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;

import com.android.internal.widget.ScrollBarUtils;

This is only used by View for displaying its scroll bars. It should probably be moved in to the view package since it is used in that lower-level layer. For now, we'll hide it so it can be cleaned up later. {@hide}
/** * This is only used by View for displaying its scroll bars. It should probably * be moved in to the view package since it is used in that lower-level layer. * For now, we'll hide it so it can be cleaned up later. * * {@hide} */
public class ScrollBarDrawable extends Drawable implements Drawable.Callback { private Drawable mVerticalTrack; private Drawable mHorizontalTrack; private Drawable mVerticalThumb; private Drawable mHorizontalThumb; private int mRange; private int mOffset; private int mExtent; private boolean mVertical; private boolean mBoundsChanged; private boolean mRangeChanged; private boolean mAlwaysDrawHorizontalTrack; private boolean mAlwaysDrawVerticalTrack; private boolean mMutated; private int mAlpha = 255; private boolean mHasSetAlpha; private ColorFilter mColorFilter; private boolean mHasSetColorFilter;
Indicate whether the horizontal scrollbar track should always be drawn regardless of the extent. Defaults to false.
Params:
  • alwaysDrawTrack – Whether the track should always be drawn
See Also:
/** * Indicate whether the horizontal scrollbar track should always be drawn * regardless of the extent. Defaults to false. * * @param alwaysDrawTrack Whether the track should always be drawn * * @see #getAlwaysDrawHorizontalTrack() */
public void setAlwaysDrawHorizontalTrack(boolean alwaysDrawTrack) { mAlwaysDrawHorizontalTrack = alwaysDrawTrack; }
Indicate whether the vertical scrollbar track should always be drawn regardless of the extent. Defaults to false.
Params:
  • alwaysDrawTrack – Whether the track should always be drawn
See Also:
/** * Indicate whether the vertical scrollbar track should always be drawn * regardless of the extent. Defaults to false. * * @param alwaysDrawTrack Whether the track should always be drawn * * @see #getAlwaysDrawVerticalTrack() */
public void setAlwaysDrawVerticalTrack(boolean alwaysDrawTrack) { mAlwaysDrawVerticalTrack = alwaysDrawTrack; }
See Also:
Returns:whether the vertical scrollbar track should always be drawn regardless of the extent.
/** * @return whether the vertical scrollbar track should always be drawn * regardless of the extent. * * @see #setAlwaysDrawVerticalTrack(boolean) */
public boolean getAlwaysDrawVerticalTrack() { return mAlwaysDrawVerticalTrack; }
See Also:
Returns:whether the horizontal scrollbar track should always be drawn regardless of the extent.
/** * @return whether the horizontal scrollbar track should always be drawn * regardless of the extent. * * @see #setAlwaysDrawHorizontalTrack(boolean) */
public boolean getAlwaysDrawHorizontalTrack() { return mAlwaysDrawHorizontalTrack; } public void setParameters(int range, int offset, int extent, boolean vertical) { if (mVertical != vertical) { mVertical = vertical; mBoundsChanged = true; } if (mRange != range || mOffset != offset || mExtent != extent) { mRange = range; mOffset = offset; mExtent = extent; mRangeChanged = true; } } @Override public void draw(Canvas canvas) { final boolean vertical = mVertical; final int extent = mExtent; final int range = mRange; boolean drawTrack = true; boolean drawThumb = true; if (extent <= 0 || range <= extent) { drawTrack = vertical ? mAlwaysDrawVerticalTrack : mAlwaysDrawHorizontalTrack; drawThumb = false; } final Rect r = getBounds(); if (canvas.quickReject(r.left, r.top, r.right, r.bottom, Canvas.EdgeType.AA)) { return; } if (drawTrack) { drawTrack(canvas, r, vertical); } if (drawThumb) { final int scrollBarLength = vertical ? r.height() : r.width(); final int thickness = vertical ? r.width() : r.height(); final int thumbLength = ScrollBarUtils.getThumbLength(scrollBarLength, thickness, extent, range); final int thumbOffset = ScrollBarUtils.getThumbOffset(scrollBarLength, thumbLength, extent, range, mOffset); drawThumb(canvas, r, thumbOffset, thumbLength, vertical); } } @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); mBoundsChanged = true; } @Override public boolean isStateful() { return (mVerticalTrack != null && mVerticalTrack.isStateful()) || (mVerticalThumb != null && mVerticalThumb.isStateful()) || (mHorizontalTrack != null && mHorizontalTrack.isStateful()) || (mHorizontalThumb != null && mHorizontalThumb.isStateful()) || super.isStateful(); } @Override protected boolean onStateChange(int[] state) { boolean changed = super.onStateChange(state); if (mVerticalTrack != null) { changed |= mVerticalTrack.setState(state); } if (mVerticalThumb != null) { changed |= mVerticalThumb.setState(state); } if (mHorizontalTrack != null) { changed |= mHorizontalTrack.setState(state); } if (mHorizontalThumb != null) { changed |= mHorizontalThumb.setState(state); } return changed; } private void drawTrack(Canvas canvas, Rect bounds, boolean vertical) { final Drawable track; if (vertical) { track = mVerticalTrack; } else { track = mHorizontalTrack; } if (track != null) { if (mBoundsChanged) { track.setBounds(bounds); } track.draw(canvas); } } private void drawThumb(Canvas canvas, Rect bounds, int offset, int length, boolean vertical) { final boolean changed = mRangeChanged || mBoundsChanged; if (vertical) { if (mVerticalThumb != null) { final Drawable thumb = mVerticalThumb; if (changed) { thumb.setBounds(bounds.left, bounds.top + offset, bounds.right, bounds.top + offset + length); } thumb.draw(canvas); } } else { if (mHorizontalThumb != null) { final Drawable thumb = mHorizontalThumb; if (changed) { thumb.setBounds(bounds.left + offset, bounds.top, bounds.left + offset + length, bounds.bottom); } thumb.draw(canvas); } } } public void setVerticalThumbDrawable(Drawable thumb) { if (mVerticalThumb != null) { mVerticalThumb.setCallback(null); } propagateCurrentState(thumb); mVerticalThumb = thumb; } public void setVerticalTrackDrawable(Drawable track) { if (mVerticalTrack != null) { mVerticalTrack.setCallback(null); } propagateCurrentState(track); mVerticalTrack = track; } public void setHorizontalThumbDrawable(Drawable thumb) { if (mHorizontalThumb != null) { mHorizontalThumb.setCallback(null); } propagateCurrentState(thumb); mHorizontalThumb = thumb; } public void setHorizontalTrackDrawable(Drawable track) { if (mHorizontalTrack != null) { mHorizontalTrack.setCallback(null); } propagateCurrentState(track); mHorizontalTrack = track; } private void propagateCurrentState(Drawable d) { if (d != null) { if (mMutated) { d.mutate(); } d.setState(getState()); d.setCallback(this); if (mHasSetAlpha) { d.setAlpha(mAlpha); } if (mHasSetColorFilter) { d.setColorFilter(mColorFilter); } } } public int getSize(boolean vertical) { if (vertical) { return mVerticalTrack != null ? mVerticalTrack.getIntrinsicWidth() : mVerticalThumb != null ? mVerticalThumb.getIntrinsicWidth() : 0; } else { return mHorizontalTrack != null ? mHorizontalTrack.getIntrinsicHeight() : mHorizontalThumb != null ? mHorizontalThumb.getIntrinsicHeight() : 0; } } @Override public ScrollBarDrawable mutate() { if (!mMutated && super.mutate() == this) { if (mVerticalTrack != null) { mVerticalTrack.mutate(); } if (mVerticalThumb != null) { mVerticalThumb.mutate(); } if (mHorizontalTrack != null) { mHorizontalTrack.mutate(); } if (mHorizontalThumb != null) { mHorizontalThumb.mutate(); } mMutated = true; } return this; } @Override public void setAlpha(int alpha) { mAlpha = alpha; mHasSetAlpha = true; if (mVerticalTrack != null) { mVerticalTrack.setAlpha(alpha); } if (mVerticalThumb != null) { mVerticalThumb.setAlpha(alpha); } if (mHorizontalTrack != null) { mHorizontalTrack.setAlpha(alpha); } if (mHorizontalThumb != null) { mHorizontalThumb.setAlpha(alpha); } } @Override public int getAlpha() { return mAlpha; } @Override public void setColorFilter(ColorFilter colorFilter) { mColorFilter = colorFilter; mHasSetColorFilter = true; if (mVerticalTrack != null) { mVerticalTrack.setColorFilter(colorFilter); } if (mVerticalThumb != null) { mVerticalThumb.setColorFilter(colorFilter); } if (mHorizontalTrack != null) { mHorizontalTrack.setColorFilter(colorFilter); } if (mHorizontalThumb != null) { mHorizontalThumb.setColorFilter(colorFilter); } } @Override public ColorFilter getColorFilter() { return mColorFilter; } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } @Override public void invalidateDrawable(@NonNull Drawable who) { invalidateSelf(); } @Override public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) { scheduleSelf(what, when); } @Override public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) { unscheduleSelf(what); } @Override public String toString() { return "ScrollBarDrawable: range=" + mRange + " offset=" + mOffset + " extent=" + mExtent + (mVertical ? " V" : " H"); } }