/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.launcher3.widget; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.View.OnLayoutChangeListener; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.FastBitmapDrawable; import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.R; import com.android.launcher3.WidgetPreviewLoader; import com.android.launcher3.WidgetPreviewLoader.PreviewLoadRequest; import com.android.launcher3.compat.AppWidgetManagerCompat; /** * Represents the individual cell of the widget inside the widget tray. */ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { private static final String TAG = "WidgetCell"; private static final boolean DEBUG = false; private static final int FADE_IN_DURATION_MS = 90; /** Widget cell width is calculated by multiplying this factor to grid cell width. */ private static final float WIDTH_SCALE = 2.6f; /** Widget preview width is calculated by multiplying this factor to the widget cell width. */ private static final float PREVIEW_SCALE = 0.8f; private int mPresetPreviewSize; int cellSize; private ImageView mWidgetImage; private TextView mWidgetName; private TextView mWidgetDims; private final Rect mOrigImgPadding = new Rect(); private String mDimensionsFormatString; private boolean mIsAppWidget; private Object mInfo; private WidgetPreviewLoader mWidgetPreviewLoader; private PreviewLoadRequest mActiveRequest; public WidgetCell(Context context) { this(context, null); } public WidgetCell(Context context, AttributeSet attrs) { this(context, attrs, 0); } public WidgetCell(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); final Resources r = context.getResources(); mDimensionsFormatString = r.getString(R.string.widget_dims_format); setContainerWidth(); setWillNotDraw(false); setClipToPadding(false); setAccessibilityDelegate(LauncherAppState.getInstance().getAccessibilityDelegate()); } private void setContainerWidth() { DeviceProfile profile = LauncherAppState.getInstance().getDynamicGrid().getDeviceProfile(); cellSize = (int) (profile.cellWidthPx * WIDTH_SCALE); mPresetPreviewSize = (int) (profile.cellWidthPx * WIDTH_SCALE * PREVIEW_SCALE); } @Override protected void onFinishInflate() { super.onFinishInflate(); mWidgetImage = (ImageView) findViewById(R.id.widget_preview); mOrigImgPadding.left = mWidgetImage.getPaddingLeft(); mOrigImgPadding.top = mWidgetImage.getPaddingTop(); mOrigImgPadding.right = mWidgetImage.getPaddingRight(); mOrigImgPadding.bottom = mWidgetImage.getPaddingBottom(); mWidgetName = ((TextView) findViewById(R.id.widget_name)); mWidgetDims = ((TextView) findViewById(R.id.widget_dims)); } /** * Called to clear the view and free attached resources. (e.g., {@link Bitmap} */ public void clear() { if (DEBUG) { Log.d(TAG, "reset called on:" + mWidgetName.getText()); } mWidgetImage.animate().cancel(); mWidgetImage.setImageDrawable(null); mWidgetName.setText(null); mWidgetDims.setText(null); if (mActiveRequest != null) { mActiveRequest.cleanup(); mActiveRequest = null; } } /** * Apply the widget provider info to the view. */ public void applyFromAppWidgetProviderInfo(LauncherAppWidgetProviderInfo info, int maxWidth, WidgetPreviewLoader loader) { LauncherAppState app = LauncherAppState.getInstance(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); mIsAppWidget = true; mInfo = info; if (maxWidth > -1) { mWidgetImage.setMaxWidth(maxWidth); } // TODO(hyunyoungs): setup a cache for these labels. mWidgetName.setText(AppWidgetManagerCompat.getInstance(getContext()).loadLabel(info)); int hSpan = Math.min(info.spanX, grid.numColumns); int vSpan = Math.min(info.spanY, grid.numRows); mWidgetDims.setText(String.format(mDimensionsFormatString, hSpan, vSpan)); mWidgetPreviewLoader = loader; } /** * Apply the resolve info to the view. */ public void applyFromResolveInfo( PackageManager pm, ResolveInfo info, WidgetPreviewLoader loader) { mIsAppWidget = false; mInfo = info; CharSequence label = info.loadLabel(pm); mWidgetName.setText(label); mWidgetDims.setText(String.format(mDimensionsFormatString, 1, 1)); mWidgetPreviewLoader = loader; } public int[] getPreviewSize() { int[] maxSize = new int[2]; maxSize[0] = mPresetPreviewSize; maxSize[1] = mPresetPreviewSize; return maxSize; } public void applyPreview(Bitmap bitmap) { FastBitmapDrawable preview = new FastBitmapDrawable(bitmap); if (preview != null) { mWidgetImage.setImageDrawable(preview); if (mIsAppWidget) { // center horizontally int[] imageSize = getPreviewSize(); int centerAmount = (imageSize[0] - preview.getIntrinsicWidth()) / 2; mWidgetImage.setPadding(mOrigImgPadding.left + centerAmount, mOrigImgPadding.top, mOrigImgPadding.right, mOrigImgPadding.bottom); } mWidgetImage.setAlpha(0f); mWidgetImage.animate().alpha(1.0f).setDuration(FADE_IN_DURATION_MS); } } public void ensurePreview() { if (mActiveRequest != null) { return; } int[] size = getPreviewSize(); if (DEBUG) { Log.d(TAG, String.format("[tag=%s] ensurePreview (%d, %d):", getTagToString(), size[0], size[1])); } mActiveRequest = mWidgetPreviewLoader.getPreview(mInfo, size[0], size[1], this); } @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { removeOnLayoutChangeListener(this); ensurePreview(); } public int getActualItemWidth() { ItemInfo info = (ItemInfo) getTag(); int[] size = getPreviewSize(); int cellWidth = LauncherAppState.getInstance() .getDynamicGrid().getDeviceProfile().cellWidthPx; return Math.min(size[0], info.spanX * cellWidth); } /** * Helper method to get the string info of the tag. */ private String getTagToString() { if (getTag() instanceof PendingAddWidgetInfo || getTag() instanceof PendingAddShortcutInfo) { return getTag().toString(); } return ""; } }