Modifying wallpapers customization page to look like widgets.

- Disallowing touch handling when there are no children

Change-Id: I925d6f1f862f8c7994a80c4eaacc80f8d59f6ab2
This commit is contained in:
Winson Chung 2010-11-09 17:19:49 -08:00
parent 0811495e24
commit 45e1d6ec0a
10 changed files with 193 additions and 194 deletions

View File

@ -19,6 +19,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
launcher:wallpaperCellSpanX="4"
launcher:widgetCellCountX="16"
launcher:cellCountX="8"
launcher:cellCountY="3"

View File

@ -19,6 +19,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
launcher:wallpaperCellSpanX="4"
launcher:widgetCellCountX="10"
launcher:cellCountX="5"
launcher:cellCountY="3"

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="365dp"
android:paddingLeft="12.5dp"
android:paddingRight="12.5dp"
android:paddingBottom="50dp"
android:gravity="top"
android:orientation="vertical">
<!-- The preview image for the wallpaper. -->
<ImageView
android:id="@+id/wallpaper_preview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:scaleType="fitStart" />
<!-- The divider image. -->
<ImageView
android:id="@+id/divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:src="@drawable/widget_divider" />
<!-- The name of the wallpaper -->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/wallpaper_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:textColor="#FFFFFFFF"
android:textSize="14sp"
android:shadowColor="#FF000000"
android:shadowDx="0.0"
android:shadowDy="1.0"
android:shadowRadius="1.0"
android:maxLines="2"
android:fadingEdge="horizontal" />
</LinearLayout>

View File

@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.android.launcher2.PagedViewWidgetIcon
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
@ -76,4 +76,4 @@
android:shadowDx="0.0"
android:shadowDy="1.0"
android:shadowRadius="1.0" />
</com.android.launcher2.PagedViewWidgetIcon>
</LinearLayout>

View File

@ -74,15 +74,6 @@
<attr name="checkedOutlineColor" format="color" />
</declare-styleable>
<!-- PagedViewWidgetIcon specific attributes. These attributes are used to
customize a PagedViewWidgetIcon view in XML files. -->
<declare-styleable name="PagedViewWidgetIcon">
<!-- The checked blur color of the holographic outline -->
<attr name="checkedBlurColor" />
<!-- The checked outline color of the holographic outline -->
<attr name="checkedOutlineColor" />
</declare-styleable>
<!-- PagedView specific attributes. These attributes are used to customize
a PagedView view in XML files. -->
<declare-styleable name="PagedView">
@ -105,6 +96,8 @@
<!-- CustomizePagedView specific attributes. These attributes are used to customize
a CustomizePagedView view in XML files. -->
<declare-styleable name="CustomizePagedView">
<!-- The cell span of an item in the wallpapers tab -->
<attr name="wallpaperCellSpanX" format="integer" />
<!-- The number of horizontal cells for the widget tab -->
<attr name="widgetCellCountX" format="integer" />
</declare-styleable>

View File

@ -77,12 +77,18 @@ public class CustomizePagedView extends PagedView
// The mapping between the pages and the widgets that will be laid out on them
private ArrayList<ArrayList<AppWidgetProviderInfo>> mWidgetPages;
// The max dimensions for the ImageView we use for displaying the widget
// The max dimensions for the ImageView we use for displaying a widget
private int mMaxWidgetWidth;
// The max number of widget cells to take a "page" of widget
// The max number of widget cells to take a "page" of widgets
private int mMaxWidgetsCellHSpan;
// The size of the items on the wallpaper tab
private int mWallpaperCellHSpan;
// The max dimensions for the ImageView we use for displaying a wallpaper
private int mMaxWallpaperWidth;
// The raw sources of data for each of the different tabs of the customization page
private List<AppWidgetProviderInfo> mWidgetList;
private List<ResolveInfo> mShortcutList;
@ -112,15 +118,15 @@ public class CustomizePagedView extends PagedView
super(context, attrs, defStyle);
TypedArray a;
a = context.obtainStyledAttributes(attrs, R.styleable.CustomizePagedView,
defStyle, 0);
a = context.obtainStyledAttributes(attrs, R.styleable.CustomizePagedView, defStyle, 0);
mWallpaperCellHSpan = a.getInt(R.styleable.CustomizePagedView_wallpaperCellSpanX, 4);
mMaxWidgetsCellHSpan = a.getInt(R.styleable.CustomizePagedView_widgetCellCountX, 8);
a.recycle();
a = context.obtainStyledAttributes(attrs, R.styleable.PagedView, defStyle, 0);
mCellCountX = a.getInt(R.styleable.PagedView_cellCountX, 7);
mCellCountY = a.getInt(R.styleable.PagedView_cellCountY, 4);
a.recycle();
mCustomizationType = CustomizationType.WidgetCustomization;
mWidgetPages = new ArrayList<ArrayList<AppWidgetProviderInfo>>();
mWorkspaceWidgetLayout = new PagedViewCellLayout(context);
@ -449,21 +455,58 @@ public class CustomizePagedView extends PagedView
/**
* Helper function to draw a drawable to the specified canvas with the specified bounds.
*/
private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int l, int t, int r, int b) {
private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h) {
if (bitmap != null) mCanvas.setBitmap(bitmap);
mCanvas.save();
d.setBounds(l, t, r, b);
d.setBounds(x, y, x+w, y+h);
d.draw(mCanvas);
mCanvas.restore();
}
/**
* This method will extract the preview image specified by the wallpaper source provider (if it
* exists) otherwise, it will try to generate a default image preview.
*/
private Drawable getWallpaperPreview(ResolveInfo info) {
// To be implemented later: resolving the up-to-date wallpaper thumbnail
final int minDim = mWorkspaceWidgetLayout.estimateCellWidth(1);
final int dim = mWorkspaceWidgetLayout.estimateCellWidth(mWallpaperCellHSpan);
Resources resources = mLauncher.getResources();
// Create a new bitmap to hold the widget preview
int width = (int) (dim * sScaleFactor);
int height = (int) (dim * sScaleFactor);
final Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
final Drawable background = resources.getDrawable(R.drawable.default_widget_preview);
renderDrawableToBitmap(background, bitmap, 0, 0, width, height);
// Draw the icon flush left
try {
final IconCache iconCache =
((LauncherApplication) mLauncher.getApplication()).getIconCache();
Drawable icon = new FastBitmapDrawable(Utilities.createIconBitmap(
iconCache.getFullResIcon(info, mPackageManager), mContext));
final int iconSize = minDim / 2;
final int offset = iconSize / 4;
renderDrawableToBitmap(icon, null, offset, offset, iconSize, iconSize);
} catch (Resources.NotFoundException e) {
// if we can't find the icon, then just don't draw it
}
Drawable drawable = new FastBitmapDrawable(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
return drawable;
}
/**
* This method will extract the preview image specified by the widget developer (if it exists),
* otherwise, it will try to generate a default image preview with the widget's package icon.
* @return the drawable will be used and sized in the ImageView to represent the widget
* @return the drawable that will be used and sized in the ImageView to represent the widget
*/
private Drawable getWidgetPreview(AppWidgetProviderInfo info) {
PackageManager packageManager = mLauncher.getPackageManager();
final PackageManager packageManager = mPackageManager;
String packageName = info.provider.getPackageName();
Drawable drawable = null;
if (info.previewImage != 0) {
@ -487,9 +530,8 @@ public class CustomizePagedView extends PagedView
final Drawable background = resources.getDrawable(R.drawable.default_widget_preview);
renderDrawableToBitmap(background, bitmap, 0, 0, width, height);
// Draw the icon vertically centered, flush left
// Draw the icon flush left
try {
Rect tmpRect = new Rect();
Drawable icon = null;
if (info.icon > 0) {
icon = packageManager.getDrawable(packageName, info.icon, null);
@ -497,12 +539,10 @@ public class CustomizePagedView extends PagedView
if (icon == null) {
icon = resources.getDrawable(R.drawable.ic_launcher_application);
}
background.getPadding(tmpRect);
final int iconSize = minDim / 2;
final int offset = iconSize / 4;
final int offsetIconSize = offset + iconSize;
renderDrawableToBitmap(icon, null, offset, offset, offsetIconSize, offsetIconSize);
renderDrawableToBitmap(icon, null, offset, offset, iconSize, iconSize);
} catch (Resources.NotFoundException e) {
// if we can't find the icon, then just don't draw it
}
@ -548,6 +588,7 @@ public class CustomizePagedView extends PagedView
mWorkspaceWidgetLayout.setPadding(20, 10, 20, 0);
mMaxWidgetWidth = mWorkspaceWidgetLayout.estimateCellWidth(sMaxWidgetCellHSpan);
mMaxWallpaperWidth = mWorkspaceWidgetLayout.estimateCellWidth(mWallpaperCellHSpan);
}
private void syncWidgetPages() {
@ -557,7 +598,7 @@ public class CustomizePagedView extends PagedView
removeAllViews();
int numPages = relayoutWidgets();
for (int i = 0; i < numPages; ++i) {
LinearLayout layout = new PagedViewWidgetLayout(getContext());
LinearLayout layout = new PagedViewExtendedLayout(getContext());
layout.setGravity(Gravity.CENTER_HORIZONTAL);
layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
@ -610,6 +651,58 @@ public class CustomizePagedView extends PagedView
}
}
private void syncWallpaperPages() {
if (mWallpaperList == null) return;
// We need to repopulate the LinearLayout for the wallpaper pages
removeAllViews();
int numPages = (int) Math.ceil((float) (mWallpaperList.size() * mWallpaperCellHSpan) /
mMaxWidgetsCellHSpan);
for (int i = 0; i < numPages; ++i) {
LinearLayout layout = new PagedViewExtendedLayout(getContext());
layout.setGravity(Gravity.CENTER_HORIZONTAL);
layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
// Temporary change to prevent the last page from being too small (and items bleeding
// onto it). We can remove this once we properly fix the fading algorithm
if (i < numPages - 1) {
addView(layout, new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.MATCH_PARENT));
} else {
addView(layout, new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
}
}
}
private void syncWallpaperPageItems(int page) {
// Load the items on to the pages
LinearLayout layout = (LinearLayout) getChildAt(page);
layout.removeAllViews();
final int count = mWallpaperList.size();
for (int i = 0; i < count; ++i) {
final ResolveInfo info = mWallpaperList.get(i);
LinearLayout l = (LinearLayout) mInflater.inflate(
R.layout.customize_paged_view_wallpaper, layout, false);
l.setTag(info);
l.setOnClickListener(this);
final Drawable icon = getWallpaperPreview(info);
ImageView image = (ImageView) l.findViewById(R.id.wallpaper_preview);
image.setMaxWidth(mMaxWidgetWidth);
image.setImageDrawable(icon);
TextView name = (TextView) l.findViewById(R.id.wallpaper_name);
name.setText(info.loadLabel(mPackageManager));
layout.addView(l);
}
}
private void syncListPages(List<ResolveInfo> list) {
// we need to repopulate with PagedViewCellLayouts
removeAllViews();
@ -716,8 +809,7 @@ public class CustomizePagedView extends PagedView
centerPagedViewCellLayouts = true;
break;
case WallpaperCustomization:
syncListPages(mWallpaperList);
centerPagedViewCellLayouts = true;
syncWallpaperPages();
break;
case ApplicationCustomization:
syncAppPages();
@ -757,7 +849,7 @@ public class CustomizePagedView extends PagedView
syncListPageItems(page, mShortcutList);
break;
case WallpaperCustomization:
syncListPageItems(page, mWallpaperList);
syncWallpaperPageItems(page);
break;
case ApplicationCustomization:
syncAppPageItems(page);

View File

@ -16,12 +16,13 @@
package com.android.launcher2;
import android.graphics.drawable.Drawable;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
class FastBitmapDrawable extends Drawable {
private Bitmap mBitmap;
@ -41,7 +42,8 @@ class FastBitmapDrawable extends Drawable {
@Override
public void draw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint);
final Rect r = getBounds();
canvas.drawBitmap(mBitmap, r.left, r.top, mPaint);
}
@Override

View File

@ -621,6 +621,9 @@ public abstract class PagedView extends ViewGroup {
* scrolling there.
*/
// Skip touch handling if there are no pages to swipe
if (getChildCount() <= 0) return super.onInterceptTouchEvent(ev);
/*
* Shortcut the most recurring case: the user is in the dragging
* state and he is moving his finger. We want to intercept this
@ -775,6 +778,9 @@ public abstract class PagedView extends ViewGroup {
@Override
public boolean onTouchEvent(MotionEvent ev) {
// Skip touch handling if there are no pages to swipe
if (getChildCount() <= 0) return super.onTouchEvent(ev);
acquireVelocityTrackerAndAddMovement(ev);
final int action = ev.getAction();

View File

@ -22,20 +22,20 @@ import android.view.MotionEvent;
import android.widget.LinearLayout;
/**
* The linear layout used strictly for the widget tab of the customization tray
* The linear layout used strictly for the widget/wallpaper tab of the customization tray
*/
public class PagedViewWidgetLayout extends LinearLayout {
public class PagedViewExtendedLayout extends LinearLayout {
static final String TAG = "PagedViewWidgetLayout";
public PagedViewWidgetLayout(Context context) {
public PagedViewExtendedLayout(Context context) {
this(context, null);
}
public PagedViewWidgetLayout(Context context, AttributeSet attrs) {
public PagedViewExtendedLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PagedViewWidgetLayout(Context context, AttributeSet attrs, int defStyle) {
public PagedViewExtendedLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

View File

@ -1,156 +0,0 @@
/*
* Copyright (C) 2010 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.launcher2;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Checkable;
import android.widget.LinearLayout;
import com.android.launcher.R;
/**
* An widget icon for use specifically in the CustomizePagedView. In class form so that
* we can add logic for how it will look when checked/unchecked.
*/
public class PagedViewWidgetIcon extends LinearLayout implements Checkable {
private static final String TAG = "PagedViewIcon";
// Holographic outline
private final Paint mPaint = new Paint();
private static HolographicOutlineHelper sHolographicOutlineHelper;
private final Paint mErasePaint = new Paint();
private Bitmap mCheckedOutline;
private Canvas mHolographicOutlineCanvas;
private boolean mIsHolographicUpdatePass;
private int mAlpha;
private boolean mIsChecked;
// Highlight colours
private int mCheckedBlurColor;
private int mCheckedOutlineColor;
public PagedViewWidgetIcon(Context context) {
this(context, null);
}
public PagedViewWidgetIcon(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PagedViewWidgetIcon(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedViewWidgetIcon,
defStyle, 0);
mCheckedBlurColor = a.getColor(R.styleable.PagedViewWidgetIcon_checkedBlurColor, 0);
mCheckedOutlineColor = a.getColor(R.styleable.PagedViewWidgetIcon_checkedOutlineColor, 0);
mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
mErasePaint.setFilterBitmap(true);
a.recycle();
if (sHolographicOutlineHelper == null) {
sHolographicOutlineHelper = new HolographicOutlineHelper();
}
setWillNotDraw(false);
}
public void invalidateCheckedImage() {
if (mCheckedOutline != null) {
mCheckedOutline.recycle();
mCheckedOutline = null;
}
}
@Override
protected void onDraw(Canvas canvas) {
// Draw the view itself
if (mIsHolographicUpdatePass) {
canvas.save();
final float alpha = getAlpha();
super.setAlpha(1.0f);
super.onDraw(canvas);
super.setAlpha(alpha);
canvas.restore();
} else {
if (mAlpha > 0) {
super.onDraw(canvas);
}
}
// Draw the holographic checked overlay if necessary
if (!mIsHolographicUpdatePass) {
if (mCheckedOutline != null) {
mPaint.setAlpha(255);
canvas.drawBitmap(mCheckedOutline, 0, 0, mPaint);
}
}
}
@Override
public boolean isChecked() {
return mIsChecked;
}
@Override
public void setChecked(boolean checked) {
if (mIsChecked != checked) {
mIsChecked = checked;
if (mIsChecked) {
// set a flag to indicate that we are going to draw the view at full alpha
mIsHolographicUpdatePass = true;
final int width = getMeasuredWidth();
final int height = getMeasuredHeight();
mCheckedOutline = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mHolographicOutlineCanvas = new Canvas(mCheckedOutline);
mHolographicOutlineCanvas.concat(getMatrix());
draw(mHolographicOutlineCanvas);
sHolographicOutlineHelper.applyExpensiveOutlineWithBlur(mCheckedOutline,
mHolographicOutlineCanvas, mCheckedBlurColor, mCheckedOutlineColor);
// Unlike PagedViewIcon, we can't seem to properly set the clip rect for all the
// children to respect when drawing... so for now, we erase over those parts in the
// checked highlight image
mHolographicOutlineCanvas.drawRect(0, findViewById(R.id.divider).getTop(),
width, height, mErasePaint);
mIsHolographicUpdatePass = false;
mHolographicOutlineCanvas = null;
} else {
invalidateCheckedImage();
}
invalidate();
}
}
@Override
public void toggle() {
setChecked(!mIsChecked);
}
}