1 /* 2 * Copyright (C) 2016 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.view; 18 19 import android.graphics.Canvas; 20 import android.graphics.Color; 21 import android.graphics.Paint; 22 import android.graphics.Rect; 23 import android.graphics.RectF; 24 25 /** 26 * Helper class for drawing round scroll bars on round Wear devices. 27 */ 28 class RoundScrollbarRenderer { 29 // The range of the scrollbar position represented as an angle in degrees. 30 private static final int SCROLLBAR_ANGLE_RANGE = 90; 31 private static final int MAX_SCROLLBAR_ANGLE_SWIPE = 16; 32 private static final int MIN_SCROLLBAR_ANGLE_SWIPE = 6; 33 private static final float WIDTH_PERCENTAGE = 0.02f; 34 private static final int DEFAULT_THUMB_COLOR = 0x4CFFFFFF; 35 private static final int DEFAULT_TRACK_COLOR = 0x26FFFFFF; 36 37 private final Paint mThumbPaint = new Paint(); 38 private final Paint mTrackPaint = new Paint(); 39 private final RectF mRect = new RectF(); 40 private final View mParent; 41 42 public RoundScrollbarRenderer(View parent) { 43 // Paints for the round scrollbar. 44 // Set up the thumb paint 45 mThumbPaint.setAntiAlias(true); 46 mThumbPaint.setStrokeCap(Paint.Cap.ROUND); 47 mThumbPaint.setStyle(Paint.Style.STROKE); 48 49 // Set up the track paint 50 mTrackPaint.setAntiAlias(true); 51 mTrackPaint.setStrokeCap(Paint.Cap.ROUND); 52 mTrackPaint.setStyle(Paint.Style.STROKE); 53 54 mParent = parent; 55 } 56 57 public void drawRoundScrollbars(Canvas canvas, float alpha, Rect bounds) { 58 if (alpha == 0) { 59 return; 60 } 61 // Get information about the current scroll state of the parent view. 62 float maxScroll = mParent.computeVerticalScrollRange(); 63 float scrollExtent = mParent.computeVerticalScrollExtent(); 64 if (scrollExtent <= 0 || maxScroll <= scrollExtent) { 65 return; 66 } 67 float currentScroll = Math.max(0, mParent.computeVerticalScrollOffset()); 68 float linearThumbLength = mParent.computeVerticalScrollExtent(); 69 float thumbWidth = mParent.getWidth() * WIDTH_PERCENTAGE; 70 mThumbPaint.setStrokeWidth(thumbWidth); 71 mTrackPaint.setStrokeWidth(thumbWidth); 72 73 setThumbColor(applyAlpha(DEFAULT_THUMB_COLOR, alpha)); 74 setTrackColor(applyAlpha(DEFAULT_TRACK_COLOR, alpha)); 75 76 // Normalize the sweep angle for the scroll bar. 77 float sweepAngle = (linearThumbLength / maxScroll) * SCROLLBAR_ANGLE_RANGE; 78 sweepAngle = clamp(sweepAngle, MIN_SCROLLBAR_ANGLE_SWIPE, MAX_SCROLLBAR_ANGLE_SWIPE); 79 // Normalize the start angle so that it falls on the track. 80 float startAngle = (currentScroll * (SCROLLBAR_ANGLE_RANGE - sweepAngle)) 81 / (maxScroll - linearThumbLength) - SCROLLBAR_ANGLE_RANGE / 2; 82 startAngle = clamp(startAngle, -SCROLLBAR_ANGLE_RANGE / 2, 83 SCROLLBAR_ANGLE_RANGE / 2 - sweepAngle); 84 85 // Draw the track and the scroll bar. 86 mRect.set( 87 bounds.left - thumbWidth / 2, 88 bounds.top, 89 bounds.right - thumbWidth / 2, 90 bounds.bottom); 91 92 canvas.drawArc(mRect, -SCROLLBAR_ANGLE_RANGE / 2, SCROLLBAR_ANGLE_RANGE, false, 93 mTrackPaint); 94 canvas.drawArc(mRect, startAngle, sweepAngle, false, mThumbPaint); 95 } 96 97 private static float clamp(float val, float min, float max) { 98 if (val < min) { 99 return min; 100 } else if (val > max) { 101 return max; 102 } else { 103 return val; 104 } 105 } 106 107 private static int applyAlpha(int color, float alpha) { 108 int alphaByte = (int) (Color.alpha(color) * alpha); 109 return Color.argb(alphaByte, Color.red(color), Color.green(color), Color.blue(color)); 110 } 111 112 private void setThumbColor(int thumbColor) { 113 if (mThumbPaint.getColor() != thumbColor) { 114 mThumbPaint.setColor(thumbColor); 115 } 116 } 117 118 private void setTrackColor(int trackColor) { 119 if (mTrackPaint.getColor() != trackColor) { 120 mTrackPaint.setColor(trackColor); 121 } 122 } 123 } 124