1 /* 2 * Copyright (C) 2010 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.launcher2; 18 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.util.AttributeSet; 25 import android.view.MotionEvent; 26 import android.view.View; 27 import android.widget.ImageView; 28 import android.widget.LinearLayout; 29 import android.widget.TextView; 30 31 import com.android.launcher.R; 32 33 /** 34 * The linear layout used strictly for the widget/wallpaper tab of the customization tray 35 */ 36 public class PagedViewWidget extends LinearLayout { 37 static final String TAG = "PagedViewWidgetLayout"; 38 39 private static boolean sDeletePreviewsWhenDetachedFromWindow = true; 40 41 private String mDimensionsFormatString; 42 CheckForShortPress mPendingCheckForShortPress = null; 43 ShortPressListener mShortPressListener = null; 44 boolean mShortPressTriggered = false; 45 static PagedViewWidget sShortpressTarget = null; 46 boolean mIsAppWidget; 47 PagedViewWidget(Context context)48 public PagedViewWidget(Context context) { 49 this(context, null); 50 } 51 PagedViewWidget(Context context, AttributeSet attrs)52 public PagedViewWidget(Context context, AttributeSet attrs) { 53 this(context, attrs, 0); 54 } 55 PagedViewWidget(Context context, AttributeSet attrs, int defStyle)56 public PagedViewWidget(Context context, AttributeSet attrs, int defStyle) { 57 super(context, attrs, defStyle); 58 59 final Resources r = context.getResources(); 60 mDimensionsFormatString = r.getString(R.string.widget_dims_format); 61 62 setWillNotDraw(false); 63 setClipToPadding(false); 64 } 65 setDeletePreviewsWhenDetachedFromWindow(boolean value)66 public static void setDeletePreviewsWhenDetachedFromWindow(boolean value) { 67 sDeletePreviewsWhenDetachedFromWindow = value; 68 } 69 70 @Override onDetachedFromWindow()71 protected void onDetachedFromWindow() { 72 super.onDetachedFromWindow(); 73 74 if (sDeletePreviewsWhenDetachedFromWindow) { 75 final ImageView image = (ImageView) findViewById(R.id.widget_preview); 76 if (image != null) { 77 FastBitmapDrawable preview = (FastBitmapDrawable) image.getDrawable(); 78 if (preview != null && preview.getBitmap() != null) { 79 preview.getBitmap().recycle(); 80 } 81 image.setImageDrawable(null); 82 } 83 } 84 } 85 applyFromAppWidgetProviderInfo(AppWidgetProviderInfo info, int maxWidth, int[] cellSpan)86 public void applyFromAppWidgetProviderInfo(AppWidgetProviderInfo info, 87 int maxWidth, int[] cellSpan) { 88 mIsAppWidget = true; 89 final ImageView image = (ImageView) findViewById(R.id.widget_preview); 90 if (maxWidth > -1) { 91 image.setMaxWidth(maxWidth); 92 } 93 image.setContentDescription(info.label); 94 final TextView name = (TextView) findViewById(R.id.widget_name); 95 name.setText(info.label); 96 final TextView dims = (TextView) findViewById(R.id.widget_dims); 97 if (dims != null) { 98 int hSpan = Math.min(cellSpan[0], LauncherModel.getCellCountX()); 99 int vSpan = Math.min(cellSpan[1], LauncherModel.getCellCountY()); 100 dims.setText(String.format(mDimensionsFormatString, hSpan, vSpan)); 101 } 102 } 103 applyFromResolveInfo(PackageManager pm, ResolveInfo info)104 public void applyFromResolveInfo(PackageManager pm, ResolveInfo info) { 105 mIsAppWidget = false; 106 CharSequence label = info.loadLabel(pm); 107 final ImageView image = (ImageView) findViewById(R.id.widget_preview); 108 image.setContentDescription(label); 109 final TextView name = (TextView) findViewById(R.id.widget_name); 110 name.setText(label); 111 final TextView dims = (TextView) findViewById(R.id.widget_dims); 112 if (dims != null) { 113 dims.setText(String.format(mDimensionsFormatString, 1, 1)); 114 } 115 } 116 getPreviewSize()117 public int[] getPreviewSize() { 118 final ImageView i = (ImageView) findViewById(R.id.widget_preview); 119 int[] maxSize = new int[2]; 120 maxSize[0] = i.getWidth() - i.getPaddingLeft() - i.getPaddingRight(); 121 maxSize[1] = i.getHeight() - i.getPaddingTop(); 122 return maxSize; 123 } 124 applyPreview(FastBitmapDrawable preview, int index)125 void applyPreview(FastBitmapDrawable preview, int index) { 126 final PagedViewWidgetImageView image = 127 (PagedViewWidgetImageView) findViewById(R.id.widget_preview); 128 if (preview != null) { 129 image.mAllowRequestLayout = false; 130 image.setImageDrawable(preview); 131 if (mIsAppWidget) { 132 // center horizontally 133 int[] imageSize = getPreviewSize(); 134 int centerAmount = (imageSize[0] - preview.getIntrinsicWidth()) / 2; 135 image.setPadding(image.getPaddingLeft() + centerAmount, 136 image.getPaddingTop(), 137 image.getPaddingRight(), 138 image.getPaddingBottom()); 139 } 140 image.setAlpha(1f); 141 image.mAllowRequestLayout = true; 142 } 143 } 144 setShortPressListener(ShortPressListener listener)145 void setShortPressListener(ShortPressListener listener) { 146 mShortPressListener = listener; 147 } 148 149 interface ShortPressListener { onShortPress(View v)150 void onShortPress(View v); cleanUpShortPress(View v)151 void cleanUpShortPress(View v); 152 } 153 154 class CheckForShortPress implements Runnable { run()155 public void run() { 156 if (sShortpressTarget != null) return; 157 if (mShortPressListener != null) { 158 mShortPressListener.onShortPress(PagedViewWidget.this); 159 sShortpressTarget = PagedViewWidget.this; 160 } 161 mShortPressTriggered = true; 162 } 163 } 164 checkForShortPress()165 private void checkForShortPress() { 166 if (sShortpressTarget != null) return; 167 if (mPendingCheckForShortPress == null) { 168 mPendingCheckForShortPress = new CheckForShortPress(); 169 } 170 postDelayed(mPendingCheckForShortPress, 120); 171 } 172 173 /** 174 * Remove the longpress detection timer. 175 */ removeShortPressCallback()176 private void removeShortPressCallback() { 177 if (mPendingCheckForShortPress != null) { 178 removeCallbacks(mPendingCheckForShortPress); 179 } 180 } 181 cleanUpShortPress()182 private void cleanUpShortPress() { 183 removeShortPressCallback(); 184 if (mShortPressTriggered) { 185 if (mShortPressListener != null) { 186 mShortPressListener.cleanUpShortPress(PagedViewWidget.this); 187 } 188 mShortPressTriggered = false; 189 } 190 } 191 resetShortPressTarget()192 static void resetShortPressTarget() { 193 sShortpressTarget = null; 194 } 195 196 @Override onTouchEvent(MotionEvent event)197 public boolean onTouchEvent(MotionEvent event) { 198 super.onTouchEvent(event); 199 200 switch (event.getAction()) { 201 case MotionEvent.ACTION_UP: 202 cleanUpShortPress(); 203 break; 204 case MotionEvent.ACTION_DOWN: 205 checkForShortPress(); 206 break; 207 case MotionEvent.ACTION_CANCEL: 208 cleanUpShortPress(); 209 break; 210 case MotionEvent.ACTION_MOVE: 211 break; 212 } 213 214 // We eat up the touch events here, since the PagedView (which uses the same swiping 215 // touch code as Workspace previously) uses onInterceptTouchEvent() to determine when 216 // the user is scrolling between pages. This means that if the pages themselves don't 217 // handle touch events, it gets forwarded up to PagedView itself, and it's own 218 // onTouchEvent() handling will prevent further intercept touch events from being called 219 // (it's the same view in that case). This is not ideal, but to prevent more changes, 220 // we just always mark the touch event as handled. 221 return true; 222 } 223 } 224