blob: 91d6232161376621250b2ccd878f7c338c41c949 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
17package android.widget;
18
19import android.graphics.Canvas;
20import android.graphics.ColorFilter;
21import android.graphics.PixelFormat;
22import android.graphics.Rect;
23import android.graphics.drawable.Drawable;
24
25/**
Alan Viverette029d0392015-01-21 15:41:53 -080026 * This is only used by View for displaying its scroll bars. It should probably
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027 * 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.
Alan Viverette029d0392015-01-21 15:41:53 -080029 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030 * {@hide}
31 */
Alan Viverette029d0392015-01-21 15:41:53 -080032public class ScrollBarDrawable extends Drawable implements Drawable.Callback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033 private Drawable mVerticalTrack;
34 private Drawable mHorizontalTrack;
35 private Drawable mVerticalThumb;
36 private Drawable mHorizontalThumb;
Alan Viverette029d0392015-01-21 15:41:53 -080037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038 private int mRange;
39 private int mOffset;
40 private int mExtent;
Alan Viverette029d0392015-01-21 15:41:53 -080041
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042 private boolean mVertical;
Alan Viverette029d0392015-01-21 15:41:53 -080043 private boolean mBoundsChanged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044 private boolean mRangeChanged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045 private boolean mAlwaysDrawHorizontalTrack;
46 private boolean mAlwaysDrawVerticalTrack;
Alan Viverettef8512ce2015-02-05 15:58:56 -080047 private boolean mMutated;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048
Alan Viverette029d0392015-01-21 15:41:53 -080049 private int mAlpha = 255;
50 private boolean mHasSetAlpha;
51
52 private ColorFilter mColorFilter;
53 private boolean mHasSetColorFilter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054
55 /**
Alan Viverette029d0392015-01-21 15:41:53 -080056 * Indicate whether the horizontal scrollbar track should always be drawn
57 * regardless of the extent. Defaults to false.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058 *
Alan Viverette029d0392015-01-21 15:41:53 -080059 * @param alwaysDrawTrack Whether the track should always be drawn
60 *
61 * @see #getAlwaysDrawHorizontalTrack()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062 */
63 public void setAlwaysDrawHorizontalTrack(boolean alwaysDrawTrack) {
64 mAlwaysDrawHorizontalTrack = alwaysDrawTrack;
65 }
66
67 /**
Alan Viverette029d0392015-01-21 15:41:53 -080068 * Indicate whether the vertical scrollbar track should always be drawn
69 * regardless of the extent. Defaults to false.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070 *
Alan Viverette029d0392015-01-21 15:41:53 -080071 * @param alwaysDrawTrack Whether the track should always be drawn
72 *
73 * @see #getAlwaysDrawVerticalTrack()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074 */
75 public void setAlwaysDrawVerticalTrack(boolean alwaysDrawTrack) {
76 mAlwaysDrawVerticalTrack = alwaysDrawTrack;
77 }
78
79 /**
Alan Viverette029d0392015-01-21 15:41:53 -080080 * @return whether the vertical scrollbar track should always be drawn
81 * regardless of the extent.
82 *
83 * @see #setAlwaysDrawVerticalTrack(boolean)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 */
85 public boolean getAlwaysDrawVerticalTrack() {
86 return mAlwaysDrawVerticalTrack;
87 }
88
89 /**
Alan Viverette029d0392015-01-21 15:41:53 -080090 * @return whether the horizontal scrollbar track should always be drawn
91 * regardless of the extent.
92 *
93 * @see #setAlwaysDrawHorizontalTrack(boolean)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094 */
95 public boolean getAlwaysDrawHorizontalTrack() {
96 return mAlwaysDrawHorizontalTrack;
97 }
98
99 public void setParameters(int range, int offset, int extent, boolean vertical) {
100 if (mVertical != vertical) {
Alan Viverette029d0392015-01-21 15:41:53 -0800101 mVertical = vertical;
102
103 mBoundsChanged = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104 }
105
106 if (mRange != range || mOffset != offset || mExtent != extent) {
Alan Viverette029d0392015-01-21 15:41:53 -0800107 mRange = range;
108 mOffset = offset;
109 mExtent = extent;
110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 mRangeChanged = true;
112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 }
114
115 @Override
116 public void draw(Canvas canvas) {
117 final boolean vertical = mVertical;
118 final int extent = mExtent;
119 final int range = mRange;
120
121 boolean drawTrack = true;
122 boolean drawThumb = true;
123 if (extent <= 0 || range <= extent) {
124 drawTrack = vertical ? mAlwaysDrawVerticalTrack : mAlwaysDrawHorizontalTrack;
125 drawThumb = false;
126 }
127
Alan Viverette029d0392015-01-21 15:41:53 -0800128 final Rect r = getBounds();
Romain Guy8fb95422010-08-17 18:38:51 -0700129 if (canvas.quickReject(r.left, r.top, r.right, r.bottom, Canvas.EdgeType.AA)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130 return;
131 }
Alan Viverette029d0392015-01-21 15:41:53 -0800132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 if (drawTrack) {
134 drawTrack(canvas, r, vertical);
135 }
136
137 if (drawThumb) {
Alan Viverette029d0392015-01-21 15:41:53 -0800138 final int size = vertical ? r.height() : r.width();
139 final int thickness = vertical ? r.width() : r.height();
140 final int minLength = thickness * 2;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141
Alan Viverette029d0392015-01-21 15:41:53 -0800142 // Avoid the tiny thumb.
143 int length = Math.round((float) size * extent / range);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144 if (length < minLength) {
145 length = minLength;
146 }
Alan Viverette029d0392015-01-21 15:41:53 -0800147
148 // Avoid the too-big thumb.
149 int offset = Math.round((float) (size - length) * mOffset / (range - extent));
150 if (offset > size - length) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 offset = size - length;
152 }
153
154 drawThumb(canvas, r, offset, length, vertical);
155 }
156 }
157
158 @Override
159 protected void onBoundsChange(Rect bounds) {
160 super.onBoundsChange(bounds);
Alan Viverette029d0392015-01-21 15:41:53 -0800161 mBoundsChanged = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 }
163
Alan Viverette029d0392015-01-21 15:41:53 -0800164 @Override
165 public boolean isStateful() {
166 return (mVerticalTrack != null && mVerticalTrack.isStateful())
167 || (mVerticalThumb != null && mVerticalThumb.isStateful())
168 || (mHorizontalTrack != null && mHorizontalTrack.isStateful())
169 || (mHorizontalThumb != null && mHorizontalThumb.isStateful())
170 || super.isStateful();
171 }
172
173 @Override
174 protected boolean onStateChange(int[] state) {
175 boolean changed = super.onStateChange(state);
176 if (mVerticalTrack != null) {
177 changed |= mVerticalTrack.setState(state);
178 }
179 if (mVerticalThumb != null) {
180 changed |= mVerticalThumb.setState(state);
181 }
182 if (mHorizontalTrack != null) {
183 changed |= mHorizontalTrack.setState(state);
184 }
185 if (mHorizontalThumb != null) {
186 changed |= mHorizontalThumb.setState(state);
187 }
188 return changed;
189 }
190
191 private void drawTrack(Canvas canvas, Rect bounds, boolean vertical) {
192 final Drawable track;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 if (vertical) {
194 track = mVerticalTrack;
195 } else {
196 track = mHorizontalTrack;
197 }
Alan Viverette029d0392015-01-21 15:41:53 -0800198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 if (track != null) {
Alan Viverette029d0392015-01-21 15:41:53 -0800200 if (mBoundsChanged) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 track.setBounds(bounds);
202 }
203 track.draw(canvas);
204 }
205 }
206
Alan Viverette029d0392015-01-21 15:41:53 -0800207 private void drawThumb(Canvas canvas, Rect bounds, int offset, int length, boolean vertical) {
208 final boolean changed = mRangeChanged || mBoundsChanged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 if (vertical) {
Chet Haase6c8fef72014-06-27 16:49:05 -0700210 if (mVerticalThumb != null) {
211 final Drawable thumb = mVerticalThumb;
Alan Viverette029d0392015-01-21 15:41:53 -0800212 if (changed) {
213 thumb.setBounds(bounds.left, bounds.top + offset,
214 bounds.right, bounds.top + offset + length);
215 }
216
Chet Haase6c8fef72014-06-27 16:49:05 -0700217 thumb.draw(canvas);
218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 } else {
Chet Haase6c8fef72014-06-27 16:49:05 -0700220 if (mHorizontalThumb != null) {
221 final Drawable thumb = mHorizontalThumb;
Alan Viverette029d0392015-01-21 15:41:53 -0800222 if (changed) {
223 thumb.setBounds(bounds.left + offset, bounds.top,
224 bounds.left + offset + length, bounds.bottom);
225 }
226
Chet Haase6c8fef72014-06-27 16:49:05 -0700227 thumb.draw(canvas);
228 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 }
230 }
231
232 public void setVerticalThumbDrawable(Drawable thumb) {
Alan Viverette029d0392015-01-21 15:41:53 -0800233 if (mVerticalThumb != null) {
234 mVerticalThumb.setCallback(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 }
Alan Viverette029d0392015-01-21 15:41:53 -0800236
237 propagateCurrentState(thumb);
238 mVerticalThumb = thumb;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 }
240
241 public void setVerticalTrackDrawable(Drawable track) {
Alan Viverette029d0392015-01-21 15:41:53 -0800242 if (mVerticalTrack != null) {
243 mVerticalTrack.setCallback(null);
Alan Viverette03748a52015-01-15 13:00:21 -0800244 }
Alan Viverette029d0392015-01-21 15:41:53 -0800245
246 propagateCurrentState(track);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 mVerticalTrack = track;
248 }
249
250 public void setHorizontalThumbDrawable(Drawable thumb) {
Alan Viverette029d0392015-01-21 15:41:53 -0800251 if (mHorizontalThumb != null) {
252 mHorizontalThumb.setCallback(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 }
Alan Viverette029d0392015-01-21 15:41:53 -0800254
255 propagateCurrentState(thumb);
256 mHorizontalThumb = thumb;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 }
258
259 public void setHorizontalTrackDrawable(Drawable track) {
Alan Viverette029d0392015-01-21 15:41:53 -0800260 if (mHorizontalTrack != null) {
261 mHorizontalTrack.setCallback(null);
Alan Viverette03748a52015-01-15 13:00:21 -0800262 }
Alan Viverette029d0392015-01-21 15:41:53 -0800263
264 propagateCurrentState(track);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 mHorizontalTrack = track;
266 }
267
Alan Viverette029d0392015-01-21 15:41:53 -0800268 private void propagateCurrentState(Drawable d) {
269 if (d != null) {
Alan Viveretteb989c552015-02-05 17:10:47 -0800270 if (mMutated) {
271 d.mutate();
272 }
273
Alan Viverette029d0392015-01-21 15:41:53 -0800274 d.setState(getState());
275 d.setCallback(this);
276
277 if (mHasSetAlpha) {
278 d.setAlpha(mAlpha);
279 }
280
281 if (mHasSetColorFilter) {
282 d.setColorFilter(mColorFilter);
283 }
284 }
285 }
286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 public int getSize(boolean vertical) {
288 if (vertical) {
Chet Haase6c8fef72014-06-27 16:49:05 -0700289 return mVerticalTrack != null ? mVerticalTrack.getIntrinsicWidth() :
290 mVerticalThumb != null ? mVerticalThumb.getIntrinsicWidth() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 } else {
Chet Haase6c8fef72014-06-27 16:49:05 -0700292 return mHorizontalTrack != null ? mHorizontalTrack.getIntrinsicHeight() :
293 mHorizontalThumb != null ? mHorizontalThumb.getIntrinsicHeight() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294 }
295 }
296
297 @Override
Alan Viverettef8512ce2015-02-05 15:58:56 -0800298 public ScrollBarDrawable mutate() {
299 if (!mMutated && super.mutate() == this) {
300 if (mVerticalTrack != null) {
301 mVerticalTrack.mutate();
302 }
303 if (mVerticalThumb != null) {
304 mVerticalThumb.mutate();
305 }
306 if (mHorizontalTrack != null) {
307 mHorizontalTrack.mutate();
308 }
309 if (mHorizontalThumb != null) {
310 mHorizontalThumb.mutate();
311 }
312 mMutated = true;
313 }
314 return this;
315 }
316
317 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 public void setAlpha(int alpha) {
Alan Viverette029d0392015-01-21 15:41:53 -0800319 mAlpha = alpha;
320 mHasSetAlpha = true;
321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 if (mVerticalTrack != null) {
323 mVerticalTrack.setAlpha(alpha);
324 }
Chet Haase6c8fef72014-06-27 16:49:05 -0700325 if (mVerticalThumb != null) {
326 mVerticalThumb.setAlpha(alpha);
327 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 if (mHorizontalTrack != null) {
329 mHorizontalTrack.setAlpha(alpha);
330 }
Chet Haase6c8fef72014-06-27 16:49:05 -0700331 if (mHorizontalThumb != null) {
332 mHorizontalThumb.setAlpha(alpha);
333 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 }
335
336 @Override
Chet Haaseb1af7f32013-03-08 14:02:04 -0800337 public int getAlpha() {
Alan Viverette029d0392015-01-21 15:41:53 -0800338 return mAlpha;
Chet Haaseb1af7f32013-03-08 14:02:04 -0800339 }
340
341 @Override
Chris Craikbd3bfc52015-03-02 10:43:29 -0800342 public void setColorFilter(ColorFilter colorFilter) {
343 mColorFilter = colorFilter;
Alan Viverette029d0392015-01-21 15:41:53 -0800344 mHasSetColorFilter = true;
345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346 if (mVerticalTrack != null) {
Chris Craikbd3bfc52015-03-02 10:43:29 -0800347 mVerticalTrack.setColorFilter(colorFilter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 }
Chet Haase6c8fef72014-06-27 16:49:05 -0700349 if (mVerticalThumb != null) {
Chris Craikbd3bfc52015-03-02 10:43:29 -0800350 mVerticalThumb.setColorFilter(colorFilter);
Chet Haase6c8fef72014-06-27 16:49:05 -0700351 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352 if (mHorizontalTrack != null) {
Chris Craikbd3bfc52015-03-02 10:43:29 -0800353 mHorizontalTrack.setColorFilter(colorFilter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 }
Chet Haase6c8fef72014-06-27 16:49:05 -0700355 if (mHorizontalThumb != null) {
Chris Craikbd3bfc52015-03-02 10:43:29 -0800356 mHorizontalThumb.setColorFilter(colorFilter);
Chet Haase6c8fef72014-06-27 16:49:05 -0700357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 }
359
360 @Override
Alan Viverette029d0392015-01-21 15:41:53 -0800361 public ColorFilter getColorFilter() {
362 return mColorFilter;
363 }
364
365 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 public int getOpacity() {
367 return PixelFormat.TRANSLUCENT;
368 }
369
370 @Override
Alan Viverette029d0392015-01-21 15:41:53 -0800371 public void invalidateDrawable(Drawable who) {
372 invalidateSelf();
373 }
374
375 @Override
376 public void scheduleDrawable(Drawable who, Runnable what, long when) {
377 scheduleSelf(what, when);
378 }
379
380 @Override
381 public void unscheduleDrawable(Drawable who, Runnable what) {
382 unscheduleSelf(what);
383 }
384
385 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 public String toString() {
387 return "ScrollBarDrawable: range=" + mRange + " offset=" + mOffset +
388 " extent=" + mExtent + (mVertical ? " V" : " H");
389 }
390}
391
392