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