PagedViewWidget.java revision 099459377a737d885bbd8ac4d52e6884a103b1c7
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 17package com.android.launcher2; 18 19import android.animation.ObjectAnimator; 20import android.appwidget.AppWidgetProviderInfo; 21import android.content.Context; 22import android.content.pm.PackageManager; 23import android.content.pm.ResolveInfo; 24import android.content.res.Resources; 25import android.content.res.TypedArray; 26import android.graphics.Bitmap; 27import android.graphics.Canvas; 28import android.graphics.Color; 29import android.graphics.Paint; 30import android.graphics.PorterDuff; 31import android.graphics.PorterDuff.Mode; 32import android.graphics.PorterDuffXfermode; 33import android.graphics.Rect; 34import android.graphics.RectF; 35import android.os.Handler; 36import android.os.HandlerThread; 37import android.os.Message; 38import android.util.AttributeSet; 39import android.view.KeyEvent; 40import android.view.MotionEvent; 41import android.view.View; 42import android.widget.Checkable; 43import android.widget.ImageView; 44import android.widget.LinearLayout; 45import android.widget.TextView; 46 47import com.android.launcher.R; 48 49/** 50 * The linear layout used strictly for the widget/wallpaper tab of the customization tray 51 */ 52public class PagedViewWidget extends LinearLayout implements Checkable { 53 static final String TAG = "PagedViewWidgetLayout"; 54 55 private final Paint mPaint = new Paint(); 56 private Bitmap mHolographicOutline; 57 private HolographicOutlineHelper mHolographicOutlineHelper; 58 private ImageView mPreviewImageView; 59 private final RectF mTmpScaleRect = new RectF(); 60 61 private String mDimensionsFormatString; 62 63 private int mAlpha = 255; 64 private int mHolographicAlpha; 65 66 private boolean mIsChecked; 67 private ObjectAnimator mCheckedAlphaAnimator; 68 private float mCheckedAlpha = 1.0f; 69 private int mCheckedFadeInDuration; 70 private int mCheckedFadeOutDuration; 71 72 public PagedViewWidget(Context context) { 73 this(context, null); 74 } 75 76 public PagedViewWidget(Context context, AttributeSet attrs) { 77 this(context, attrs, 0); 78 } 79 80 public PagedViewWidget(Context context, AttributeSet attrs, int defStyle) { 81 super(context, attrs, defStyle); 82 83 // Set up fade in/out constants 84 final Resources r = context.getResources(); 85 final int alpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha); 86 if (alpha > 0) { 87 mCheckedAlpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha) / 256.0f; 88 mCheckedFadeInDuration = 89 r.getInteger(R.integer.config_dragAppsCustomizeIconFadeInDuration); 90 mCheckedFadeOutDuration = 91 r.getInteger(R.integer.config_dragAppsCustomizeIconFadeOutDuration); 92 } 93 mDimensionsFormatString = r.getString(R.string.widget_dims_format); 94 95 setWillNotDraw(false); 96 setClipToPadding(false); 97 } 98 99 @Override 100 protected void onDetachedFromWindow() { 101 super.onDetachedFromWindow(); 102 103 final ImageView image = (ImageView) findViewById(R.id.widget_preview); 104 if (image != null) { 105 FastBitmapDrawable preview = (FastBitmapDrawable) image.getDrawable(); 106 if (preview != null && preview.getBitmap() != null) { 107 preview.getBitmap().recycle(); 108 } 109 image.setImageDrawable(null); 110 } 111 } 112 113 public void applyFromAppWidgetProviderInfo(AppWidgetProviderInfo info, 114 FastBitmapDrawable preview, int maxWidth, int[] cellSpan, 115 HolographicOutlineHelper holoOutlineHelper) { 116 mHolographicOutlineHelper = holoOutlineHelper; 117 final ImageView image = (ImageView) findViewById(R.id.widget_preview); 118 if (maxWidth > -1) { 119 image.setMaxWidth(maxWidth); 120 } 121 image.setImageDrawable(preview); 122 image.setContentDescription(info.label); 123 mPreviewImageView = image; 124 final TextView name = (TextView) findViewById(R.id.widget_name); 125 name.setText(info.label); 126 final TextView dims = (TextView) findViewById(R.id.widget_dims); 127 if (dims != null) { 128 dims.setText(String.format(mDimensionsFormatString, cellSpan[0], cellSpan[1])); 129 } 130 } 131 132 public void applyFromResolveInfo(PackageManager pm, ResolveInfo info, 133 FastBitmapDrawable preview, HolographicOutlineHelper holoOutlineHelper) { 134 mHolographicOutlineHelper = holoOutlineHelper; 135 CharSequence label = info.loadLabel(pm); 136 final ImageView image = (ImageView) findViewById(R.id.widget_preview); 137 image.setImageDrawable(preview); 138 image.setContentDescription(label); 139 mPreviewImageView = image; 140 final TextView name = (TextView) findViewById(R.id.widget_name); 141 name.setText(label); 142 final TextView dims = (TextView) findViewById(R.id.widget_dims); 143 if (dims != null) { 144 dims.setText(String.format(mDimensionsFormatString, 1, 1)); 145 } 146 } 147 148 public void setHolographicOutline(Bitmap holoOutline) { 149 mHolographicOutline = holoOutline; 150 invalidate(); 151 } 152 153 @Override 154 public boolean onTouchEvent(MotionEvent event) { 155 // We eat up the touch events here, since the PagedView (which uses the same swiping 156 // touch code as Workspace previously) uses onInterceptTouchEvent() to determine when 157 // the user is scrolling between pages. This means that if the pages themselves don't 158 // handle touch events, it gets forwarded up to PagedView itself, and it's own 159 // onTouchEvent() handling will prevent further intercept touch events from being called 160 // (it's the same view in that case). This is not ideal, but to prevent more changes, 161 // we just always mark the touch event as handled. 162 return super.onTouchEvent(event) || true; 163 } 164 165 @Override 166 public boolean onKeyDown(int keyCode, KeyEvent event) { 167 return FocusHelper.handlePagedViewGridLayoutWidgetKeyEvent(this, keyCode, event) 168 || super.onKeyDown(keyCode, event); 169 } 170 171 @Override 172 public boolean onKeyUp(int keyCode, KeyEvent event) { 173 return FocusHelper.handlePagedViewGridLayoutWidgetKeyEvent(this, keyCode, event) 174 || super.onKeyUp(keyCode, event); 175 } 176 177 @Override 178 protected void onDraw(Canvas canvas) { 179 if (mAlpha > 0) { 180 super.onDraw(canvas); 181 } 182 183 // draw any blended overlays 184 if (mHolographicOutline != null && mHolographicAlpha > 0) { 185 // Calculate how much to scale the holographic preview 186 mTmpScaleRect.set(0,0,1,1); 187 mPreviewImageView.getImageMatrix().mapRect(mTmpScaleRect); 188 189 mPaint.setAlpha(mHolographicAlpha); 190 canvas.save(); 191 canvas.scale(mTmpScaleRect.right, mTmpScaleRect.bottom); 192 canvas.drawBitmap(mHolographicOutline, mPreviewImageView.getLeft(), 193 mPreviewImageView.getTop(), mPaint); 194 canvas.restore(); 195 } 196 } 197 198 @Override 199 protected boolean onSetAlpha(int alpha) { 200 return true; 201 } 202 203 private void setChildrenAlpha(float alpha) { 204 final int childCount = getChildCount(); 205 for (int i = 0; i < childCount; i++) { 206 getChildAt(i).setAlpha(alpha); 207 } 208 } 209 @Override 210 public void setAlpha(float alpha) { 211 final float viewAlpha = mHolographicOutlineHelper.viewAlphaInterpolator(alpha); 212 final float holographicAlpha = mHolographicOutlineHelper.highlightAlphaInterpolator(alpha); 213 int newViewAlpha = (int) (viewAlpha * 255); 214 int newHolographicAlpha = (int) (holographicAlpha * 255); 215 if ((mAlpha != newViewAlpha) || (mHolographicAlpha != newHolographicAlpha)) { 216 mAlpha = newViewAlpha; 217 mHolographicAlpha = newHolographicAlpha; 218 setChildrenAlpha(viewAlpha); 219 super.setAlpha(viewAlpha); 220 } 221 } 222 223 void setChecked(boolean checked, boolean animate) { 224 if (mIsChecked != checked) { 225 mIsChecked = checked; 226 227 float alpha; 228 int duration; 229 if (mIsChecked) { 230 alpha = mCheckedAlpha; 231 duration = mCheckedFadeInDuration; 232 } else { 233 alpha = 1.0f; 234 duration = mCheckedFadeOutDuration; 235 } 236 237 // Initialize the animator 238 if (mCheckedAlphaAnimator != null) { 239 mCheckedAlphaAnimator.cancel(); 240 } 241 if (animate) { 242 mCheckedAlphaAnimator = ObjectAnimator.ofFloat(this, "alpha", getAlpha(), alpha); 243 mCheckedAlphaAnimator.setDuration(duration); 244 mCheckedAlphaAnimator.start(); 245 } else { 246 setAlpha(alpha); 247 } 248 249 invalidate(); 250 } 251 } 252 253 @Override 254 public void setChecked(boolean checked) { 255 setChecked(checked, true); 256 } 257 258 @Override 259 public boolean isChecked() { 260 return mIsChecked; 261 } 262 263 @Override 264 public void toggle() { 265 setChecked(!mIsChecked); 266 } 267} 268