436 lines
12 KiB
Java
436 lines
12 KiB
Java
![]() |
/*
|
||
|
* 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.annotation.Nullable;
|
||
|
import android.compat.annotation.UnsupportedAppUsage;
|
||
|
import android.graphics.Canvas;
|
||
|
import android.graphics.ColorFilter;
|
||
|
import android.graphics.PixelFormat;
|
||
|
import android.graphics.Rect;
|
||
|
import android.graphics.drawable.Drawable;
|
||
|
import android.os.Build;
|
||
|
import android.view.View;
|
||
|
|
||
|
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}
|
||
|
*/
|
||
|
public class ScrollBarDrawable extends Drawable implements Drawable.Callback {
|
||
|
private Drawable mVerticalTrack;
|
||
|
private Drawable mHorizontalTrack;
|
||
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768422)
|
||
|
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;
|
||
|
|
||
|
@UnsupportedAppUsage
|
||
|
public ScrollBarDrawable() {
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 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.
|
||
|
*
|
||
|
* @param alwaysDrawTrack Whether the track should always be drawn
|
||
|
*
|
||
|
* @see #getAlwaysDrawVerticalTrack()
|
||
|
*/
|
||
|
public void setAlwaysDrawVerticalTrack(boolean alwaysDrawTrack) {
|
||
|
mAlwaysDrawVerticalTrack = alwaysDrawTrack;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return whether the vertical scrollbar track should always be drawn
|
||
|
* regardless of the extent.
|
||
|
*
|
||
|
* @see #setAlwaysDrawVerticalTrack(boolean)
|
||
|
*/
|
||
|
public boolean getAlwaysDrawVerticalTrack() {
|
||
|
return mAlwaysDrawVerticalTrack;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @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)) {
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see android.view.View#setVerticalThumbDrawable(Drawable)
|
||
|
*/
|
||
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
|
||
|
public void setVerticalThumbDrawable(Drawable thumb) {
|
||
|
if (mVerticalThumb != null) {
|
||
|
mVerticalThumb.setCallback(null);
|
||
|
}
|
||
|
|
||
|
propagateCurrentState(thumb);
|
||
|
mVerticalThumb = thumb;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see View#getVerticalTrackDrawable()
|
||
|
*/
|
||
|
public @Nullable Drawable getVerticalTrackDrawable() {
|
||
|
return mVerticalTrack;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see View#getVerticalThumbDrawable()
|
||
|
*/
|
||
|
public @Nullable Drawable getVerticalThumbDrawable() {
|
||
|
return mVerticalThumb;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see View#getHorizontalTrackDrawable()
|
||
|
*/
|
||
|
public @Nullable Drawable getHorizontalTrackDrawable() {
|
||
|
return mHorizontalTrack;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see View#getHorizontalThumbDrawable()
|
||
|
*/
|
||
|
public @Nullable Drawable getHorizontalThumbDrawable() {
|
||
|
return mHorizontalThumb;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see android.view.View#setVerticalTrackDrawable(Drawable)
|
||
|
*/
|
||
|
public void setVerticalTrackDrawable(Drawable track) {
|
||
|
if (mVerticalTrack != null) {
|
||
|
mVerticalTrack.setCallback(null);
|
||
|
}
|
||
|
|
||
|
propagateCurrentState(track);
|
||
|
mVerticalTrack = track;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see android.view.View#setHorizontalThumbDrawable(Drawable)
|
||
|
*/
|
||
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
|
||
|
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");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|