• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.launcher3.popup;
18 
19 import android.content.Context;
20 import android.graphics.Bitmap;
21 import android.graphics.Canvas;
22 import android.graphics.Matrix;
23 import android.graphics.Paint;
24 import android.graphics.PorterDuff;
25 import android.graphics.PorterDuffXfermode;
26 import android.graphics.Rect;
27 import android.graphics.drawable.ShapeDrawable;
28 import android.graphics.drawable.shapes.RoundRectShape;
29 import android.util.AttributeSet;
30 import android.view.View;
31 import android.widget.FrameLayout;
32 
33 import com.android.launcher3.R;
34 import com.android.launcher3.Utilities;
35 import com.android.launcher3.popup.PopupContainerWithArrow.RoundedCornerFlags;
36 
37 import static com.android.launcher3.popup.PopupContainerWithArrow.ROUNDED_BOTTOM_CORNERS;
38 import static com.android.launcher3.popup.PopupContainerWithArrow.ROUNDED_TOP_CORNERS;
39 
40 /**
41  * An abstract {@link FrameLayout} that contains content for {@link PopupContainerWithArrow}.
42  */
43 public abstract class PopupItemView extends FrameLayout {
44 
45     protected final Rect mPillRect;
46     protected  @RoundedCornerFlags int mRoundedCorners;
47     protected final boolean mIsRtl;
48     protected View mIconView;
49 
50     private final Paint mBackgroundClipPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
51     private final Matrix mMatrix = new Matrix();
52     private Bitmap mRoundedCornerBitmap;
53 
PopupItemView(Context context)54     public PopupItemView(Context context) {
55         this(context, null, 0);
56     }
57 
PopupItemView(Context context, AttributeSet attrs)58     public PopupItemView(Context context, AttributeSet attrs) {
59         this(context, attrs, 0);
60     }
61 
PopupItemView(Context context, AttributeSet attrs, int defStyle)62     public PopupItemView(Context context, AttributeSet attrs, int defStyle) {
63         super(context, attrs, defStyle);
64 
65         mPillRect = new Rect();
66 
67         // Initialize corner clipping Bitmap and Paint.
68         int radius = (int) getBackgroundRadius();
69         mRoundedCornerBitmap = Bitmap.createBitmap(radius, radius, Bitmap.Config.ALPHA_8);
70         Canvas canvas = new Canvas();
71         canvas.setBitmap(mRoundedCornerBitmap);
72         canvas.drawArc(0, 0, radius*2, radius*2, 180, 90, true, mBackgroundClipPaint);
73         mBackgroundClipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
74 
75         mIsRtl = Utilities.isRtl(getResources());
76     }
77 
78     @Override
onFinishInflate()79     protected void onFinishInflate() {
80         super.onFinishInflate();
81         mIconView = findViewById(R.id.popup_item_icon);
82     }
83 
84     @Override
onMeasure(int widthMeasureSpec, int heightMeasureSpec)85     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
86         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
87         mPillRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
88     }
89 
90     @Override
dispatchDraw(Canvas canvas)91     protected void dispatchDraw(Canvas canvas) {
92         if (mRoundedCorners == 0) {
93             super.dispatchDraw(canvas);
94             return;
95         }
96 
97         int saveCount = canvas.saveLayer(0, 0, getWidth(), getHeight(), null);
98         super.dispatchDraw(canvas);
99 
100         // Clip children to this item's rounded corners.
101         int cornerWidth = mRoundedCornerBitmap.getWidth();
102         int cornerHeight = mRoundedCornerBitmap.getHeight();
103         int cornerCenterX = Math.round(cornerWidth / 2f);
104         int cornerCenterY = Math.round(cornerHeight / 2f);
105         if ((mRoundedCorners & ROUNDED_TOP_CORNERS) != 0) {
106             // Clip top left corner.
107             mMatrix.reset();
108             canvas.drawBitmap(mRoundedCornerBitmap, mMatrix, mBackgroundClipPaint);
109             // Clip top right corner.
110             mMatrix.setRotate(90, cornerCenterX, cornerCenterY);
111             mMatrix.postTranslate(canvas.getWidth() - cornerWidth, 0);
112             canvas.drawBitmap(mRoundedCornerBitmap, mMatrix, mBackgroundClipPaint);
113         }
114         if ((mRoundedCorners & ROUNDED_BOTTOM_CORNERS) != 0) {
115             // Clip bottom right corner.
116             mMatrix.setRotate(180, cornerCenterX, cornerCenterY);
117             mMatrix.postTranslate(canvas.getWidth() - cornerWidth, canvas.getHeight() - cornerHeight);
118             canvas.drawBitmap(mRoundedCornerBitmap, mMatrix, mBackgroundClipPaint);
119             // Clip bottom left corner.
120             mMatrix.setRotate(270, cornerCenterX, cornerCenterY);
121             mMatrix.postTranslate(0, canvas.getHeight() - cornerHeight);
122             canvas.drawBitmap(mRoundedCornerBitmap, mMatrix, mBackgroundClipPaint);
123         }
124 
125         canvas.restoreToCount(saveCount);
126     }
127 
128     /**
129      * Creates a round rect drawable (with the specified corners unrounded)
130      * and sets it as this View's background.
131      */
setBackgroundWithCorners(int color, @RoundedCornerFlags int roundedCorners)132     public void setBackgroundWithCorners(int color, @RoundedCornerFlags int roundedCorners) {
133         mRoundedCorners = roundedCorners;
134         float rTop = (roundedCorners & ROUNDED_TOP_CORNERS) == 0 ? 0 : getBackgroundRadius();
135         float rBot = (roundedCorners & ROUNDED_BOTTOM_CORNERS) == 0 ? 0 : getBackgroundRadius();
136         float[] radii = new float[] {rTop, rTop, rTop, rTop, rBot, rBot, rBot, rBot};
137         ShapeDrawable roundRectBackground = new ShapeDrawable(new RoundRectShape(radii, null, null));
138         roundRectBackground.getPaint().setColor(color);
139         setBackground(roundRectBackground);
140     }
141 
getBackgroundRadius()142     protected float getBackgroundRadius() {
143         return getResources().getDimensionPixelSize(R.dimen.bg_round_rect_radius);
144     }
145 }
146