• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 com.android.launcher3.shortcuts;
18 
19 import android.content.Context;
20 import android.content.pm.ShortcutInfo;
21 import android.content.res.ColorStateList;
22 import android.graphics.Color;
23 import android.graphics.Point;
24 import android.graphics.drawable.ColorDrawable;
25 import android.graphics.drawable.Drawable;
26 import android.graphics.drawable.GradientDrawable;
27 import android.graphics.drawable.RippleDrawable;
28 import android.text.TextUtils;
29 import android.util.AttributeSet;
30 import android.view.View;
31 import android.widget.FrameLayout;
32 
33 import com.android.launcher3.BubbleTextView;
34 import com.android.launcher3.Launcher;
35 import com.android.launcher3.R;
36 import com.android.launcher3.Utilities;
37 import com.android.launcher3.model.data.WorkspaceItemInfo;
38 import com.android.launcher3.popup.PopupContainerWithArrow;
39 import com.android.launcher3.util.Themes;
40 import com.android.launcher3.views.BubbleTextHolder;
41 
42 /**
43  * A {@link android.widget.FrameLayout} that contains an icon and a {@link BubbleTextView} for text.
44  * This lets us animate the child BubbleTextView's background (transparent ripple) separately from
45  * the {@link DeepShortcutView} background color.
46  */
47 public class DeepShortcutView extends FrameLayout implements BubbleTextHolder {
48 
49     private static final Point sTempPoint = new Point();
50 
51     private final Drawable mTransparentDrawable = new ColorDrawable(Color.TRANSPARENT);
52 
53     private BubbleTextView mBubbleText;
54     private View mIconView;
55 
56     private WorkspaceItemInfo mInfo;
57     private ShortcutInfo mDetail;
58 
DeepShortcutView(Context context)59     public DeepShortcutView(Context context) {
60         this(context, null, 0);
61     }
62 
DeepShortcutView(Context context, AttributeSet attrs)63     public DeepShortcutView(Context context, AttributeSet attrs) {
64         this(context, attrs, 0);
65     }
66 
DeepShortcutView(Context context, AttributeSet attrs, int defStyle)67     public DeepShortcutView(Context context, AttributeSet attrs, int defStyle) {
68         super(context, attrs, defStyle);
69     }
70 
71     @Override
onFinishInflate()72     protected void onFinishInflate() {
73         super.onFinishInflate();
74         mBubbleText = findViewById(R.id.bubble_text);
75         mIconView = findViewById(R.id.icon);
76         tryUpdateTextBackground();
77     }
78 
79     @Override
setBackground(Drawable background)80     public void setBackground(Drawable background) {
81         super.setBackground(background);
82         tryUpdateTextBackground();
83     }
84 
85     @Override
setBackgroundResource(int resid)86     public void setBackgroundResource(int resid) {
87         super.setBackgroundResource(resid);
88         tryUpdateTextBackground();
89     }
90 
91     /**
92      * Updates the text background to match the shape of this background (when applicable).
93      */
tryUpdateTextBackground()94     private void tryUpdateTextBackground() {
95         if (!(getBackground() instanceof GradientDrawable) || mBubbleText == null) {
96             return;
97         }
98         GradientDrawable background = (GradientDrawable) getBackground();
99 
100         int color = Themes.getAttrColor(getContext(), android.R.attr.colorControlHighlight);
101         GradientDrawable backgroundMask = new GradientDrawable();
102         backgroundMask.setColor(color);
103         backgroundMask.setShape(GradientDrawable.RECTANGLE);
104         if (background.getCornerRadii() != null) {
105             backgroundMask.setCornerRadii(background.getCornerRadii());
106         } else {
107             backgroundMask.setCornerRadius(background.getCornerRadius());
108         }
109 
110         RippleDrawable drawable = new RippleDrawable(ColorStateList.valueOf(color),
111                 mTransparentDrawable, backgroundMask);
112         mBubbleText.setBackground(drawable);
113     }
114 
115     @Override
getBubbleText()116     public BubbleTextView getBubbleText() {
117         return mBubbleText;
118     }
119 
setWillDrawIcon(boolean willDraw)120     public void setWillDrawIcon(boolean willDraw) {
121         mIconView.setVisibility(willDraw ? View.VISIBLE : View.INVISIBLE);
122     }
123 
willDrawIcon()124     public boolean willDrawIcon() {
125         return mIconView.getVisibility() == View.VISIBLE;
126     }
127 
128     /**
129      * Returns the position of the center of the icon relative to the container.
130      */
getIconCenter()131     public Point getIconCenter() {
132         sTempPoint.y = sTempPoint.x = getMeasuredHeight() / 2;
133         if (Utilities.isRtl(getResources())) {
134             sTempPoint.x = getMeasuredWidth() - sTempPoint.x;
135         }
136         return sTempPoint;
137     }
138 
139     /** package private **/
applyShortcutInfo(WorkspaceItemInfo info, ShortcutInfo detail, PopupContainerWithArrow container)140     public void applyShortcutInfo(WorkspaceItemInfo info, ShortcutInfo detail,
141             PopupContainerWithArrow container) {
142         mInfo = info;
143         mDetail = detail;
144         mBubbleText.applyFromWorkspaceItem(info);
145         mIconView.setBackground(mBubbleText.getIcon());
146 
147         // Use the long label as long as it exists and fits.
148         CharSequence longLabel = mDetail.getLongLabel();
149         int availableWidth = mBubbleText.getWidth() - mBubbleText.getTotalPaddingLeft()
150                 - mBubbleText.getTotalPaddingRight();
151         boolean usingLongLabel = !TextUtils.isEmpty(longLabel)
152                 && mBubbleText.getPaint().measureText(longLabel.toString()) <= availableWidth;
153         mBubbleText.setText(usingLongLabel ? longLabel : mDetail.getShortLabel());
154 
155         // TODO: Add the click handler to this view directly and not the child view.
156         mBubbleText.setOnClickListener(container.getItemClickListener());
157         mBubbleText.setOnLongClickListener(container.getItemDragHandler());
158         mBubbleText.setOnTouchListener(container.getItemDragHandler());
159     }
160 
161     /**
162      * Returns the shortcut info that is suitable to be added on the homescreen
163      */
getFinalInfo()164     public WorkspaceItemInfo getFinalInfo() {
165         final WorkspaceItemInfo badged = new WorkspaceItemInfo(mInfo);
166         // Queue an update task on the worker thread. This ensures that the badged
167         // shortcut eventually gets its icon updated.
168         Launcher.getLauncher(getContext()).getModel()
169                 .updateAndBindWorkspaceItem(badged, mDetail);
170         return badged;
171     }
172 
getIconView()173     public View getIconView() {
174         return mIconView;
175     }
176 
getDetail()177     public ShortcutInfo getDetail() {
178         return mDetail;
179     }
180 }
181