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, Canvas.EdgeType.AA)) { 115 return; 116 } 117 if (drawTrack) { 118 drawTrack(canvas, r, vertical); 119 } 120 121 if (drawThumb) { 122 int size = vertical ? r.height() : r.width(); 123 int thickness = vertical ? r.width() : r.height(); 124 int length = Math.round((float) size * extent / range); 125 int offset = Math.round((float) (size - length) * mOffset / (range - extent)); 126 127 // avoid the tiny thumb 128 int minLength = thickness * 2; 129 if (length < minLength) { 130 length = minLength; 131 } 132 // avoid the too-big thumb 133 if (offset + length > size) { 134 offset = size - length; 135 } 136 137 drawThumb(canvas, r, offset, length, vertical); 138 } 139 } 140 141 @Override onBoundsChange(Rect bounds)142 protected void onBoundsChange(Rect bounds) { 143 super.onBoundsChange(bounds); 144 mChanged = true; 145 } 146 drawTrack(Canvas canvas, Rect bounds, boolean vertical)147 protected void drawTrack(Canvas canvas, Rect bounds, boolean vertical) { 148 Drawable track; 149 if (vertical) { 150 track = mVerticalTrack; 151 } else { 152 track = mHorizontalTrack; 153 } 154 if (track != null) { 155 if (mChanged) { 156 track.setBounds(bounds); 157 } 158 track.draw(canvas); 159 } 160 } 161 drawThumb(Canvas canvas, Rect bounds, int offset, int length, boolean vertical)162 protected void drawThumb(Canvas canvas, Rect bounds, int offset, int length, boolean vertical) { 163 final Rect thumbRect = mTempBounds; 164 final boolean changed = mRangeChanged || mChanged; 165 if (changed) { 166 if (vertical) { 167 thumbRect.set(bounds.left, bounds.top + offset, 168 bounds.right, bounds.top + offset + length); 169 } else { 170 thumbRect.set(bounds.left + offset, bounds.top, 171 bounds.left + offset + length, bounds.bottom); 172 } 173 } 174 175 if (vertical) { 176 final Drawable thumb = mVerticalThumb; 177 if (changed) thumb.setBounds(thumbRect); 178 thumb.draw(canvas); 179 } else { 180 final Drawable thumb = mHorizontalThumb; 181 if (changed) thumb.setBounds(thumbRect); 182 thumb.draw(canvas); 183 } 184 } 185 setVerticalThumbDrawable(Drawable thumb)186 public void setVerticalThumbDrawable(Drawable thumb) { 187 if (thumb != null) { 188 mVerticalThumb = thumb; 189 } 190 } 191 setVerticalTrackDrawable(Drawable track)192 public void setVerticalTrackDrawable(Drawable track) { 193 mVerticalTrack = track; 194 } 195 setHorizontalThumbDrawable(Drawable thumb)196 public void setHorizontalThumbDrawable(Drawable thumb) { 197 if (thumb != null) { 198 mHorizontalThumb = thumb; 199 } 200 } 201 setHorizontalTrackDrawable(Drawable track)202 public void setHorizontalTrackDrawable(Drawable track) { 203 mHorizontalTrack = track; 204 } 205 getSize(boolean vertical)206 public int getSize(boolean vertical) { 207 if (vertical) { 208 return (mVerticalTrack != null ? 209 mVerticalTrack : mVerticalThumb).getIntrinsicWidth(); 210 } else { 211 return (mHorizontalTrack != null ? 212 mHorizontalTrack : mHorizontalThumb).getIntrinsicHeight(); 213 } 214 } 215 216 @Override setAlpha(int alpha)217 public void setAlpha(int alpha) { 218 if (mVerticalTrack != null) { 219 mVerticalTrack.setAlpha(alpha); 220 } 221 mVerticalThumb.setAlpha(alpha); 222 if (mHorizontalTrack != null) { 223 mHorizontalTrack.setAlpha(alpha); 224 } 225 mHorizontalThumb.setAlpha(alpha); 226 } 227 228 @Override setColorFilter(ColorFilter cf)229 public void setColorFilter(ColorFilter cf) { 230 if (mVerticalTrack != null) { 231 mVerticalTrack.setColorFilter(cf); 232 } 233 mVerticalThumb.setColorFilter(cf); 234 if (mHorizontalTrack != null) { 235 mHorizontalTrack.setColorFilter(cf); 236 } 237 mHorizontalThumb.setColorFilter(cf); 238 } 239 240 @Override getOpacity()241 public int getOpacity() { 242 return PixelFormat.TRANSLUCENT; 243 } 244 245 @Override toString()246 public String toString() { 247 return "ScrollBarDrawable: range=" + mRange + " offset=" + mOffset + 248 " extent=" + mExtent + (mVertical ? " V" : " H"); 249 } 250 } 251 252 253