From 5f1c509d5ad1954a7e38e77db4d5f27c7345fd39 Mon Sep 17 00:00:00 2001 From: Michael Jurka Date: Fri, 3 Sep 2010 14:15:02 -0700 Subject: supporting swipable home screens on xlarge devices - icons and widgets on home screens can be "dimmed" - celllayout no longer renders a dimmed version of itself, but instead its children make dimmed versions of themselves - celllayout no longer always takes up full size of workspace, in landscape mode neighboring screens (celllayouts) are visible - on xlarge devices, in landscape mode side screens are "dimmed" - moved holographic outline helper to its own file - fixed bug where mini-screens were still able to scroll left/right Change-Id: I9e85ab4147edfae1e7525c3d11d42be3fabf4f6d --- proguard.flags | 4 +- res/layout-land/application.xml | 4 +- res/layout-port/application.xml | 2 +- res/layout-xlarge-land/workspace_screen.xml | 8 +- res/layout-xlarge-port/workspace_screen.xml | 8 +- res/values-xlarge/colors.xml | 1 + src/com/android/launcher2/CellLayout.java | 138 +++++++------------ .../launcher2/DimmableAppWidgetHostView.java | 147 +++++++++++++++++++++ .../android/launcher2/DimmableBubbleTextView.java | 137 +++++++++++++++++++ .../launcher2/HolographicOutlineHelper.java | 118 +++++++++++++++++ src/com/android/launcher2/Launcher.java | 6 - .../android/launcher2/LauncherAppWidgetHost.java | 6 +- src/com/android/launcher2/PagedView.java | 46 +++++-- src/com/android/launcher2/PagedViewIcon.java | 99 +------------- src/com/android/launcher2/SmoothPagedView.java | 2 +- src/com/android/launcher2/Workspace.java | 83 +++++++++--- 16 files changed, 571 insertions(+), 238 deletions(-) create mode 100644 src/com/android/launcher2/DimmableAppWidgetHostView.java create mode 100644 src/com/android/launcher2/DimmableBubbleTextView.java create mode 100644 src/com/android/launcher2/HolographicOutlineHelper.java diff --git a/proguard.flags b/proguard.flags index aa75f4a86..82411eb85 100644 --- a/proguard.flags +++ b/proguard.flags @@ -9,8 +9,8 @@ } -keep class com.android.launcher2.CellLayout { - public float getDimmedBitmapAlpha(); - public void setDimmedBitmapAlpha(float); + public float getBackgroundAlpha(); + public void setBackgroundAlpha(float); } -keep class com.android.launcher2.AllApps3D$Defines { diff --git a/res/layout-land/application.xml b/res/layout-land/application.xml index 6de565878..846c81c1d 100644 --- a/res/layout-land/application.xml +++ b/res/layout-land/application.xml @@ -14,5 +14,5 @@ limitations under the License. --> - + diff --git a/res/layout-port/application.xml b/res/layout-port/application.xml index f904a661f..ec6697658 100644 --- a/res/layout-port/application.xml +++ b/res/layout-port/application.xml @@ -14,5 +14,5 @@ limitations under the License. --> - diff --git a/res/layout-xlarge-land/workspace_screen.xml b/res/layout-xlarge-land/workspace_screen.xml index 15fc3b19d..f35844371 100644 --- a/res/layout-xlarge-land/workspace_screen.xml +++ b/res/layout-xlarge-land/workspace_screen.xml @@ -18,13 +18,13 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher" - android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:hapticFeedbackEnabled="false" launcher:cellWidth="@dimen/workspace_cell_width" launcher:cellHeight="@dimen/workspace_cell_height" launcher:yAxisStartPadding="40dip" launcher:yAxisEndPadding="40dip" - launcher:xAxisStartPadding="256dip" - launcher:xAxisEndPadding="256dip" /> + launcher:xAxisStartPadding="40dip" + launcher:xAxisEndPadding="40dip" /> diff --git a/res/layout-xlarge-port/workspace_screen.xml b/res/layout-xlarge-port/workspace_screen.xml index eb7620ca6..7314e6046 100644 --- a/res/layout-xlarge-port/workspace_screen.xml +++ b/res/layout-xlarge-port/workspace_screen.xml @@ -18,13 +18,13 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher" - android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:hapticFeedbackEnabled="false" launcher:cellWidth="@dimen/workspace_cell_width" launcher:cellHeight="@dimen/workspace_cell_height" - launcher:yAxisStartPadding="172dip" - launcher:yAxisEndPadding="172dip" + launcher:yAxisStartPadding="40dip" + launcher:yAxisEndPadding="40dip" launcher:xAxisStartPadding="40dip" launcher:xAxisEndPadding="40dip"/> diff --git a/res/values-xlarge/colors.xml b/res/values-xlarge/colors.xml index a6cdd06bf..d4c6fadb4 100644 --- a/res/values-xlarge/colors.xml +++ b/res/values-xlarge/colors.xml @@ -18,4 +18,5 @@ --> #A50000FE + #FF7F7F7F \ No newline at end of file diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java index 8cf70412b..4d1c29961 100644 --- a/src/com/android/launcher2/CellLayout.java +++ b/src/com/android/launcher2/CellLayout.java @@ -22,12 +22,7 @@ import android.app.WallpaperManager; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; -import android.graphics.Bitmap; import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; @@ -37,17 +32,13 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewDebug; import android.view.ViewGroup; -import android.view.View.OnTouchListener; import android.view.animation.Animation; import android.view.animation.LayoutAnimationController; -import java.util.ArrayList; import java.util.Arrays; public class CellLayout extends ViewGroup { static final String TAG = "CellLayout"; - // we make the dimmed bitmap smaller than the screen itself for memory + perf reasons - static final float DIMMED_BITMAP_SCALE = 0.25f; private boolean mPortrait; @@ -77,17 +68,10 @@ public class CellLayout extends ViewGroup { private OnTouchListener mInterceptTouchListener; - // this is what the home screen fades to when it shrinks - // (ie in all apps and in home screen customize mode) - private Bitmap mDimmedBitmap; - private Canvas mDimmedBitmapCanvas; - private float mDimmedBitmapAlpha; - private boolean mDimmedBitmapDirty = false; - private final Paint mDimmedBitmapPaint = new Paint(); - private final Rect mLayoutRect = new Rect(); - private final Rect mDimmedBitmapRect = new Rect(); - private Drawable mDimmedBitmapBackground; - private Drawable mDimmedBitmapBackgroundHover; + private float mBackgroundAlpha; + private final Rect mBackgroundLayoutRect = new Rect(); + private Drawable mBackground; + private Drawable mBackgroundHover; // If we're actively dragging something over this screen and it's small, // mHover is true private boolean mHover = false; @@ -129,13 +113,10 @@ public class CellLayout extends ViewGroup { mOccupiedDrawable = getResources().getDrawable(R.drawable.rounded_rect_red); if (LauncherApplication.isScreenXLarge()) { - mDimmedBitmapBackground = getResources().getDrawable( - R.drawable.mini_home_screen_bg); - mDimmedBitmapBackground.setFilterBitmap(true); - - mDimmedBitmapBackgroundHover = getResources().getDrawable( - R.drawable.mini_home_screen_bg_hover); - mDimmedBitmapBackgroundHover.setFilterBitmap(true); + mBackground = getResources().getDrawable(R.drawable.mini_home_screen_bg); + mBackground.setFilterBitmap(true); + mBackgroundHover = getResources().getDrawable(R.drawable.mini_home_screen_bg_hover); + mBackgroundHover.setFilterBitmap(true); } TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CellLayout, defStyle, 0); @@ -160,8 +141,6 @@ public class CellLayout extends ViewGroup { setAlwaysDrawnWithCacheEnabled(false); mWallpaperManager = WallpaperManager.getInstance(getContext()); - - mDimmedBitmapPaint.setFilterBitmap(true); } public void setHover(boolean value) { @@ -173,9 +152,9 @@ public class CellLayout extends ViewGroup { @Override public void dispatchDraw(Canvas canvas) { - if (mDimmedBitmapAlpha > 0.0f) { - final Drawable bg = mHover ? mDimmedBitmapBackgroundHover : mDimmedBitmapBackground; - bg.setAlpha((int) (mDimmedBitmapAlpha * 255)); + if (mBackgroundAlpha > 0.0f) { + final Drawable bg = mHover ? mBackgroundHover : mBackground; + bg.setAlpha((int) (mBackgroundAlpha * 255)); bg.draw(canvas); } super.dispatchDraw(canvas); @@ -191,15 +170,7 @@ public class CellLayout extends ViewGroup { (int)mDragRect.bottom); mDragRectDrawable.draw(canvas); } - if (mDimmedBitmap != null && mDimmedBitmapAlpha > 0.0f) { - if (mDimmedBitmapDirty) { - updateDimmedBitmap(); - mDimmedBitmapDirty = false; - } - mDimmedBitmapPaint.setAlpha((int) (mDimmedBitmapAlpha * 255)); - - //canvas.drawBitmap(mDimmedBitmap, mDimmedBitmapRect, mLayoutRect, mDimmedBitmapPaint); - } + super.onDraw(canvas); } @Override @@ -242,23 +213,15 @@ public class CellLayout extends ViewGroup { // We might be in the middle or end of shrinking/fading to a dimmed view // Make sure this view's alpha is set the same as all the rest of the views - //child.setAlpha(1.0f - mDimmedBitmapAlpha); + child.setAlpha(getAlpha()); addView(child, index, lp); - // next time we draw the dimmed bitmap we need to update it - mDimmedBitmapDirty = true; return true; } return false; } - @Override - public void removeView(View view) { - super.removeView(view); - mDimmedBitmapDirty = true; - } - @Override public void requestChildFocus(View child, View focused) { super.requestChildFocus(child, focused); @@ -544,6 +507,10 @@ public class CellLayout extends ViewGroup { - mRightPadding - (cellWidth * mCountX); mWidthGap = hSpaceLeft / numWidthGaps; + // center it around the min gaps + int minGap = Math.min(mWidthGap, mHeightGap); + mWidthGap = mHeightGap = minGap; + int count = getChildCount(); for (int i = 0; i < count; i++) { @@ -559,8 +526,15 @@ public class CellLayout extends ViewGroup { child.measure(childWidthMeasureSpec, childheightMeasureSpec); } - - setMeasuredDimension(widthSpecSize, heightSpecSize); + if (widthSpecMode == MeasureSpec.AT_MOST) { + int newWidth = mLeftPadding + mRightPadding + (mCountX * cellWidth) + + ((mCountX - 1) * minGap); + int newHeight = mTopPadding + mBottomPadding + (mCountY * cellHeight) + + ((mCountY - 1) * minGap); + setMeasuredDimension(newWidth, newHeight); + } else if (widthSpecMode == MeasureSpec.EXACTLY) { + setMeasuredDimension(widthSpecSize, heightSpecSize); + } } @Override @@ -593,13 +567,12 @@ public class CellLayout extends ViewGroup { @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); - mLayoutRect.set(0, 0, w, h); - mDimmedBitmapRect.set(0, 0, (int) (DIMMED_BITMAP_SCALE * w), (int) (DIMMED_BITMAP_SCALE * h)); - if (mDimmedBitmapBackground != null) { - mDimmedBitmapBackground.setBounds(mLayoutRect); + mBackgroundLayoutRect.set(0, 0, w, h); + if (mBackground != null) { + mBackground.setBounds(mBackgroundLayoutRect); } - if (mDimmedBitmapBackgroundHover != null) { - mDimmedBitmapBackgroundHover.setBounds(mLayoutRect); + if (mBackgroundHover != null) { + mBackgroundHover.setBounds(mBackgroundLayoutRect); } } @@ -619,22 +592,28 @@ public class CellLayout extends ViewGroup { super.setChildrenDrawnWithCacheEnabled(enabled); } - public float getDimmedBitmapAlpha() { - return mDimmedBitmapAlpha; + public float getBackgroundAlpha() { + return mBackgroundAlpha; } - public void setDimmedBitmapAlpha(float alpha) { - // If we're dimming the screen after it was not dimmed, refresh - // to allow for updated widgets. We don't continually refresh it - // after this point, however, as an optimization - if (mDimmedBitmapAlpha == 0.0f && alpha > 0.0f) { - updateDimmedBitmap(); - } - mDimmedBitmapAlpha = alpha; - //setChildrenAlpha(1.0f - mDimmedBitmapAlpha); + public void setBackgroundAlpha(float alpha) { + mBackgroundAlpha = alpha; invalidate(); } + // Need to return true to let the view system know we know how to handle alpha-- this is + // because when our children have an alpha of 0.0f, they are still rendering their "dimmed" + // versions + @Override + protected boolean onSetAlpha(int alpha) { + return true; + } + + public void setAlpha(float alpha) { + setChildrenAlpha(alpha); + super.setAlpha(alpha); + } + private void setChildrenAlpha(float alpha) { final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { @@ -642,27 +621,6 @@ public class CellLayout extends ViewGroup { } } - public void updateDimmedBitmap() { - if (mDimmedBitmap == null) { - mDimmedBitmap = Bitmap.createBitmap((int) (getWidth() * DIMMED_BITMAP_SCALE), - (int) (getHeight() * DIMMED_BITMAP_SCALE), Bitmap.Config.ARGB_8888); - mDimmedBitmapCanvas = new Canvas(mDimmedBitmap); - mDimmedBitmapCanvas.scale(DIMMED_BITMAP_SCALE, DIMMED_BITMAP_SCALE); - } - // clear the canvas - mDimmedBitmapCanvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR); - - // draw the screen into the bitmap - // just for drawing to the bitmap, make all the items on the screen opaque - //setChildrenAlpha(1.0f); - // call our superclass's dispatchdraw so we don't draw the background - super.dispatchDraw(mDimmedBitmapCanvas); - //setChildrenAlpha(1.0f - mDimmedBitmapAlpha); - - // replace all colored areas with a dark (semi-transparent black) - mDimmedBitmapCanvas.drawColor(Color.argb(160, 0, 0, 0), PorterDuff.Mode.SRC_IN); - } - private boolean isVacant(int originX, int originY, int spanX, int spanY) { for (int i = 0; i < spanY; i++) { if (!isRowEmpty(originY + i, originX, originX + spanX - 1, mOccupied)) { diff --git a/src/com/android/launcher2/DimmableAppWidgetHostView.java b/src/com/android/launcher2/DimmableAppWidgetHostView.java new file mode 100644 index 000000000..7a1d4f9da --- /dev/null +++ b/src/com/android/launcher2/DimmableAppWidgetHostView.java @@ -0,0 +1,147 @@ +/* + * 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 com.android.launcher.R; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.view.View; + +public class DimmableAppWidgetHostView extends LauncherAppWidgetHostView { + public DimmableAppWidgetHostView(Context context) { + super(context); + mPaint.setFilterBitmap(true); + } + + private final Paint mPaint = new Paint(); + private int mAlpha; + private int mDimmedAlpha; + private Bitmap mDimmedView; + private Canvas mDimmedViewCanvas; + private boolean isDimmedViewUpdatePass; + + private static float cubic(float r) { + return (float) (Math.pow(r-1, 3) + 1); + } + + /** + * Returns the interpolated holographic highlight alpha for the effect we want when scrolling + * pages. + */ + public static float highlightAlphaInterpolator(float r) { + final float pivot = 0.3f; + if (r < pivot) { + return Math.max(0.5f, 0.65f*cubic(r/pivot)); + } else { + return Math.min(1.0f, 0.65f*cubic(1 - (r-pivot)/(1-pivot))); + } + } + + /** + * Returns the interpolated view alpha for the effect we want when scrolling pages. + */ + public static float viewAlphaInterpolator(float r) { + final float pivot = 0.6f; + if (r < pivot) { + return r/pivot; + } else { + return 1.0f; + } + } + + private void setChildAlpha(float alpha) { + if (getChildCount() > 0) { + final View child = getChildAt(0); + if (child.getAlpha() != alpha) { + getChildAt(0).setAlpha(alpha); + } + } + } + + private void updateChildAlpha() { + // hacky, but sometimes widgets get their alpha set back to 1.0f, so we call + // this to force them back + setChildAlpha(getAlpha()); + } + + @Override + public boolean onSetAlpha(int alpha) { + super.onSetAlpha(alpha); + return true; + } + + @Override + public void setAlpha(float alpha) { + final float viewAlpha = viewAlphaInterpolator(alpha); + final float dimmedAlpha = highlightAlphaInterpolator(alpha); + mAlpha = (int) (viewAlpha * 255); + mDimmedAlpha = (int) (dimmedAlpha * 255); + super.setAlpha(viewAlpha); + setChildAlpha(viewAlpha); + } + + private void updateDimmedView() { + if (mDimmedView == null) { + mDimmedView = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), + Bitmap.Config.ARGB_8888); + mDimmedViewCanvas = new Canvas(mDimmedView); + } + mDimmedViewCanvas.drawColor(0x00000000); + mDimmedViewCanvas.concat(getMatrix()); + isDimmedViewUpdatePass = true; + draw(mDimmedViewCanvas); + // make the bitmap look "dimmed" + int dimmedColor = getContext().getResources().getColor(R.color.dimmed_view_color); + mDimmedViewCanvas.drawColor(dimmedColor, PorterDuff.Mode.SRC_IN); + isDimmedViewUpdatePass = false; + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + if (mDimmedView == null && mDimmedAlpha > 0.0f) { + updateDimmedView(); + } + } + + @Override + public void dispatchDraw(Canvas canvas) { + if (isDimmedViewUpdatePass) { + final float alpha = getAlpha(); + canvas.save(); + setAlpha(1.0f); + super.dispatchDraw(canvas); + canvas.restore(); + setAlpha(alpha); + } else { + if (mDimmedView != null && mDimmedAlpha > 0) { + // draw the dimmed version of this widget + mPaint.setAlpha(mDimmedAlpha); + canvas.drawBitmap(mDimmedView, 0, 0, mPaint); + } + + updateChildAlpha(); + super.dispatchDraw(canvas); + } + } +} \ No newline at end of file diff --git a/src/com/android/launcher2/DimmableBubbleTextView.java b/src/com/android/launcher2/DimmableBubbleTextView.java new file mode 100644 index 000000000..66cc97a1b --- /dev/null +++ b/src/com/android/launcher2/DimmableBubbleTextView.java @@ -0,0 +1,137 @@ +/* + * 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 com.android.launcher.R; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.util.AttributeSet; + +public class DimmableBubbleTextView extends BubbleTextView { + private Paint mDimmedPaint = new Paint(); + private int mAlpha; + private int mDimmedAlpha; + private Bitmap mDimmedView; + private Canvas mDimmedViewCanvas; + private boolean isDimmedViewUpdatePass; + + public DimmableBubbleTextView(Context context) { + super(context); + mDimmedPaint.setFilterBitmap(true); + } + + public DimmableBubbleTextView(Context context, AttributeSet attrs) { + super(context, attrs); + mDimmedPaint.setFilterBitmap(true); + } + + public DimmableBubbleTextView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mDimmedPaint.setFilterBitmap(true); + } + + private static float cubic(float r) { + return (float) (Math.pow(r-1, 3) + 1); + } + + /** + * Returns the interpolated holographic highlight alpha for the effect we want when scrolling + * pages. + */ + public static float highlightAlphaInterpolator(float r) { + final float pivot = 0.3f; + if (r < pivot) { + return Math.max(0.5f, 0.65f*cubic(r/pivot)); + } else { + return Math.min(1.0f, 0.65f*cubic(1 - (r-pivot)/(1-pivot))); + } + } + + /** + * Returns the interpolated view alpha for the effect we want when scrolling pages. + */ + public static float viewAlphaInterpolator(float r) { + final float pivot = 0.6f; + if (r < pivot) { + return r/pivot; + } else { + return 1.0f; + } + } + + @Override + public boolean onSetAlpha(int alpha) { + super.onSetAlpha(alpha); + return true; + } + + @Override + public void setAlpha(float alpha) { + final float viewAlpha = viewAlphaInterpolator(alpha); + final float dimmedAlpha = highlightAlphaInterpolator(alpha); + mAlpha = (int) (viewAlpha * 255); + mDimmedAlpha = (int) (dimmedAlpha * 255); + super.setAlpha(viewAlpha); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + if (mDimmedView == null) { + isDimmedViewUpdatePass = true; + mDimmedView = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), + Bitmap.Config.ARGB_8888); + mDimmedViewCanvas = new Canvas(mDimmedView); + mDimmedViewCanvas.concat(getMatrix()); + + draw(mDimmedViewCanvas); + + // MAKE THE DIMMED VERSION + int dimmedColor = getContext().getResources().getColor(R.color.dimmed_view_color); + mDimmedViewCanvas.drawColor(dimmedColor, PorterDuff.Mode.SRC_IN); + + isDimmedViewUpdatePass = false; + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (isDimmedViewUpdatePass) { + 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); + } + } + + if (mDimmedView != null && mDimmedAlpha > 0) { + mDimmedPaint.setAlpha(mDimmedAlpha); + canvas.drawBitmap(mDimmedView, mScrollX, mScrollY, mDimmedPaint); + } + } +} \ No newline at end of file diff --git a/src/com/android/launcher2/HolographicOutlineHelper.java b/src/com/android/launcher2/HolographicOutlineHelper.java new file mode 100644 index 000000000..621033748 --- /dev/null +++ b/src/com/android/launcher2/HolographicOutlineHelper.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2008 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.graphics.Bitmap; +import android.graphics.BlurMaskFilter; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PointF; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; + +public class HolographicOutlineHelper { + private float mDensity; + private final Paint mHolographicPaint = new Paint(); + private final Paint mBlurPaint = new Paint(); + private final Paint mErasePaint = new Paint(); + private static final Matrix mIdentity = new Matrix();; + private static final float BLUR_FACTOR = 3.5f; + + public static final float DEFAULT_STROKE_WIDTH = 6.0f; + public static final int HOLOGRAPHIC_BLUE = 0xFF6699FF; + public static final int HOLOGRAPHIC_GREEN = 0xFF51E633; + + HolographicOutlineHelper(float density) { + mDensity = density; + mHolographicPaint.setColor(HOLOGRAPHIC_BLUE); + mHolographicPaint.setFilterBitmap(true); + mHolographicPaint.setAntiAlias(true); + mBlurPaint.setMaskFilter(new BlurMaskFilter(BLUR_FACTOR * density, + BlurMaskFilter.Blur.OUTER)); + mBlurPaint.setFilterBitmap(true); + mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + mErasePaint.setFilterBitmap(true); + mErasePaint.setAntiAlias(true); + } + + private float cubic(float r) { + return (float) (Math.pow(r - 1, 3) + 1); + } + + /** + * Returns the interpolated holographic highlight alpha for the effect we want when scrolling + * pages. + */ + public float highlightAlphaInterpolator(float r) { + final float pivot = 0.3f; + if (r < pivot) { + return Math.max(0.5f, 0.65f * cubic(r / pivot)); + } else { + return Math.min(1.0f, 0.65f * cubic(1 - (r - pivot) / (1 - pivot))); + } + } + + /** + * Returns the interpolated view alpha for the effect we want when scrolling pages. + */ + public float viewAlphaInterpolator(float r) { + final float pivot = 0.6f; + if (r < pivot) { + return r / pivot; + } else { + return 1.0f; + } + } + + /** + * Sets the color of the holographic paint to be used when applying the outline/blur. + */ + void setColor(int color) { + mHolographicPaint.setColor(color); + } + + /** + * Applies an outline to whatever is currently drawn in the specified bitmap. + */ + void applyOutline(Bitmap srcDst, Canvas srcDstCanvas, float strokeWidth, PointF offset) { + strokeWidth *= mDensity; + Bitmap mask = srcDst.extractAlpha(); + Matrix m = new Matrix(); + final int width = srcDst.getWidth(); + final int height = srcDst.getHeight(); + float xScale = strokeWidth * 2.0f / width; + float yScale = strokeWidth * 2.0f / height; + m.preScale(1 + xScale, 1 + yScale, (width / 2.0f) + offset.x, + (height / 2.0f) + offset.y); + + srcDstCanvas.drawColor(0, PorterDuff.Mode.CLEAR); + srcDstCanvas.drawBitmap(mask, m, mHolographicPaint); + srcDstCanvas.drawBitmap(mask, mIdentity, mErasePaint); + mask.recycle(); + } + + /** + * Applies an blur to whatever is currently drawn in the specified bitmap. + */ + void applyBlur(Bitmap srcDst, Canvas srcDstCanvas) { + int[] xy = new int[2]; + Bitmap mask = srcDst.extractAlpha(mBlurPaint, xy); + srcDstCanvas.drawBitmap(mask, xy[0], xy[1], mHolographicPaint); + mask.recycle(); + } +} \ No newline at end of file diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java index dc0e7e93b..c5450f34e 100644 --- a/src/com/android/launcher2/Launcher.java +++ b/src/com/android/launcher2/Launcher.java @@ -374,12 +374,6 @@ public final class Launcher extends Activity registerReceiver(mCloseSystemDialogsReceiver, filter); } - @Override - public void onConfigurationChanged(Configuration newConfig) { - // TODO Auto-generated method stub - super.onConfigurationChanged(newConfig); - } - private void checkForLocaleChange() { if (sLocaleConfiguration == null) { new AsyncTask() { diff --git a/src/com/android/launcher2/LauncherAppWidgetHost.java b/src/com/android/launcher2/LauncherAppWidgetHost.java index a5761ecc3..75a9940c5 100644 --- a/src/com/android/launcher2/LauncherAppWidgetHost.java +++ b/src/com/android/launcher2/LauncherAppWidgetHost.java @@ -34,6 +34,10 @@ public class LauncherAppWidgetHost extends AppWidgetHost { @Override protected AppWidgetHostView onCreateView(Context context, int appWidgetId, AppWidgetProviderInfo appWidget) { - return new LauncherAppWidgetHostView(context); + if (LauncherApplication.isScreenXLarge()) { + return new DimmableAppWidgetHostView(context); + } else { + return new AppWidgetHostView(context); + } } } diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java index c62c397c5..e3c36af3b 100644 --- a/src/com/android/launcher2/PagedView.java +++ b/src/com/android/launcher2/PagedView.java @@ -33,8 +33,8 @@ import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; import android.view.animation.Animation; -import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationUtils; +import android.view.animation.Animation.AnimationListener; import android.widget.Checkable; import android.widget.Scroller; @@ -87,13 +87,11 @@ public abstract class PagedView extends ViewGroup { private int mPagingTouchSlop; private int mMaximumVelocity; - private static final int INVALID_POINTER = -1; + protected static final int INVALID_POINTER = -1; - private int mActivePointerId = INVALID_POINTER; + protected int mActivePointerId = INVALID_POINTER; - private enum PageMovingState { PAGE_BEGIN_MOVING, PAGE_END_MOVING }; private PageSwitchListener mPageSwitchListener; - private PageMovingListener mPageMovingListener; private ArrayList mDirtyPageContent; private boolean mDirtyPageAlpha; @@ -266,10 +264,12 @@ public abstract class PagedView extends ViewGroup { // we moved this functionality to a helper function so SmoothPagedView can reuse it protected boolean computeScrollHelper() { if (mScroller.computeScrollOffset()) { + mDirtyPageAlpha = true; scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); invalidate(); return true; } else if (mNextPage != INVALID_PAGE) { + mDirtyPageAlpha = true; mCurrentPage = Math.max(0, Math.min(mNextPage, getPageCount() - 1)); mNextPage = INVALID_PAGE; notifyPageSwitchListener(); @@ -299,17 +299,41 @@ public abstract class PagedView extends ViewGroup { } // The children are given the same width and height as the workspace + // unless they were set to WRAP_CONTENT final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { - getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec); + // disallowing padding in paged view (just pass 0) + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + int childWidthMode; + if (lp.width == LayoutParams.WRAP_CONTENT) { + childWidthMode = MeasureSpec.AT_MOST; + } else { + childWidthMode = MeasureSpec.EXACTLY; + } + + int childHeightMode; + if (lp.height == LayoutParams.WRAP_CONTENT) { + childHeightMode = MeasureSpec.AT_MOST; + } else { + childHeightMode = MeasureSpec.EXACTLY; + } + + final int childWidthMeasureSpec = + MeasureSpec.makeMeasureSpec(widthSize, childWidthMode); + final int childHeightMeasureSpec = + MeasureSpec.makeMeasureSpec(heightSize, childHeightMode); + + child.measure(childWidthMeasureSpec, childHeightMeasureSpec); } setMeasuredDimension(widthSize, heightSize); - if (mFirstLayout) { + if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) { setHorizontalScrollBarEnabled(false); - scrollTo(mCurrentPage * widthSize, 0); - mScroller.setFinalX(mCurrentPage * widthSize); + scrollTo(getChildOffset(mCurrentPage) - getRelativeChildOffset(mCurrentPage), 0); + mScroller.setFinalX(getChildOffset(mCurrentPage) - getRelativeChildOffset(mCurrentPage)); setHorizontalScrollBarEnabled(true); mFirstLayout = false; } @@ -327,7 +351,9 @@ public abstract class PagedView extends ViewGroup { final View child = getChildAt(i); if (child.getVisibility() != View.GONE) { final int childWidth = child.getMeasuredWidth(); - child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight()); + final int childHeight = (getMeasuredHeight() - child.getMeasuredHeight()) / 2; + child.layout(childLeft, childHeight, + childLeft + childWidth, childHeight + child.getMeasuredHeight()); childLeft += childWidth; } } diff --git a/src/com/android/launcher2/PagedViewIcon.java b/src/com/android/launcher2/PagedViewIcon.java index b8cc206bf..4fa83dfa7 100644 --- a/src/com/android/launcher2/PagedViewIcon.java +++ b/src/com/android/launcher2/PagedViewIcon.java @@ -16,120 +16,25 @@ package com.android.launcher2; +import com.android.launcher2.PagedView.PagedViewIconCache; + 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.BlurMaskFilter; import android.graphics.Canvas; -import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PointF; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.Region.Op; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.DisplayMetrics; -import android.util.Log; import android.widget.Checkable; import android.widget.TextView; -import com.android.launcher2.PagedView.PagedViewIconCache; - -class HolographicOutlineHelper { - private float mDensity; - private final Paint mHolographicPaint = new Paint(); - private final Paint mBlurPaint = new Paint(); - private final Paint mErasePaint = new Paint(); - private static final Matrix mIdentity = new Matrix();; - private static final float BLUR_FACTOR = 3.5f; - - public static final float DEFAULT_STROKE_WIDTH = 6.0f; - public static final int HOLOGRAPHIC_BLUE = 0xFF6699FF; - public static final int HOLOGRAPHIC_GREEN = 0xFF51E633; - - HolographicOutlineHelper(float density) { - mDensity = density; - mHolographicPaint.setColor(HOLOGRAPHIC_BLUE); - mHolographicPaint.setFilterBitmap(true); - mHolographicPaint.setAntiAlias(true); - mBlurPaint.setMaskFilter(new BlurMaskFilter(BLUR_FACTOR * density, - BlurMaskFilter.Blur.OUTER)); - mBlurPaint.setFilterBitmap(true); - mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); - mErasePaint.setFilterBitmap(true); - mErasePaint.setAntiAlias(true); - } - - private float cubic(float r) { - return (float) (Math.pow(r-1, 3) + 1); - } - - /** - * Returns the interpolated holographic highlight alpha for the effect we want when scrolling - * pages. - */ - public float highlightAlphaInterpolator(float r) { - final float pivot = 0.3f; - if (r < pivot) { - return Math.max(0.5f, 0.65f*cubic(r/pivot)); - } else { - return Math.min(1.0f, 0.65f*cubic(1 - (r-pivot)/(1-pivot))); - } - } - /** - * Returns the interpolated view alpha for the effect we want when scrolling pages. - */ - public float viewAlphaInterpolator(float r) { - final float pivot = 0.6f; - if (r < pivot) { - return r/pivot; - } else { - return 1.0f; - } - } - - /** - * Sets the color of the holographic paint to be used when applying the outline/blur. - */ - void setColor(int color) { - mHolographicPaint.setColor(color); - } - - /** - * Applies an outline to whatever is currently drawn in the specified bitmap. - */ - void applyOutline(Bitmap srcDst, Canvas srcDstCanvas, float strokeWidth, PointF offset) { - strokeWidth *= mDensity; - Bitmap mask = srcDst.extractAlpha(); - Matrix m = new Matrix(); - final int width = srcDst.getWidth(); - final int height = srcDst.getHeight(); - float xScale = strokeWidth*2.0f/width; - float yScale = strokeWidth*2.0f/height; - m.preScale(1+xScale, 1+yScale, (width / 2.0f) + offset.x, - (height / 2.0f) + offset.y); - - srcDstCanvas.drawColor(0, PorterDuff.Mode.CLEAR); - srcDstCanvas.drawBitmap(mask, m, mHolographicPaint); - srcDstCanvas.drawBitmap(mask, mIdentity, mErasePaint); - mask.recycle(); - } - - /** - * Applies an blur to whatever is currently drawn in the specified bitmap. - */ - void applyBlur(Bitmap srcDst, Canvas srcDstCanvas) { - int[] xy = new int[2]; - Bitmap mask = srcDst.extractAlpha(mBlurPaint, xy); - srcDstCanvas.drawBitmap(mask, xy[0], xy[1], mHolographicPaint); - mask.recycle(); - } -} /** * An icon on a PagedView, specifically for items in the launcher's paged view (with compound diff --git a/src/com/android/launcher2/SmoothPagedView.java b/src/com/android/launcher2/SmoothPagedView.java index 321834902..73e147a22 100644 --- a/src/com/android/launcher2/SmoothPagedView.java +++ b/src/com/android/launcher2/SmoothPagedView.java @@ -110,7 +110,7 @@ public abstract class SmoothPagedView extends PagedView { whichPage = Math.max(0, Math.min(whichPage, getChildCount() - 1)); final int screenDelta = Math.max(1, Math.abs(whichPage - mCurrentPage)); - final int newX = whichPage * getWidth(); + final int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage); final int delta = newX - mScrollX; int duration = (screenDelta + 1) * 100; diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index 59e061b5c..7ce7ea999 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -138,7 +138,10 @@ public class Workspace extends SmoothPagedView public Workspace(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mContentIsRefreshable = false; - mFadeInAdjacentScreens = false; + + if (!LauncherApplication.isScreenXLarge()) { + mFadeInAdjacentScreens = false; + } mWallpaperManager = WallpaperManager.getInstance(context); @@ -383,19 +386,46 @@ public class Workspace extends SmoothPagedView return false; } + @Override + public boolean dispatchUnhandledMove(View focused, int direction) { + if (mIsSmall) { + // when the home screens are shrunken, shouldn't allow side-scrolling + return false; + } + return super.dispatchUnhandledMove(focused, direction); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (mIsSmall) { + // when the home screens are shrunken, shouldn't allow side-scrolling + return false; + } + return super.onInterceptTouchEvent(ev); + } + protected void pageBeginMoving() { if (mNextPage != INVALID_PAGE) { // we're snapping to a particular screen - enableChildrenCache(mCurrentPage, mNextPage); + // there's an issue where the alpha of neighboring pages doesn't get updated + // if drawing cache is enabled on children-- we only use that on xlarge devices, + // so disable drawing cache in those cases + if (!LauncherApplication.isScreenXLarge()) { + enableChildrenCache(mCurrentPage, mNextPage); + } } else { // this is when user is actively dragging a particular screen, they might // swipe it either left or right (but we won't advance by more than one screen) - enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1); + if (!LauncherApplication.isScreenXLarge()) { + enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1); + } } } protected void pageEndMoving() { - clearChildrenCache(); + if (!LauncherApplication.isScreenXLarge()) { + clearChildrenCache(); + } } @Override @@ -465,9 +495,6 @@ public class Workspace extends SmoothPagedView for (int i = 0; i < pageCount; i++) { final View page = (View) getChildAt(i); - if (page.getAlpha() != 1.0f) { - page.setAlpha(1.0f); - } drawChild(canvas, page, drawingTime); } } else { @@ -596,6 +623,10 @@ public class Workspace extends SmoothPagedView // we use this to shrink the workspace for the all apps view and the customize view private void shrink(ShrinkPosition shrinkPosition, boolean animated) { mIsSmall = true; + // we intercept and reject all touch events when we're small, so be sure to reset the state + mTouchState = TOUCH_STATE_REST; + mActivePointerId = INVALID_POINTER; + final Resources res = getResources(); final int screenWidth = getWidth(); final int screenHeight = getHeight(); @@ -637,19 +668,21 @@ public class Workspace extends SmoothPagedView if (animated) { final int duration = res.getInteger(R.integer.config_workspaceShrinkTime); - new ObjectAnimator(duration, cl, - new PropertyValuesHolder("x", newX), - new PropertyValuesHolder("y", newY), - new PropertyValuesHolder("scaleX", SHRINK_FACTOR * rotationScaleX), - new PropertyValuesHolder("scaleY", SHRINK_FACTOR * rotationScaleY), - new PropertyValuesHolder("dimmedBitmapAlpha", 1.0f), - new PropertyValuesHolder("rotationY", rotation)).start(); + new ObjectAnimator(duration, cl, + new PropertyValuesHolder("x", newX), + new PropertyValuesHolder("y", newY), + new PropertyValuesHolder("scaleX", SHRINK_FACTOR), + new PropertyValuesHolder("scaleY", SHRINK_FACTOR), + new PropertyValuesHolder("backgroundAlpha", 1.0f), + new PropertyValuesHolder("alpha", 0.0f), + new PropertyValuesHolder("rotationY", rotation)).start(); } else { cl.setX((int)newX); cl.setY((int)newY); cl.setScaleX(SHRINK_FACTOR); cl.setScaleY(SHRINK_FACTOR); - cl.setDimmedBitmapAlpha(1.0f); + cl.setBackgroundAlpha(1.0f); + cl.setAlpha(0.0f); cl.setRotationY(rotation); } // increment newX for the next screen @@ -673,7 +706,8 @@ public class Workspace extends SmoothPagedView private void unshrink(int newCurrentPage) { if (mIsSmall) { - int delta = (newCurrentPage - mCurrentPage)*getWidth(); + int newX = getChildOffset(newCurrentPage) - getRelativeChildOffset(newCurrentPage); + int delta = newX - mScrollX; final int screenCount = getChildCount(); for (int i = 0; i < screenCount; i++) { @@ -699,20 +733,23 @@ public class Workspace extends SmoothPagedView final int duration = getResources().getInteger(R.integer.config_workspaceUnshrinkTime); for (int i = 0; i < screenCount; i++) { final CellLayout cl = (CellLayout)getChildAt(i); + float finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f; if (animated) { s.playTogether( new ObjectAnimator(duration, cl, "translationX", 0.0f), new ObjectAnimator(duration, cl, "translationY", 0.0f), new ObjectAnimator(duration, cl, "scaleX", 1.0f), new ObjectAnimator(duration, cl, "scaleY", 1.0f), - new ObjectAnimator(duration, cl, "dimmedBitmapAlpha", 0.0f), + new ObjectAnimator(duration, cl, "backgroundAlpha", 0.0f), + new ObjectAnimator(duration, cl, "alpha", finalAlphaValue), new ObjectAnimator(duration, cl, "rotationY", 0.0f)); } else { cl.setTranslationX(0.0f); cl.setTranslationY(0.0f); cl.setScaleX(1.0f); cl.setScaleY(1.0f); - cl.setDimmedBitmapAlpha(0.0f); + cl.setBackgroundAlpha(0.0f); + cl.setAlpha(1.0f); cl.setRotationY(0.0f); } } @@ -838,6 +875,8 @@ public class Workspace extends SmoothPagedView // If we are dragging over a cell that contains a DropTarget that will // accept the drop, delegate to that DropTarget. final int[] cellXY = mTempCell; + int localDragPointX = dragPointX - (currentLayout.getLeft() - mScrollX); + int localDragPointY = dragPointY - (currentLayout.getTop() - mScrollY); currentLayout.estimateDropCell(dragPointX, dragPointY, item.spanX, item.spanY, cellXY); View child = currentLayout.getChildAt(cellXY[0], cellXY[1]); if (child instanceof DropTarget) { @@ -986,8 +1025,10 @@ public class Workspace extends SmoothPagedView if ((!LauncherApplication.isScreenXLarge() || source == this) && mDragTargetLayout != null) { final View child = (mDragInfo == null) ? null : mDragInfo.cell; + int localOriginX = originX - (mDragTargetLayout.getLeft() - mScrollX); + int localOriginY = originY - (mDragTargetLayout.getTop() - mScrollY); mDragTargetLayout.visualizeDropLocation( - child, originX, originY, item.spanX, item.spanY); + child, localOriginX, localOriginY, item.spanX, item.spanY); } } @@ -1143,7 +1184,9 @@ public class Workspace extends SmoothPagedView int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) { final int[] cellXY = mTempCell; - layout.estimateDropCell(pixelX, pixelY, spanX, spanY, cellXY); + int localPixelX = pixelX - (layout.getLeft() - mScrollX); + int localPixelY = pixelY - (layout.getTop() - mScrollY); + layout.estimateDropCell(localPixelX, localPixelY, spanX, spanY, cellXY); layout.cellToPoint(cellXY[0], cellXY[1], mTempEstimate); final CellLayout.CellInfo cellInfo = layout.updateOccupiedCells(null, ignoreView); -- cgit v1.2.3