| /* |
| * 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.graphics.Canvas; |
| import android.graphics.ColorFilter; |
| import android.graphics.PixelFormat; |
| import android.graphics.Rect; |
| import android.graphics.drawable.Drawable; |
| |
| /** |
| * 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 { |
| 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 mChanged; |
| private boolean mRangeChanged; |
| private final Rect mTempBounds = new Rect(); |
| private boolean mAlwaysDrawHorizontalTrack; |
| private boolean mAlwaysDrawVerticalTrack; |
| |
| public ScrollBarDrawable() { |
| } |
| |
| /** |
| * Indicate whether the horizontal scrollbar track should always be drawn regardless of the |
| * extent. Defaults to false. |
| * |
| * @param alwaysDrawTrack Set to true if the track should always be drawn |
| */ |
| 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 Set to true if the track should always be drawn |
| */ |
| public void setAlwaysDrawVerticalTrack(boolean alwaysDrawTrack) { |
| mAlwaysDrawVerticalTrack = alwaysDrawTrack; |
| } |
| |
| /** |
| * Indicates whether the vertical scrollbar track should always be drawn regardless of the |
| * extent. |
| */ |
| public boolean getAlwaysDrawVerticalTrack() { |
| return mAlwaysDrawVerticalTrack; |
| } |
| |
| /** |
| * Indicates whether the horizontal scrollbar track should always be drawn regardless of the |
| * extent. |
| */ |
| public boolean getAlwaysDrawHorizontalTrack() { |
| return mAlwaysDrawHorizontalTrack; |
| } |
| |
| public void setParameters(int range, int offset, int extent, boolean vertical) { |
| if (mVertical != vertical) { |
| mChanged = true; |
| } |
| |
| if (mRange != range || mOffset != offset || mExtent != extent) { |
| mRangeChanged = true; |
| } |
| |
| mRange = range; |
| mOffset = offset; |
| mExtent = extent; |
| mVertical = vertical; |
| } |
| |
| @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; |
| } |
| |
| 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) { |
| int size = vertical ? r.height() : r.width(); |
| int thickness = vertical ? r.width() : r.height(); |
| int length = Math.round((float) size * extent / range); |
| int offset = Math.round((float) (size - length) * mOffset / (range - extent)); |
| |
| // avoid the tiny thumb |
| int minLength = thickness * 2; |
| if (length < minLength) { |
| length = minLength; |
| } |
| // avoid the too-big thumb |
| if (offset + length > size) { |
| offset = size - length; |
| } |
| |
| drawThumb(canvas, r, offset, length, vertical); |
| } |
| } |
| |
| @Override |
| protected void onBoundsChange(Rect bounds) { |
| super.onBoundsChange(bounds); |
| mChanged = true; |
| } |
| |
| protected void drawTrack(Canvas canvas, Rect bounds, boolean vertical) { |
| Drawable track; |
| if (vertical) { |
| track = mVerticalTrack; |
| } else { |
| track = mHorizontalTrack; |
| } |
| if (track != null) { |
| if (mChanged) { |
| track.setBounds(bounds); |
| } |
| track.draw(canvas); |
| } |
| } |
| |
| protected void drawThumb(Canvas canvas, Rect bounds, int offset, int length, boolean vertical) { |
| final Rect thumbRect = mTempBounds; |
| final boolean changed = mRangeChanged || mChanged; |
| if (changed) { |
| if (vertical) { |
| thumbRect.set(bounds.left, bounds.top + offset, |
| bounds.right, bounds.top + offset + length); |
| } else { |
| thumbRect.set(bounds.left + offset, bounds.top, |
| bounds.left + offset + length, bounds.bottom); |
| } |
| } |
| |
| if (vertical) { |
| if (mVerticalThumb != null) { |
| final Drawable thumb = mVerticalThumb; |
| if (changed) thumb.setBounds(thumbRect); |
| thumb.draw(canvas); |
| } |
| } else { |
| if (mHorizontalThumb != null) { |
| final Drawable thumb = mHorizontalThumb; |
| if (changed) thumb.setBounds(thumbRect); |
| thumb.draw(canvas); |
| } |
| } |
| } |
| |
| public void setVerticalThumbDrawable(Drawable thumb) { |
| if (thumb != null) { |
| mVerticalThumb = thumb; |
| } |
| } |
| |
| public void setVerticalTrackDrawable(Drawable track) { |
| mVerticalTrack = track; |
| } |
| |
| public void setHorizontalThumbDrawable(Drawable thumb) { |
| if (thumb != null) { |
| mHorizontalThumb = thumb; |
| } |
| } |
| |
| public void setHorizontalTrackDrawable(Drawable track) { |
| mHorizontalTrack = track; |
| } |
| |
| 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 void setAlpha(int alpha) { |
| 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() { |
| // All elements should have same alpha, just return one of them |
| return mVerticalThumb.getAlpha(); |
| } |
| |
| @Override |
| public void setColorFilter(ColorFilter cf) { |
| if (mVerticalTrack != null) { |
| mVerticalTrack.setColorFilter(cf); |
| } |
| if (mVerticalThumb != null) { |
| mVerticalThumb.setColorFilter(cf); |
| } |
| if (mHorizontalTrack != null) { |
| mHorizontalTrack.setColorFilter(cf); |
| } |
| if (mHorizontalThumb != null) { |
| mHorizontalThumb.setColorFilter(cf); |
| } |
| } |
| |
| @Override |
| public int getOpacity() { |
| return PixelFormat.TRANSLUCENT; |
| } |
| |
| @Override |
| public String toString() { |
| return "ScrollBarDrawable: range=" + mRange + " offset=" + mOffset + |
| " extent=" + mExtent + (mVertical ? " V" : " H"); |
| } |
| } |
| |
| |