2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.launcher3;
19 import android.appwidget.AppWidgetProviderInfo;
20 import android.content.Context;
21 import android.content.pm.PackageManager;
22 import android.content.pm.ResolveInfo;
23 import android.content.res.Resources;
24 import android.graphics.Rect;
25 import android.util.AttributeSet;
26 import android.util.TypedValue;
27 import android.view.MotionEvent;
28 import android.view.View;
29 import android.widget.ImageView;
30 import android.widget.LinearLayout;
31 import android.widget.TextView;
33 import com.android.launcher3.compat.AppWidgetManagerCompat;
36 * The linear layout used strictly for the widget/wallpaper tab of the customization tray
38 public class PagedViewWidget extends LinearLayout {
39 static final String TAG = "PagedViewWidgetLayout";
41 private static boolean sDeletePreviewsWhenDetachedFromWindow = true;
42 private static boolean sRecyclePreviewsWhenDetachedFromWindow = true;
44 private String mDimensionsFormatString;
45 CheckForShortPress mPendingCheckForShortPress = null;
46 ShortPressListener mShortPressListener = null;
47 boolean mShortPressTriggered = false;
48 static PagedViewWidget sShortpressTarget = null;
50 private final Rect mOriginalImagePadding = new Rect();
52 private WidgetPreviewLoader mWidgetPreviewLoader;
54 public PagedViewWidget(Context context) {
58 public PagedViewWidget(Context context, AttributeSet attrs) {
59 this(context, attrs, 0);
62 public PagedViewWidget(Context context, AttributeSet attrs, int defStyle) {
63 super(context, attrs, defStyle);
65 final Resources r = context.getResources();
66 mDimensionsFormatString = r.getString(R.string.widget_dims_format);
68 setWillNotDraw(false);
69 setClipToPadding(false);
73 protected void onFinishInflate() {
74 super.onFinishInflate();
76 final ImageView image = (ImageView) findViewById(R.id.widget_preview);
77 mOriginalImagePadding.left = image.getPaddingLeft();
78 mOriginalImagePadding.top = image.getPaddingTop();
79 mOriginalImagePadding.right = image.getPaddingRight();
80 mOriginalImagePadding.bottom = image.getPaddingBottom();
82 // Ensure we are using the right text size
83 LauncherAppState app = LauncherAppState.getInstance();
84 DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
85 TextView name = (TextView) findViewById(R.id.widget_name);
87 name.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
89 TextView dims = (TextView) findViewById(R.id.widget_dims);
91 dims.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
95 public static void setDeletePreviewsWhenDetachedFromWindow(boolean value) {
96 sDeletePreviewsWhenDetachedFromWindow = value;
99 public static void setRecyclePreviewsWhenDetachedFromWindow(boolean value) {
100 sRecyclePreviewsWhenDetachedFromWindow = value;
104 protected void onDetachedFromWindow() {
105 super.onDetachedFromWindow();
107 if (sDeletePreviewsWhenDetachedFromWindow) {
108 final ImageView image = (ImageView) findViewById(R.id.widget_preview);
110 FastBitmapDrawable preview = (FastBitmapDrawable) image.getDrawable();
111 if (sRecyclePreviewsWhenDetachedFromWindow &&
112 mInfo != null && preview != null && preview.getBitmap() != null) {
113 mWidgetPreviewLoader.recycleBitmap(mInfo, preview.getBitmap());
115 image.setImageDrawable(null);
120 public void applyFromAppWidgetProviderInfo(AppWidgetProviderInfo info,
121 int maxWidth, int[] cellSpan, WidgetPreviewLoader loader) {
122 LauncherAppState app = LauncherAppState.getInstance();
123 DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
127 final ImageView image = (ImageView) findViewById(R.id.widget_preview);
129 image.setMaxWidth(maxWidth);
131 final TextView name = (TextView) findViewById(R.id.widget_name);
132 name.setText(AppWidgetManagerCompat.getInstance(getContext()).loadLabel(info));
133 final TextView dims = (TextView) findViewById(R.id.widget_dims);
135 int hSpan = Math.min(cellSpan[0], (int) grid.numColumns);
136 int vSpan = Math.min(cellSpan[1], (int) grid.numRows);
137 dims.setText(String.format(mDimensionsFormatString, hSpan, vSpan));
139 mWidgetPreviewLoader = loader;
142 public void applyFromResolveInfo(
143 PackageManager pm, ResolveInfo info, WidgetPreviewLoader loader) {
144 mIsAppWidget = false;
146 CharSequence label = info.loadLabel(pm);
147 final TextView name = (TextView) findViewById(R.id.widget_name);
149 final TextView dims = (TextView) findViewById(R.id.widget_dims);
151 dims.setText(String.format(mDimensionsFormatString, 1, 1));
153 mWidgetPreviewLoader = loader;
156 public int[] getPreviewSize() {
157 final ImageView i = (ImageView) findViewById(R.id.widget_preview);
158 int[] maxSize = new int[2];
159 maxSize[0] = i.getWidth() - mOriginalImagePadding.left - mOriginalImagePadding.right;
160 maxSize[1] = i.getHeight() - mOriginalImagePadding.top;
164 void applyPreview(FastBitmapDrawable preview, int index) {
165 final PagedViewWidgetImageView image =
166 (PagedViewWidgetImageView) findViewById(R.id.widget_preview);
167 if (preview != null) {
168 image.mAllowRequestLayout = false;
169 image.setImageDrawable(preview);
171 // center horizontally
172 int[] imageSize = getPreviewSize();
173 int centerAmount = (imageSize[0] - preview.getIntrinsicWidth()) / 2;
174 image.setPadding(mOriginalImagePadding.left + centerAmount,
175 mOriginalImagePadding.top,
176 mOriginalImagePadding.right,
177 mOriginalImagePadding.bottom);
180 image.mAllowRequestLayout = true;
184 void setShortPressListener(ShortPressListener listener) {
185 mShortPressListener = listener;
188 interface ShortPressListener {
189 void onShortPress(View v);
190 void cleanUpShortPress(View v);
193 class CheckForShortPress implements Runnable {
195 if (sShortpressTarget != null) return;
196 if (mShortPressListener != null) {
197 mShortPressListener.onShortPress(PagedViewWidget.this);
198 sShortpressTarget = PagedViewWidget.this;
200 mShortPressTriggered = true;
204 private void checkForShortPress() {
205 if (sShortpressTarget != null) return;
206 if (mPendingCheckForShortPress == null) {
207 mPendingCheckForShortPress = new CheckForShortPress();
209 postDelayed(mPendingCheckForShortPress, 120);
213 * Remove the longpress detection timer.
215 private void removeShortPressCallback() {
216 if (mPendingCheckForShortPress != null) {
217 removeCallbacks(mPendingCheckForShortPress);
221 private void cleanUpShortPress() {
222 removeShortPressCallback();
223 if (mShortPressTriggered) {
224 if (mShortPressListener != null) {
225 mShortPressListener.cleanUpShortPress(PagedViewWidget.this);
227 mShortPressTriggered = false;
231 static void resetShortPressTarget() {
232 sShortpressTarget = null;
236 public boolean onTouchEvent(MotionEvent event) {
237 super.onTouchEvent(event);
239 switch (event.getAction()) {
240 case MotionEvent.ACTION_UP:
243 case MotionEvent.ACTION_DOWN:
244 checkForShortPress();
246 case MotionEvent.ACTION_CANCEL:
249 case MotionEvent.ACTION_MOVE:
253 // We eat up the touch events here, since the PagedView (which uses the same swiping
254 // touch code as Workspace previously) uses onInterceptTouchEvent() to determine when
255 // the user is scrolling between pages. This means that if the pages themselves don't
256 // handle touch events, it gets forwarded up to PagedView itself, and it's own
257 // onTouchEvent() handling will prevent further intercept touch events from being called
258 // (it's the same view in that case). This is not ideal, but to prevent more changes,
259 // we just always mark the touch event as handled.