• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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 com.android.launcher;
18 
19 import android.widget.TextView;
20 import android.content.Context;
21 import android.util.AttributeSet;
22 import android.graphics.Canvas;
23 import android.graphics.Paint;
24 import android.graphics.RectF;
25 import android.graphics.drawable.Drawable;
26 import android.text.Layout;
27 
28 /**
29  * TextView that draws a bubble behind the text. We cannot use a LineBackgroundSpan
30  * because we want to make the bubble taller than the text and TextView's clip is
31  * too aggressive.
32  */
33 public class BubbleTextView extends TextView {
34     private static final float CORNER_RADIUS = 8.0f;
35     private static final float PADDING_H = 5.0f;
36     private static final float PADDING_V = 1.0f;
37 
38     private final RectF mRect = new RectF();
39     private Paint mPaint;
40 
41     private boolean mBackgroundSizeChanged;
42     private Drawable mBackground;
43     private float mCornerRadius;
44     private float mPaddingH;
45     private float mPaddingV;
46 
BubbleTextView(Context context)47     public BubbleTextView(Context context) {
48         super(context);
49         init();
50     }
51 
BubbleTextView(Context context, AttributeSet attrs)52     public BubbleTextView(Context context, AttributeSet attrs) {
53         super(context, attrs);
54         init();
55     }
56 
BubbleTextView(Context context, AttributeSet attrs, int defStyle)57     public BubbleTextView(Context context, AttributeSet attrs, int defStyle) {
58         super(context, attrs, defStyle);
59         init();
60     }
61 
init()62     private void init() {
63         setFocusable(true);
64         mBackground = getBackground();
65         setBackgroundDrawable(null);
66         mBackground.setCallback(this);
67 
68         mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
69         mPaint.setColor(getContext().getResources().getColor(R.color.bubble_dark_background));
70 
71         final float scale = getContext().getResources().getDisplayMetrics().density;
72         mCornerRadius = CORNER_RADIUS * scale;
73         mPaddingH = PADDING_H * scale;
74         //noinspection PointlessArithmeticExpression
75         mPaddingV = PADDING_V * scale;
76     }
77 
78     @Override
setFrame(int left, int top, int right, int bottom)79     protected boolean setFrame(int left, int top, int right, int bottom) {
80         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
81             mBackgroundSizeChanged = true;
82         }
83         return super.setFrame(left, top, right, bottom);
84     }
85 
86     @Override
verifyDrawable(Drawable who)87     protected boolean verifyDrawable(Drawable who) {
88         return who == mBackground || super.verifyDrawable(who);
89     }
90 
91     @Override
drawableStateChanged()92     protected void drawableStateChanged() {
93         Drawable d = mBackground;
94         if (d != null && d.isStateful()) {
95             d.setState(getDrawableState());
96         }
97         super.drawableStateChanged();
98     }
99 
100     @Override
draw(Canvas canvas)101     public void draw(Canvas canvas) {
102         final Drawable background = mBackground;
103         if (background != null) {
104             final int scrollX = mScrollX;
105             final int scrollY = mScrollY;
106 
107             if (mBackgroundSizeChanged) {
108                 background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
109                 mBackgroundSizeChanged = false;
110             }
111 
112             if ((scrollX | scrollY) == 0) {
113                 background.draw(canvas);
114             } else {
115                 canvas.translate(scrollX, scrollY);
116                 background.draw(canvas);
117                 canvas.translate(-scrollX, -scrollY);
118             }
119         }
120 
121         final Layout layout = getLayout();
122         final RectF rect = mRect;
123         final int left = getCompoundPaddingLeft();
124         final int top = getExtendedPaddingTop();
125 
126         rect.set(left + layout.getLineLeft(0) - mPaddingH,
127                 top + layout.getLineTop(0) -  mPaddingV,
128                 Math.min(left + layout.getLineRight(0) + mPaddingH, mScrollX + mRight - mLeft),
129                 top + layout.getLineBottom(0) + mPaddingV);
130         canvas.drawRoundRect(rect, mCornerRadius, mCornerRadius, mPaint);
131 
132         super.draw(canvas);
133     }
134 }
135