Polish to 3d carousel and standard pager

-> updated assets
-> Always showing outlines as per new mock
-> Enabling layers on content during fades (still need to sort out layers for frames)
-> Added carousel overscroll as per discussion with danship
-> Fading side pages in carousel
-> other small polish

Change-Id: If88686768c621a65b175a74c07cb55a69321fd97
This commit is contained in:
Adam Cohen
2012-10-27 16:36:10 -07:00
parent 1d269e8e8f
commit f9048cd09b
11 changed files with 181 additions and 114 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 516 B

View File

@@ -1234,7 +1234,7 @@
<java-symbol type="drawable" name="magnified_region_frame" />
<java-symbol type="drawable" name="menu_background" />
<java-symbol type="drawable" name="stat_sys_secure" />
<java-symbol type="drawable" name="security_frame" />
<java-symbol type="drawable" name="kg_bouncer_bg_white" />
<java-symbol type="id" name="action_mode_bar_stub" />
<java-symbol type="id" name="alarm_status" />
<java-symbol type="id" name="backspace" />

View File

@@ -17,12 +17,14 @@ package com.android.internal.policy.impl.keyguard;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import com.android.internal.R;
public class KeyguardWidgetCarousel extends KeyguardWidgetPager {
private float mAdjacentPagesAngle;
private static float MAX_SCROLL_PROGRESS = 1.3f;
private static float CAMERA_DISTANCE = 10000;
public KeyguardWidgetCarousel(Context context, AttributeSet attrs) {
@@ -39,43 +41,73 @@ public class KeyguardWidgetCarousel extends KeyguardWidgetPager {
}
protected float getMaxScrollProgress() {
return 1.5f;
return MAX_SCROLL_PROGRESS;
}
public float getAlphaForPage(int screenCenter, int index) {
View child = getChildAt(index);
if (child == null) return 0f;
float scrollProgress = getScrollProgress(screenCenter, child, index);
if (!isOverScrollChild(index, scrollProgress)) {
scrollProgress = getBoundedScrollProgress(screenCenter, child, index);
float alpha = 1 - Math.abs(scrollProgress / MAX_SCROLL_PROGRESS);
return alpha;
} else {
return 1f;
}
}
private void updatePageAlphaValues(int screenCenter) {
boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
if (!isInOverscroll) {
if (mChildrenOutlineFadeAnimation != null) {
mChildrenOutlineFadeAnimation.cancel();
mChildrenOutlineFadeAnimation = null;
}
if (!isReordering(false)) {
for (int i = 0; i < getChildCount(); i++) {
KeyguardWidgetFrame child = getWidgetPageAt(i);
if (child != null) {
float scrollProgress = getScrollProgress(screenCenter, child, i);
if (!isReordering(false)) {
child.setBackgroundAlphaMultiplier(
backgroundAlphaInterpolator(Math.abs(scrollProgress)));
} else {
child.setBackgroundAlphaMultiplier(1f);
}
float alpha = getAlphaForPage(screenCenter, i);
child.setBackgroundAlpha(alpha);
child.setContentAlpha(alpha);
}
}
}
}
@Override
protected void screenScrolled(int screenCenter) {
mScreenCenter = screenCenter;
updatePageAlphaValues(screenCenter);
for (int i = 0; i < getChildCount(); i++) {
KeyguardWidgetFrame v = getWidgetPageAt(i);
if (v == mDragView) continue;
if (v != null) {
float scrollProgress = getScrollProgress(screenCenter, v, i);
float scrollProgress = getScrollProgress(screenCenter, v, i);
if (v == mDragView || v == null) continue;
v.setCameraDistance(CAMERA_DISTANCE);
if (isOverScrollChild(i, scrollProgress)) {
v.setRotationY(- OVERSCROLL_MAX_ROTATION * scrollProgress);
v.setOverScrollAmount(Math.abs(scrollProgress), scrollProgress < 0);
} else {
scrollProgress = getBoundedScrollProgress(screenCenter, v, i);
int width = v.getMeasuredWidth();
float pivotX = (width / 2f) + scrollProgress * (width / 2f);
float pivotY = v.getMeasuredHeight() / 2;
float rotationY = - mAdjacentPagesAngle * scrollProgress;
v.setCameraDistance(CAMERA_DISTANCE);
v.setPivotX(pivotX);
v.setPivotY(pivotY);
v.setRotationY(rotationY);
v.setOverScrollAmount(0f, false);
}
float alpha = v.getAlpha();
// If the view has 0 alpha, we set it to be invisible so as to prevent
// it from accepting touches
if (alpha == 0) {
v.setVisibility(INVISIBLE);
} else if (v.getVisibility() != VISIBLE) {
v.setVisibility(VISIBLE);
}
}
}

View File

@@ -51,6 +51,7 @@ public class KeyguardWidgetFrame extends FrameLayout {
private CheckLongPressHelper mLongPressHelper;
private float mBackgroundAlpha;
private float mContentAlpha;
private float mBackgroundAlphaMultiplier = 1.0f;
private Drawable mBackgroundDrawable;
private Rect mBackgroundRect = new Rect();
@@ -74,7 +75,7 @@ public class KeyguardWidgetFrame extends FrameLayout {
int padding = (int) (res.getDisplayMetrics().density * 8);
setPadding(padding, padding, padding, padding);
mBackgroundDrawable = res.getDrawable(R.drawable.security_frame);
mBackgroundDrawable = res.getDrawable(R.drawable.kg_bouncer_bg_white);
mGradientColor = res.getColor(com.android.internal.R.color.kg_widget_pager_gradient);
mGradientPaint.setXfermode(sAddBlendMode);
}
@@ -133,6 +134,23 @@ public class KeyguardWidgetFrame extends FrameLayout {
mLongPressHelper.cancelLongPress();
}
private void drawGradientOverlay(Canvas c) {
mGradientPaint.setShader(mForegroundGradient);
mGradientPaint.setAlpha(mForegroundAlpha);
c.drawRect(mForegroundRect, mGradientPaint);
}
protected void drawBg(Canvas canvas) {
if (mBackgroundAlpha > 0.0f) {
Drawable bg = mBackgroundDrawable;
bg.setAlpha((int) (mBackgroundAlpha * mBackgroundAlphaMultiplier * 255));
bg.setBounds(mBackgroundRect);
bg.draw(canvas);
}
}
@Override
protected void dispatchDraw(Canvas canvas) {
drawBg(canvas);
@@ -164,6 +182,14 @@ public class KeyguardWidgetFrame extends FrameLayout {
}
}
public void enableHardwareLayers() {
setLayerType(LAYER_TYPE_HARDWARE, null);
}
public void disableHardwareLayers() {
setLayerType(LAYER_TYPE_NONE, null);
}
public View getContent() {
return getChildAt(0);
}
@@ -177,28 +203,12 @@ public class KeyguardWidgetFrame extends FrameLayout {
}
}
private void drawGradientOverlay(Canvas c) {
mGradientPaint.setShader(mForegroundGradient);
mGradientPaint.setAlpha(mForegroundAlpha);
c.drawRect(mForegroundRect, mGradientPaint);
}
protected void drawBg(Canvas canvas) {
if (mBackgroundAlpha > 0.0f) {
Drawable bg = mBackgroundDrawable;
bg.setAlpha((int) (mBackgroundAlpha * mBackgroundAlphaMultiplier * 255));
bg.setBounds(mBackgroundRect);
bg.draw(canvas);
}
}
public float getBackgroundAlpha() {
return mBackgroundAlpha;
}
public void setBackgroundAlphaMultiplier(float multiplier) {
if (mBackgroundAlphaMultiplier != multiplier) {
if (Float.compare(mBackgroundAlphaMultiplier, multiplier) != 0) {
mBackgroundAlphaMultiplier = multiplier;
invalidate();
}
@@ -209,13 +219,18 @@ public class KeyguardWidgetFrame extends FrameLayout {
}
public void setBackgroundAlpha(float alpha) {
if (mBackgroundAlpha != alpha) {
if (Float.compare(mBackgroundAlpha, alpha) != 0) {
mBackgroundAlpha = alpha;
invalidate();
}
}
public float getContentAlpha() {
return mContentAlpha;
}
public void setContentAlpha(float alpha) {
mContentAlpha = alpha;
View content = getContent();
if (content != null) {
content.setAlpha(alpha);

View File

@@ -15,6 +15,9 @@
*/
package com.android.internal.policy.impl.keyguard;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
@@ -27,33 +30,32 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import com.android.internal.R;
import com.android.internal.widget.LockPatternUtils;
import java.util.ArrayList;
public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwitchListener,
OnLongClickListener {
ZInterpolator mZInterpolator = new ZInterpolator(0.5f);
private static float CAMERA_DISTANCE = 10000;
private static float TRANSITION_MAX_ROTATION = 30;
protected static float OVERSCROLL_MAX_ROTATION = 30;
private static final boolean PERFORM_OVERSCROLL_ROTATION = true;
private KeyguardViewStateManager mViewStateManager;
private LockPatternUtils mLockPatternUtils;
// Related to the fading in / out background outlines
private static final int CHILDREN_OUTLINE_FADE_OUT_DELAY = 0;
private static final int CHILDREN_OUTLINE_FADE_OUT_DURATION = 375;
private static final int CHILDREN_OUTLINE_FADE_IN_DURATION = 100;
private ObjectAnimator mChildrenOutlineFadeInAnimation;
private ObjectAnimator mChildrenOutlineFadeOutAnimation;
private static final int CHILDREN_OUTLINE_FADE_IN_DURATION = 75;
protected AnimatorSet mChildrenOutlineFadeAnimation;
private float mChildrenOutlineAlpha = 0;
private float mSidePagesAlpha = 1f;
protected int mScreenCenter;
private static final long CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT = 30000;
@@ -253,13 +255,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
@Override
protected void onPageBeginMoving() {
// Enable hardware layers while pages are moving
// TODO: We should only do this for the two views that are actually moving
int children = getChildCount();
for (int i = 0; i < children; i++) {
getWidgetPageAt(i).enableHardwareLayersForContent();
}
enablePageLayers();
if (mViewStateManager != null) {
mViewStateManager.onPageBeginMoving();
}
@@ -268,18 +264,26 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
@Override
protected void onPageEndMoving() {
// Disable hardware layers while pages are moving
int children = getChildCount();
for (int i = 0; i < children; i++) {
getWidgetPageAt(i).disableHardwareLayersForContent();
}
if (mViewStateManager != null) {
mViewStateManager.onPageEndMoving();
}
hideOutlinesAndSidePages();
}
private void enablePageLayers() {
int children = getChildCount();
for (int i = 0; i < children; i++) {
getWidgetPageAt(i).enableHardwareLayersForContent();
}
}
private void disablePageLayers() {
int children = getChildCount();
for (int i = 0; i < children; i++) {
getWidgetPageAt(i).disableHardwareLayersForContent();
}
}
/*
* This interpolator emulates the rate at which the perceived scale of an object changes
* as its distance from a camera increases. When this interpolator is applied to a scale
@@ -325,25 +329,21 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
}
private void updatePageAlphaValues(int screenCenter) {
}
public float getAlphaForPage(int screenCenter, int index) {
return 1f;
}
protected boolean isOverScrollChild(int index, float scrollProgress) {
boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
if (!isInOverscroll) {
for (int i = 0; i < getChildCount(); i++) {
KeyguardWidgetFrame child = getWidgetPageAt(i);
if (child != null) {
float scrollProgress = getScrollProgress(screenCenter, child, i);
if (!isReordering(false)) {
child.setBackgroundAlphaMultiplier(
backgroundAlphaInterpolator(Math.abs(scrollProgress)));
} else {
child.setBackgroundAlphaMultiplier(1f);
}
}
}
}
return (isInOverscroll && (index == 0 && scrollProgress < 0 ||
index == getChildCount() - 1 && scrollProgress > 0));
}
@Override
protected void screenScrolled(int screenCenter) {
mScreenCenter = screenCenter;
updatePageAlphaValues(screenCenter);
for (int i = 0; i < getChildCount(); i++) {
KeyguardWidgetFrame v = getWidgetPageAt(i);
@@ -351,30 +351,17 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
if (v != null) {
float scrollProgress = getScrollProgress(screenCenter, v, i);
float alpha = 1.0f;
v.setCameraDistance(mDensity * CAMERA_DISTANCE);
if (PERFORM_OVERSCROLL_ROTATION) {
if (i == 0 && scrollProgress < 0) {
// Over scroll to the left
v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
v.setOverScrollAmount(Math.abs(scrollProgress), true);
alpha = 1.0f;
// On the first page, we don't want the page to have any lateral motion
} else if (i == getChildCount() - 1 && scrollProgress > 0) {
// Over scroll to the right
v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
alpha = 1.0f;
v.setOverScrollAmount(Math.abs(scrollProgress), false);
// On the last page, we don't want the page to have any lateral motion.
} else {
v.setRotationY(0f);
v.setOverScrollAmount(0, false);
}
if (isOverScrollChild(i, scrollProgress) && PERFORM_OVERSCROLL_ROTATION) {
v.setRotationY(- OVERSCROLL_MAX_ROTATION * scrollProgress);
v.setOverScrollAmount(Math.abs(scrollProgress), scrollProgress < 0);
} else {
v.setRotationY(0f);
v.setOverScrollAmount(0, false);
}
v.setAlpha(alpha);
float alpha = v.getAlpha();
// If the view has 0 alpha, we set it to be invisible so as to prevent
// it from accepting touches
if (alpha == 0) {
@@ -385,6 +372,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
}
}
}
@Override
void boundByReorderablePages(boolean isReordering, int[] range) {
if (isReordering) {
@@ -418,7 +406,6 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
@Override
protected void onStartReordering() {
super.onStartReordering();
setChildrenOutlineMultiplier(1.0f);
showOutlinesAndSidePages();
}
@@ -429,43 +416,67 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
}
void showOutlinesAndSidePages() {
if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
animateOutlinesAndSidePages(true);
}
PropertyValuesHolder outlinesAlpha =
PropertyValuesHolder.ofFloat("childrenOutlineAlpha", 1.0f);
PropertyValuesHolder sidePagesAlpha = PropertyValuesHolder.ofFloat("sidePagesAlpha", 1.0f);
mChildrenOutlineFadeInAnimation =
ObjectAnimator.ofPropertyValuesHolder(this, outlinesAlpha, sidePagesAlpha);
mChildrenOutlineFadeInAnimation.setDuration(CHILDREN_OUTLINE_FADE_IN_DURATION);
mChildrenOutlineFadeInAnimation.start();
void hideOutlinesAndSidePages() {
animateOutlinesAndSidePages(false);
}
public void showInitialPageHints() {
// We start with everything showing
setChildrenOutlineAlpha(1.0f);
setSidePagesAlpha(1.0f);
setChildrenOutlineMultiplier(1.0f);
int currPage = getCurrentPage();
KeyguardWidgetFrame frame = getWidgetPageAt(currPage);
frame.setBackgroundAlphaMultiplier(0f);
frame.setBackgroundAlpha(0f);
}
void hideOutlinesAndSidePages() {
if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
void animateOutlinesAndSidePages(final boolean show) {
if (mChildrenOutlineFadeAnimation != null) {
mChildrenOutlineFadeAnimation.cancel();
mChildrenOutlineFadeAnimation = null;
}
PropertyValuesHolder outlinesAlpha =
PropertyValuesHolder.ofFloat("childrenOutlineAlpha", 0f);
PropertyValuesHolder sidePagesAlpha = PropertyValuesHolder.ofFloat("sidePagesAlpha", 0f);
mChildrenOutlineFadeOutAnimation =
ObjectAnimator.ofPropertyValuesHolder(this, outlinesAlpha, sidePagesAlpha);
int count = getChildCount();
PropertyValuesHolder alpha;
PropertyValuesHolder outlineAlpha;
ArrayList<Animator> anims = new ArrayList<Animator>();
mChildrenOutlineFadeOutAnimation.setDuration(CHILDREN_OUTLINE_FADE_OUT_DURATION);
mChildrenOutlineFadeOutAnimation.setStartDelay(CHILDREN_OUTLINE_FADE_OUT_DELAY);
mChildrenOutlineFadeOutAnimation.start();
int curPage = getNextPage();
for (int i = 0; i < count; i++) {
float finalContentAlpha;
if (show) {
finalContentAlpha = getAlphaForPage(mScreenCenter, i);
} else if (!show && i == curPage) {
finalContentAlpha = 1f;
} else {
finalContentAlpha = 0f;
}
float finalOutlineAlpha = show ? getAlphaForPage(mScreenCenter, i) : 0f;
KeyguardWidgetFrame child = getWidgetPageAt(i);
alpha = PropertyValuesHolder.ofFloat("contentAlpha", finalContentAlpha);
outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha",finalOutlineAlpha);
ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha);
anims.add(a);
}
int duration = show ? CHILDREN_OUTLINE_FADE_IN_DURATION :
CHILDREN_OUTLINE_FADE_OUT_DURATION;
mChildrenOutlineFadeAnimation = new AnimatorSet();
mChildrenOutlineFadeAnimation.playTogether(anims);
mChildrenOutlineFadeAnimation.setDuration(duration);
mChildrenOutlineFadeAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (!show) {
disablePageLayers();
}
}
});
mChildrenOutlineFadeAnimation.start();
}
public void setChildrenOutlineAlpha(float alpha) {

View File

@@ -201,8 +201,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
// We use the min scale to determine how much to expand the actually PagedView measured
// dimensions such that when we are zoomed out, the view is not clipped
private int REORDERING_DROP_REPOSITION_DURATION = 200;
private int REORDERING_REORDER_REPOSITION_DURATION = 350;
private int REORDERING_ZOOM_IN_OUT_DURATION = 250;
protected int REORDERING_REORDER_REPOSITION_DURATION = 350;
protected int REORDERING_ZOOM_IN_OUT_DURATION = 250;
private int REORDERING_SIDE_PAGE_HOVER_TIMEOUT = 500;
private float REORDERING_SIDE_PAGE_BUFFER_PERCENTAGE = 0.1f;
private float mMinScale = 1f;
@@ -1162,6 +1162,15 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
return 1.0f;
}
protected float getBoundedScrollProgress(int screenCenter, View v, int page) {
final int halfScreenSize = getViewportWidth() / 2;
screenCenter = Math.min(mScrollX + halfScreenSize, screenCenter);
screenCenter = Math.max(halfScreenSize, screenCenter);
return getScrollProgress(screenCenter, v, page);
}
protected float getScrollProgress(int screenCenter, View v, int page) {
final int halfScreenSize = getViewportWidth() / 2;