WidgetCell.java revision ed66b2bac7447febe2e405b4ce725cae4f6b5988
129d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung/* 229d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * Copyright (C) 2010 The Android Open Source Project 329d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * 429d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * Licensed under the Apache License, Version 2.0 (the "License"); 529d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * you may not use this file except in compliance with the License. 629d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * You may obtain a copy of the License at 729d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * 829d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * http://www.apache.org/licenses/LICENSE-2.0 929d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * 1029d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * Unless required by applicable law or agreed to in writing, software 1129d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * distributed under the License is distributed on an "AS IS" BASIS, 1229d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1329d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * See the License for the specific language governing permissions and 1429d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * limitations under the License. 1529d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung */ 1629d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung 1729d6fea296ebecb607525c8245a54696ad7c5db7Winson Chungpackage com.android.launcher2; 1829d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung 1929d6fea296ebecb607525c8245a54696ad7c5db7Winson Chungimport android.appwidget.AppWidgetProviderInfo; 2029d6fea296ebecb607525c8245a54696ad7c5db7Winson Chungimport android.content.Context; 2129d6fea296ebecb607525c8245a54696ad7c5db7Winson Chungimport android.content.pm.PackageManager; 2229d6fea296ebecb607525c8245a54696ad7c5db7Winson Chungimport android.content.pm.ResolveInfo; 2359e1f9a07eef87b1d287956d21b8d9c5b27faf9cWinson Chungimport android.content.res.Resources; 2429d6fea296ebecb607525c8245a54696ad7c5db7Winson Chungimport android.util.AttributeSet; 2529d6fea296ebecb607525c8245a54696ad7c5db7Winson Chungimport android.view.MotionEvent; 26ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohenimport android.view.View; 2729d6fea296ebecb607525c8245a54696ad7c5db7Winson Chungimport android.widget.ImageView; 2829d6fea296ebecb607525c8245a54696ad7c5db7Winson Chungimport android.widget.LinearLayout; 2929d6fea296ebecb607525c8245a54696ad7c5db7Winson Chungimport android.widget.TextView; 3029d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung 3129d6fea296ebecb607525c8245a54696ad7c5db7Winson Chungimport com.android.launcher.R; 3229d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung 3329d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung/** 3429d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung * The linear layout used strictly for the widget/wallpaper tab of the customization tray 3529d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung */ 3682369a16126a1030c1c9203dc62b33c2598add89Michael Jurkapublic class PagedViewWidget extends LinearLayout { 3729d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung static final String TAG = "PagedViewWidgetLayout"; 3829d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung 39141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka private static boolean sDeletePreviewsWhenDetachedFromWindow = true; 40e4a647f8793ce7823394db43d6af57f9eab8a340Winson Chung 411908d07151e0d3f82899f368874e41ed1e49ba16Winson Chung private ImageView mPreviewImageView; 4229d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung 4363257c110a4ee54d5e8872c471cce254cf613c7aWinson Chung private String mDimensionsFormatString; 44ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen CheckForShortPress mPendingCheckForShortPress = null; 45ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen ShortPressListener mShortPressListener = null; 46ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen boolean mShortPressTriggered = false; 470499834db3f9dc6fb0f5f57b5876b8503bce5189Winson Chung 4829d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung public PagedViewWidget(Context context) { 4929d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung this(context, null); 5029d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung } 5129d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung 5229d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung public PagedViewWidget(Context context, AttributeSet attrs) { 5329d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung this(context, attrs, 0); 5429d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung } 5529d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung 5629d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung public PagedViewWidget(Context context, AttributeSet attrs, int defStyle) { 5729d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung super(context, attrs, defStyle); 5829d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung 5959e1f9a07eef87b1d287956d21b8d9c5b27faf9cWinson Chung final Resources r = context.getResources(); 6063257c110a4ee54d5e8872c471cce254cf613c7aWinson Chung mDimensionsFormatString = r.getString(R.string.widget_dims_format); 6159e1f9a07eef87b1d287956d21b8d9c5b27faf9cWinson Chung 6229d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung setWillNotDraw(false); 6329d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung setClipToPadding(false); 6429d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung } 6529d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung 66141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka public static void setDeletePreviewsWhenDetachedFromWindow(boolean value) { 67141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka sDeletePreviewsWhenDetachedFromWindow = value; 68141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka } 69141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka 70099459377a737d885bbd8ac4d52e6884a103b1c7Winson Chung @Override 71099459377a737d885bbd8ac4d52e6884a103b1c7Winson Chung protected void onDetachedFromWindow() { 72099459377a737d885bbd8ac4d52e6884a103b1c7Winson Chung super.onDetachedFromWindow(); 73099459377a737d885bbd8ac4d52e6884a103b1c7Winson Chung 74141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka if (sDeletePreviewsWhenDetachedFromWindow) { 75141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka final ImageView image = (ImageView) findViewById(R.id.widget_preview); 76141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka if (image != null) { 77141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka FastBitmapDrawable preview = (FastBitmapDrawable) image.getDrawable(); 78141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka if (preview != null && preview.getBitmap() != null) { 79141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka preview.getBitmap().recycle(); 80141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka } 81141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka image.setImageDrawable(null); 82141dbd0e02f9fd9f3a096722d8d812990b5931e1Michael Jurka } 83099459377a737d885bbd8ac4d52e6884a103b1c7Winson Chung } 84099459377a737d885bbd8ac4d52e6884a103b1c7Winson Chung } 85099459377a737d885bbd8ac4d52e6884a103b1c7Winson Chung 8629d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung public void applyFromAppWidgetProviderInfo(AppWidgetProviderInfo info, 8782369a16126a1030c1c9203dc62b33c2598add89Michael Jurka int maxWidth, int[] cellSpan) { 8829d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung final ImageView image = (ImageView) findViewById(R.id.widget_preview); 894b576be59e58072cc03b5a8d36afb6a322513575Winson Chung if (maxWidth > -1) { 904b576be59e58072cc03b5a8d36afb6a322513575Winson Chung image.setMaxWidth(maxWidth); 914b576be59e58072cc03b5a8d36afb6a322513575Winson Chung } 926a0f57dfafced837a2a282d8feec28d5418be3b9Winson Chung image.setContentDescription(info.label); 931908d07151e0d3f82899f368874e41ed1e49ba16Winson Chung mPreviewImageView = image; 9429d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung final TextView name = (TextView) findViewById(R.id.widget_name); 9529d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung name.setText(info.label); 9629d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung final TextView dims = (TextView) findViewById(R.id.widget_dims); 9735d4a257cff6ff69232f10c8dc405df8044eab1fWinson Chung if (dims != null) { 9835d4a257cff6ff69232f10c8dc405df8044eab1fWinson Chung dims.setText(String.format(mDimensionsFormatString, cellSpan[0], cellSpan[1])); 9935d4a257cff6ff69232f10c8dc405df8044eab1fWinson Chung } 10029d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung } 10129d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung 10282369a16126a1030c1c9203dc62b33c2598add89Michael Jurka public void applyFromResolveInfo(PackageManager pm, ResolveInfo info) { 1036a0f57dfafced837a2a282d8feec28d5418be3b9Winson Chung CharSequence label = info.loadLabel(pm); 1041ed747a4c07101793322c13a36dd547df4a3aa50Winson Chung final ImageView image = (ImageView) findViewById(R.id.widget_preview); 1056a0f57dfafced837a2a282d8feec28d5418be3b9Winson Chung image.setContentDescription(label); 1061ed747a4c07101793322c13a36dd547df4a3aa50Winson Chung mPreviewImageView = image; 1071ed747a4c07101793322c13a36dd547df4a3aa50Winson Chung final TextView name = (TextView) findViewById(R.id.widget_name); 1086a0f57dfafced837a2a282d8feec28d5418be3b9Winson Chung name.setText(label); 1091ed747a4c07101793322c13a36dd547df4a3aa50Winson Chung final TextView dims = (TextView) findViewById(R.id.widget_dims); 11046af2e89164b391b7a0049c6ce9048a2b7a7f644Winson Chung if (dims != null) { 11146af2e89164b391b7a0049c6ce9048a2b7a7f644Winson Chung dims.setText(String.format(mDimensionsFormatString, 1, 1)); 11246af2e89164b391b7a0049c6ce9048a2b7a7f644Winson Chung } 113b44b52439d155f570db7d6d0b80fdd3350e35685Winson Chung } 1140499834db3f9dc6fb0f5f57b5876b8503bce5189Winson Chung 115038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka public int[] getPreviewSize() { 116038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka final ImageView i = (ImageView) findViewById(R.id.widget_preview); 117038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka int[] maxSize = new int[2]; 118038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka maxSize[0] = i.getWidth() - i.getPaddingLeft() - i.getPaddingRight(); 119038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka maxSize[1] = i.getHeight() - i.getPaddingBottom() - i.getPaddingTop(); 120038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka return maxSize; 121038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka } 122038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka 123038f9d8bfb53288e7cf5812f62ec3d5b25fec965Michael Jurka void applyPreview(FastBitmapDrawable preview, int index) { 12481efbad05e0ce69b06d7323749ef2e200b84b98eMichael Jurka final PagedViewWidgetImageView image = 12581efbad05e0ce69b06d7323749ef2e200b84b98eMichael Jurka (PagedViewWidgetImageView) findViewById(R.id.widget_preview); 126e4a647f8793ce7823394db43d6af57f9eab8a340Winson Chung if (preview != null) { 12781efbad05e0ce69b06d7323749ef2e200b84b98eMichael Jurka image.mAllowRequestLayout = false; 128e4a647f8793ce7823394db43d6af57f9eab8a340Winson Chung image.setImageDrawable(preview); 12968e4c64a67f4a40afac4cab44def461783f096a4Winson Chung image.setAlpha(1f); 13081efbad05e0ce69b06d7323749ef2e200b84b98eMichael Jurka image.mAllowRequestLayout = true; 131e4a647f8793ce7823394db43d6af57f9eab8a340Winson Chung } 132e4a647f8793ce7823394db43d6af57f9eab8a340Winson Chung } 133e4a647f8793ce7823394db43d6af57f9eab8a340Winson Chung 134ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen void setShortPressListener(ShortPressListener listener) { 135ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen mShortPressListener = listener; 136ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 137ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 138ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen interface ShortPressListener { 139ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen void onShortPress(View v); 140ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen void cleanUpShortPress(View v); 141ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 142ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 143ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen class CheckForShortPress implements Runnable { 144ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen public void run() { 145ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen if (mShortPressListener != null) { 146ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen mShortPressListener.onShortPress(PagedViewWidget.this); 147ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 148ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen mShortPressTriggered = true; 149ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 150ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 151ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 152ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen private void checkForShortPress() { 153ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen if (mPendingCheckForShortPress == null) { 154ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen mPendingCheckForShortPress = new CheckForShortPress(); 155ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 156ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen postDelayed(mPendingCheckForShortPress, 120); 157ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 158ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 159ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen /** 160ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen * Remove the longpress detection timer. 161ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen */ 162ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen private void removeShortPressCallback() { 163ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen if (mPendingCheckForShortPress != null) { 164ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen removeCallbacks(mPendingCheckForShortPress); 165ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 166ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 167ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 168ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen private void cleanUpShortPress() { 169ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen removeShortPressCallback(); 170ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen if (mShortPressTriggered) { 171ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen if (mShortPressListener != null) { 172ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen mShortPressListener.cleanUpShortPress(PagedViewWidget.this); 173ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 174ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen mShortPressTriggered = false; 175ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 176ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 177ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 17829d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung @Override 17929d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung public boolean onTouchEvent(MotionEvent event) { 180ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen super.onTouchEvent(event); 181ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 182ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen switch (event.getAction()) { 183ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen case MotionEvent.ACTION_UP: 184ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen cleanUpShortPress(); 185ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen break; 186ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen case MotionEvent.ACTION_DOWN: 187ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen checkForShortPress(); 188ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen break; 189ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen case MotionEvent.ACTION_CANCEL: 190ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen cleanUpShortPress(); 191ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen break; 192ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen case MotionEvent.ACTION_MOVE: 193ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen break; 194ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen } 19529d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung // We eat up the touch events here, since the PagedView (which uses the same swiping 19629d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung // touch code as Workspace previously) uses onInterceptTouchEvent() to determine when 19729d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung // the user is scrolling between pages. This means that if the pages themselves don't 19829d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung // handle touch events, it gets forwarded up to PagedView itself, and it's own 19929d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung // onTouchEvent() handling will prevent further intercept touch events from being called 20029d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung // (it's the same view in that case). This is not ideal, but to prevent more changes, 20129d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung // we just always mark the touch event as handled. 202ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen return true; 20329d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung } 20429d6fea296ebecb607525c8245a54696ad7c5db7Winson Chung} 205