public void onMove(MotionEvent ev) {
float x = ev.getX();
float y = ev.getY();
+ boolean xMoved = Math.abs(mDownX - x) > mScaledTouchSlop;
+ boolean yMoved = Math.abs(mDownY - y) > mScaledTouchSlop;
- if (Math.sqrt(Math.pow(mDownX - x, 2) + Math.pow(mDownY - y, 2)) > mScaledTouchSlop) {
+ if (xMoved || yMoved) {
cancelLongPress();
}
}
public boolean hasPerformedLongPress() {
return mHasPerformedLongPress;
}
-}
\ No newline at end of file
+}
public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChallengeScrolledListener {
private KeyguardWidgetPager mPagedView;
- private int mCurrentPageIndex;
private ChallengeLayout mChallengeLayout;
private Runnable mHideHintsRunnable;
private KeyguardSecurityView mKeyguardSecurityContainer;
private static final int SCREEN_ON_RING_HINT_DELAY = 300;
Handler mMainQueue = new Handler(Looper.myLooper());
+ int mLastScrollState = SlidingChallengeLayout.SCROLL_STATE_IDLE;
+
+ // Paged view state
+ private int mPageListeningToSlider = -1;
+ private int mCurrentPage = -1;
+
int mChallengeTop = 0;
public KeyguardViewStateManager() {
}
public void onPageSwitch(View newPage, int newPageIndex) {
- // Reset the previous page size and ensure the current page is sized appropriately
- if (mPagedView != null) {
- KeyguardWidgetFrame oldPage = mPagedView.getWidgetPageAt(mCurrentPageIndex);
- // Reset the old widget page to full size
- if (oldPage != null) {
- oldPage.resetSize();
+ // Reset the previous page size and ensure the current page is sized appropriately.
+ // We only modify the page state if it is not currently under control by the slider.
+ // This prevents conflicts.
+ if (mPagedView != null && mChallengeLayout != null) {
+ KeyguardWidgetFrame prevPage = mPagedView.getWidgetPageAt(mCurrentPage);
+ if (prevPage != null && mCurrentPage != mPageListeningToSlider) {
+ prevPage.resetSize();
}
KeyguardWidgetFrame newCurPage = mPagedView.getWidgetPageAt(newPageIndex);
- if (mChallengeLayout.isChallengeOverlapping()) {
- sizeWidgetFrameToChallengeTop(newCurPage);
+ boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
+ if (challengeOverlapping && !newCurPage.isSmall()
+ && mPageListeningToSlider != newPageIndex) {
+ shrinkWidget(newCurPage);
}
}
- mCurrentPageIndex = newPageIndex;
+ mCurrentPage = newPageIndex;
}
- private void sizeWidgetFrameToChallengeTop(KeyguardWidgetFrame frame) {
- if (frame == null) return;
+ private int getChallengeTopRelativeToFrame(KeyguardWidgetFrame frame, int top) {
mTmpPoint[0] = 0;
- mTmpPoint[1] = mChallengeTop;
+ mTmpPoint[1] = top;
mapPoint((View) mChallengeLayout, frame, mTmpPoint);
- frame.setChallengeTop(mTmpPoint[1]);
+ return mTmpPoint[1];
+ }
+
+ private void shrinkWidget(KeyguardWidgetFrame frame) {
+ if (frame != null && mChallengeLayout != null &&
+ mChallengeLayout instanceof SlidingChallengeLayout) {
+ SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
+ int top = scl.getMaxChallengeTop();
+ frame.shrinkWidget(getChallengeTopRelativeToFrame(frame, top));
+ }
}
/**
@Override
public void onScrollStateChanged(int scrollState) {
+ if (mPagedView == null || mChallengeLayout == null) return;
+ boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
+
if (scrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
- if (mPagedView == null) return;
+ KeyguardWidgetFrame frame = mPagedView.getWidgetPageAt(mPageListeningToSlider);
+ if (frame == null) return;
- boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
- int curPage = mPagedView.getCurrentPage();
- KeyguardWidgetFrame frame = mPagedView.getWidgetPageAt(curPage);
-
- if (frame != null) {
- if (!challengeOverlapping) {
- frame.resetSize();
- } else {
- sizeWidgetFrameToChallengeTop(frame);
- }
+ if (!challengeOverlapping) {
+ frame.resetSize();
}
+ frame.hideFrame(this);
if (challengeOverlapping) {
mPagedView.setOnlyAllowEdgeSwipes(true);
} else {
mKeyguardSecurityContainer.onPause();
}
- } else {
+ mPageListeningToSlider = -1;
+ } else if (mLastScrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
+ // Whether dragging or settling, if the last state was idle, we use this signal
+ // to update the current page who will receive events from the sliding challenge.
+ // We resize the frame as appropriate.
+ mPageListeningToSlider = mPagedView.getNextPage();
+ KeyguardWidgetFrame frame = mPagedView.getWidgetPageAt(mPageListeningToSlider);
+ if (frame == null) return;
+
+ frame.showFrame(this);
+
+ // As soon as the security begins sliding, the widget becomes small (if it wasn't
+ // small to begin with).
+ if (!frame.isSmall()) {
+ // We need to fetch the final page, in case the pages are in motion.
+ mPageListeningToSlider = mPagedView.getNextPage();
+ System.out.println("Shrink widget from scroll state changed!");
+ shrinkWidget(frame);
+ }
// View is on the move. Pause the security view until it completes.
mKeyguardSecurityContainer.onPause();
}
+ mLastScrollState = scrollState;
+ }
+
+ @Override
+ public void onScrollPositionChanged(float scrollPosition, int challengeTop) {
+ mChallengeTop = challengeTop;
+ KeyguardWidgetFrame frame = mPagedView.getWidgetPageAt(mPageListeningToSlider);
+ if (frame != null) {
+ frame.adjustFrame(getChallengeTopRelativeToFrame(frame, mChallengeTop));
+ }
}
public void showUsabilityHints() {
mMainQueue.postDelayed(mHideHintsRunnable, SCREEN_ON_HINT_DURATION);
}
-
- @Override
- public void onScrollPositionChanged(float scrollPosition, int challengeTop) {
- mChallengeTop = challengeTop;
- }
-
}
package com.android.internal.policy.impl.keyguard;
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
import android.appwidget.AppWidgetHostView;
import android.content.Context;
import android.content.res.Resources;
private final Rect mForegroundRect = new Rect();
private int mForegroundAlpha = 0;
private CheckLongPressHelper mLongPressHelper;
+ private Animator mFrameFade;
+ private boolean mIsSmall = false;
private float mBackgroundAlpha;
private float mContentAlpha;
private Drawable mBackgroundDrawable;
private Rect mBackgroundRect = new Rect();
+ // Multiple callers may try and adjust the alpha of the frame. When a caller shows
+ // the outlines, we give that caller control, and nobody else can fade them out.
+ // This prevents animation conflicts.
+ private Object mBgAlphaController;
+
public KeyguardWidgetFrame(Context context) {
this(context, null, 0);
}
}
@Override
+ protected void onDetachedFromWindow() {
+ cancelLongPress();
+ }
+
+ @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// Watch for longpress events at this level to make sure
// users can always pick up this widget
}
/**
+ * Set the top location of the challenge.
+ *
+ * @param top The top of the challenge, in _local_ coordinates, or -1 to indicate the challenge
+ * is down.
+ */
+ private void setChallengeTop(int top, boolean updateWidgetSize) {
+ // The widget starts below the padding, and extends to the top of the challengs.
+ int widgetHeight = top - getPaddingTop();
+ int frameHeight = top + getPaddingBottom();
+ setFrameHeight(frameHeight);
+ if (updateWidgetSize) {
+ setWidgetHeight(widgetHeight);
+ }
+ }
+
+ /**
* Depending on whether the security is up, the widget size needs to change
*
* @param height The height of the widget, -1 for full height
*/
- public void setWidgetHeight(int height) {
+ private void setWidgetHeight(int height) {
+ System.out.println("Set widget height: " + this + " : " + height);
boolean needLayout = false;
View widget = getContent();
if (widget != null) {
}
}
- /**
- * Set the top location of the challenge.
- *
- * @param top The top of the challenge, in _local_ coordinates, or -1 to indicate the challenge
- * is down.
- */
- public void setChallengeTop(int top) {
- // The widget starts below the padding, and extends to the top of the challengs.
- int widgetHeight = top - getPaddingTop();
- setWidgetHeight(widgetHeight);
+ public boolean isSmall() {
+ return mIsSmall;
+ }
+
+ public void adjustFrame(int challengeTop) {
+ setChallengeTop(challengeTop, false);
+ }
+
+ public void shrinkWidget(int challengeTop) {
+ mIsSmall = true;
+ setChallengeTop(challengeTop, true);
}
public void resetSize() {
+ mIsSmall = false;
+ setFrameHeight(getMeasuredHeight());
setWidgetHeight(LayoutParams.MATCH_PARENT);
}
+ public void setFrameHeight(int height) {
+ height = Math.min(height, getMeasuredHeight());
+ mBackgroundRect.set(0, 0, getMeasuredWidth(), height);
+ invalidate();
+ }
+
+ public void hideFrame(Object caller) {
+ fadeFrame(caller, false, 0f, 150);
+ }
+
+ public void showFrame(Object caller) {
+ fadeFrame(caller, true, 1f, 150);
+ }
+
+ public void fadeFrame(Object caller, boolean takeControl, float alpha, int duration) {
+ if (takeControl) {
+ mBgAlphaController = caller;
+ }
+
+ if (mBgAlphaController != caller) return;
+
+ if (mFrameFade != null) {
+ mFrameFade.cancel();
+ mFrameFade = null;
+ }
+ PropertyValuesHolder bgAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", alpha);
+ mFrameFade = ObjectAnimator.ofPropertyValuesHolder(this, bgAlpha);
+ mFrameFade.setDuration(duration);
+ mFrameFade.start();
+ }
+
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mRightToLeftGradient = new LinearGradient(x1, 0f, x0, 0f,
mGradientColor, 0, Shader.TileMode.CLAMP);
mBackgroundRect.set(0, 0, w, h);
+ invalidate();
}
void setOverScrollAmount(float r, boolean left) {
int count = getChildCount();
PropertyValuesHolder alpha;
- PropertyValuesHolder outlineAlpha;
ArrayList<Animator> anims = new ArrayList<Animator>();
+ int duration = show ? CHILDREN_OUTLINE_FADE_IN_DURATION :
+ CHILDREN_OUTLINE_FADE_OUT_DURATION;
+
int curPage = getNextPage();
for (int i = 0; i < count; i++) {
float finalContentAlpha;
} 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);
+ ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha);
anims.add(a);
+
+ float finalOutlineAlpha = show ? getAlphaForPage(mScreenCenter, i) : 0f;
+ child.fadeFrame(this, show, finalOutlineAlpha, duration);
}
- int duration = show ? CHILDREN_OUTLINE_FADE_IN_DURATION :
- CHILDREN_OUTLINE_FADE_OUT_DURATION;
mChildrenOutlineFadeAnimation = new AnimatorSet();
mChildrenOutlineFadeAnimation.playTogether(anims);
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
mScrollState = state;
animateHandle(state == SCROLL_STATE_IDLE && !mChallengeShowing);
- animateFrame(state != SCROLL_STATE_IDLE, false);
+ animateFrame(false , false);
if (mScrollListener != null) {
mScrollListener.onScrollStateChanged(state);
}
}
}
+ public int getMaxChallengeTop() {
+ if (mChallengeView == null) return 0;
+
+ final int layoutBottom = getLayoutBottom();
+ final int challengeHeight = mChallengeView.getHeight();
+ return layoutBottom - challengeHeight;
+ }
+
/**
* Move the bottom edge of mChallengeView to a new position and notify the listener
* if it represents a change in position. Changes made through this method will