1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.widget; 18 19 import android.graphics.Canvas; 20 import android.graphics.ColorFilter; 21 import android.graphics.PixelFormat; 22 import android.graphics.Rect; 23 import android.graphics.drawable.Drawable; 24 25 /** 26 * This is only used by View for displaying its scroll bars. It should probably 27 * be moved in to the view package since it is used in that lower-level layer. 28 * For now, we'll hide it so it can be cleaned up later. 29 * {@hide} 30 */ 31 public class ScrollBarDrawable extends Drawable { 32 private Drawable mVerticalTrack; 33 private Drawable mHorizontalTrack; 34 private Drawable mVerticalThumb; 35 private Drawable mHorizontalThumb; 36 private int mRange; 37 private int mOffset; 38 private int mExtent; 39 private boolean mVertical; 40 private boolean mChanged; 41 private boolean mRangeChanged; 42 private final Rect mTempBounds = new Rect(); 43 private boolean mAlwaysDrawHorizontalTrack; 44 private boolean mAlwaysDrawVerticalTrack; 45 ScrollBarDrawable()46 public ScrollBarDrawable() { 47 } 48 49 /** 50 * Indicate whether the horizontal scrollbar track should always be drawn regardless of the 51 * extent. Defaults to false. 52 * 53 * @param alwaysDrawTrack Set to true if the track should always be drawn 54 */ setAlwaysDrawHorizontalTrack(boolean alwaysDrawTrack)55 public void setAlwaysDrawHorizontalTrack(boolean alwaysDrawTrack) { 56 mAlwaysDrawHorizontalTrack = alwaysDrawTrack; 57 } 58 59 /** 60 * Indicate whether the vertical scrollbar track should always be drawn regardless of the 61 * extent. Defaults to false. 62 * 63 * @param alwaysDrawTrack Set to true if the track should always be drawn 64 */ setAlwaysDrawVerticalTrack(boolean alwaysDrawTrack)65 public void setAlwaysDrawVerticalTrack(boolean alwaysDrawTrack) { 66 mAlwaysDrawVerticalTrack = alwaysDrawTrack; 67 } 68 69 /** 70 * Indicates whether the vertical scrollbar track should always be drawn regardless of the 71 * extent. 72 */ getAlwaysDrawVerticalTrack()73 public boolean getAlwaysDrawVerticalTrack() { 74 return mAlwaysDrawVerticalTrack; 75 } 76 77 /** 78 * Indicates whether the horizontal scrollbar track should always be drawn regardless of the 79 * extent. 80 */ getAlwaysDrawHorizontalTrack()81 public boolean getAlwaysDrawHorizontalTrack() { 82 return mAlwaysDrawHorizontalTrack; 83 } 84 setParameters(int range, int offset, int extent, boolean vertical)85 public void setParameters(int range, int offset, int extent, boolean vertical) { 86 if (mVertical != vertical) { 87 mChanged = true; 88 } 89 90 if (mRange != range || mOffset != offset || mExtent != extent) { 91 mRangeChanged = true; 92 } 93 94 mRange = range; 95 mOffset = offset; 96 mExtent = extent; 97 mVertical = vertical; 98 } 99 100 @Override draw(Canvas canvas)101 public void draw(Canvas canvas) { 102 final boolean vertical = mVertical; 103 final int extent = mExtent; 104 final int range = mRange; 105 106 boolean drawTrack = true; 107 boolean drawThumb = true; 108 if (extent <= 0 || range <= extent) { 109 drawTrack = vertical ? mAlwaysDrawVerticalTrack : mAlwaysDrawHorizontalTrack; 110 drawThumb = false; 111 } 112 113 Rect r = getBounds(); 114 if (canvas.quickReject(r.left, r.top, r.right, r.bottom, 115 Canvas.EdgeType.AA)) { 116 return; 117 } 118 if (drawTrack) { 119 drawTrack(canvas, r, vertical); 120 } 121 122 if (drawThumb) { 123 int size = vertical ? r.height() : r.width(); 124 int thickness = vertical ? r.width() : r.height(); 125 int length = Math.round((float) size * extent / range); 126 int offset = Math.round((float) (size - length) * mOffset / (range - extent)); 127 128 // avoid the tiny thumb 129 int minLength = thickness * 2; 130 if (length < minLength) { 131 length = minLength; 132 } 133 // avoid the too-big thumb 134 if (offset + length > size) { 135 offset = size - length; 136 } 137 138 drawThumb(canvas, r, offset, length, vertical); 139 } 140 } 141 142 @Override onBoundsChange(Rect bounds)143 protected void onBoundsChange(Rect bounds) { 144 super.onBoundsChange(bounds); 145 mChanged = true; 146 } 147 drawTrack(Canvas canvas, Rect bounds, boolean vertical)148 protected void drawTrack(Canvas canvas, Rect bounds, boolean vertical) { 149 Drawable track; 150 if (vertical) { 151 track = mVerticalTrack; 152 } else { 153 track = mHorizontalTrack; 154 } 155 if (track != null) { 156 if (mChanged) { 157 track.setBounds(bounds); 158 } 159 track.draw(canvas); 160 } 161 } 162 drawThumb(Canvas canvas, Rect bounds, int offset, int length, boolean vertical)163 protected void drawThumb(Canvas canvas, Rect bounds, int offset, int length, boolean vertical) { 164 final Rect thumbRect = mTempBounds; 165 final boolean changed = mRangeChanged || mChanged; 166 if (changed) { 167 if (vertical) { 168 thumbRect.set(bounds.left, bounds.top + offset, 169 bounds.right, bounds.top + offset + length); 170 } else { 171 thumbRect.set(bounds.left + offset, bounds.top, 172 bounds.left + offset + length, bounds.bottom); 173 } 174 } 175 176 if (vertical) { 177 final Drawable thumb = mVerticalThumb; 178 if (changed) thumb.setBounds(thumbRect); 179 thumb.draw(canvas); 180 } else { 181 final Drawable thumb = mHorizontalThumb; 182 if (changed) thumb.setBounds(thumbRect); 183 thumb.draw(canvas); 184 } 185 } 186 setVerticalThumbDrawable(Drawable thumb)187 public void setVerticalThumbDrawable(Drawable thumb) { 188 if (thumb != null) { 189 mVerticalThumb = thumb; 190 } 191 } 192 setVerticalTrackDrawable(Drawable track)193 public void setVerticalTrackDrawable(Drawable track) { 194 mVerticalTrack = track; 195 } 196 setHorizontalThumbDrawable(Drawable thumb)197 public void setHorizontalThumbDrawable(Drawable thumb) { 198 if (thumb != null) { 199 mHorizontalThumb = thumb; 200 } 201 } 202 setHorizontalTrackDrawable(Drawable track)203 public void setHorizontalTrackDrawable(Drawable track) { 204 mHorizontalTrack = track; 205 } 206 getSize(boolean vertical)207 public int getSize(boolean vertical) { 208 if (vertical) { 209 return (mVerticalTrack != null ? 210 mVerticalTrack : mVerticalThumb).getIntrinsicWidth(); 211 } else { 212 return (mHorizontalTrack != null ? 213 mHorizontalTrack : mHorizontalThumb).getIntrinsicHeight(); 214 } 215 } 216 217 @Override setAlpha(int alpha)218 public void setAlpha(int alpha) { 219 if (mVerticalTrack != null) { 220 mVerticalTrack.setAlpha(alpha); 221 } 222 mVerticalThumb.setAlpha(alpha); 223 if (mHorizontalTrack != null) { 224 mHorizontalTrack.setAlpha(alpha); 225 } 226 mHorizontalThumb.setAlpha(alpha); 227 } 228 229 @Override setColorFilter(ColorFilter cf)230 public void setColorFilter(ColorFilter cf) { 231 if (mVerticalTrack != null) { 232 mVerticalTrack.setColorFilter(cf); 233 } 234 mVerticalThumb.setColorFilter(cf); 235 if (mHorizontalTrack != null) { 236 mHorizontalTrack.setColorFilter(cf); 237 } 238 mHorizontalThumb.setColorFilter(cf); 239 } 240 241 @Override getOpacity()242 public int getOpacity() { 243 return PixelFormat.TRANSLUCENT; 244 } 245 246 @Override toString()247 public String toString() { 248 return "ScrollBarDrawable: range=" + mRange + " offset=" + mOffset + 249 " extent=" + mExtent + (mVertical ? " V" : " H"); 250 } 251 } 252 253 254