Skip to content

Commit e364313

Browse files
author
Adam Cohen
committed
Implementing new slider / widget interaction where frame goes around the widget
-> Frame resizes dynamically as the security slides -> Widget shrinks immediately as the handle begins being brought up -> Widget grows only upon security settling in the down position -> Cleaned up a lot of state interaction between the security slider and the widget pager / pages -> Loosened long press slop (was using Euclidean distance by accident instead of x crossed or y crossed logic) Change-Id: Ic52b62e577c539327b0a65c9277300fc626cf190
1 parent b317db4 commit e364313

File tree

6 files changed

+165
-53
lines changed

6 files changed

+165
-53
lines changed

policy/src/com/android/internal/policy/impl/keyguard/CheckLongPressHelper.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,10 @@ public void postCheckForLongPress(MotionEvent ev) {
6060
public void onMove(MotionEvent ev) {
6161
float x = ev.getX();
6262
float y = ev.getY();
63+
boolean xMoved = Math.abs(mDownX - x) > mScaledTouchSlop;
64+
boolean yMoved = Math.abs(mDownY - y) > mScaledTouchSlop;
6365

64-
if (Math.sqrt(Math.pow(mDownX - x, 2) + Math.pow(mDownY - y, 2)) > mScaledTouchSlop) {
66+
if (xMoved || yMoved) {
6567
cancelLongPress();
6668
}
6769
}
@@ -77,4 +79,4 @@ public void cancelLongPress() {
7779
public boolean hasPerformedLongPress() {
7880
return mHasPerformedLongPress;
7981
}
80-
}
82+
}

policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java

Lines changed: 67 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChallengeScrolledListener {
2323

2424
private KeyguardWidgetPager mPagedView;
25-
private int mCurrentPageIndex;
2625
private ChallengeLayout mChallengeLayout;
2726
private Runnable mHideHintsRunnable;
2827
private KeyguardSecurityView mKeyguardSecurityContainer;
@@ -31,6 +30,12 @@ public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChalle
3130
private static final int SCREEN_ON_RING_HINT_DELAY = 300;
3231
Handler mMainQueue = new Handler(Looper.myLooper());
3332

33+
int mLastScrollState = SlidingChallengeLayout.SCROLL_STATE_IDLE;
34+
35+
// Paged view state
36+
private int mPageListeningToSlider = -1;
37+
private int mCurrentPage = -1;
38+
3439
int mChallengeTop = 0;
3540

3641
public KeyguardViewStateManager() {
@@ -66,28 +71,39 @@ public void showBouncer(boolean show) {
6671
}
6772

6873
public void onPageSwitch(View newPage, int newPageIndex) {
69-
// Reset the previous page size and ensure the current page is sized appropriately
70-
if (mPagedView != null) {
71-
KeyguardWidgetFrame oldPage = mPagedView.getWidgetPageAt(mCurrentPageIndex);
72-
// Reset the old widget page to full size
73-
if (oldPage != null) {
74-
oldPage.resetSize();
74+
// Reset the previous page size and ensure the current page is sized appropriately.
75+
// We only modify the page state if it is not currently under control by the slider.
76+
// This prevents conflicts.
77+
if (mPagedView != null && mChallengeLayout != null) {
78+
KeyguardWidgetFrame prevPage = mPagedView.getWidgetPageAt(mCurrentPage);
79+
if (prevPage != null && mCurrentPage != mPageListeningToSlider) {
80+
prevPage.resetSize();
7581
}
7682

7783
KeyguardWidgetFrame newCurPage = mPagedView.getWidgetPageAt(newPageIndex);
78-
if (mChallengeLayout.isChallengeOverlapping()) {
79-
sizeWidgetFrameToChallengeTop(newCurPage);
84+
boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
85+
if (challengeOverlapping && !newCurPage.isSmall()
86+
&& mPageListeningToSlider != newPageIndex) {
87+
shrinkWidget(newCurPage);
8088
}
8189
}
82-
mCurrentPageIndex = newPageIndex;
90+
mCurrentPage = newPageIndex;
8391
}
8492

85-
private void sizeWidgetFrameToChallengeTop(KeyguardWidgetFrame frame) {
86-
if (frame == null) return;
93+
private int getChallengeTopRelativeToFrame(KeyguardWidgetFrame frame, int top) {
8794
mTmpPoint[0] = 0;
88-
mTmpPoint[1] = mChallengeTop;
95+
mTmpPoint[1] = top;
8996
mapPoint((View) mChallengeLayout, frame, mTmpPoint);
90-
frame.setChallengeTop(mTmpPoint[1]);
97+
return mTmpPoint[1];
98+
}
99+
100+
private void shrinkWidget(KeyguardWidgetFrame frame) {
101+
if (frame != null && mChallengeLayout != null &&
102+
mChallengeLayout instanceof SlidingChallengeLayout) {
103+
SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
104+
int top = scl.getMaxChallengeTop();
105+
frame.shrinkWidget(getChallengeTopRelativeToFrame(frame, top));
106+
}
91107
}
92108

93109
/**
@@ -114,20 +130,17 @@ public void mapPoint(View fromView, View toView, int pt[]) {
114130

115131
@Override
116132
public void onScrollStateChanged(int scrollState) {
133+
if (mPagedView == null || mChallengeLayout == null) return;
134+
boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
135+
117136
if (scrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
118-
if (mPagedView == null) return;
137+
KeyguardWidgetFrame frame = mPagedView.getWidgetPageAt(mPageListeningToSlider);
138+
if (frame == null) return;
119139

120-
boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
121-
int curPage = mPagedView.getCurrentPage();
122-
KeyguardWidgetFrame frame = mPagedView.getWidgetPageAt(curPage);
123-
124-
if (frame != null) {
125-
if (!challengeOverlapping) {
126-
frame.resetSize();
127-
} else {
128-
sizeWidgetFrameToChallengeTop(frame);
129-
}
140+
if (!challengeOverlapping) {
141+
frame.resetSize();
130142
}
143+
frame.hideFrame(this);
131144

132145
if (challengeOverlapping) {
133146
mPagedView.setOnlyAllowEdgeSwipes(true);
@@ -140,10 +153,38 @@ public void onScrollStateChanged(int scrollState) {
140153
} else {
141154
mKeyguardSecurityContainer.onPause();
142155
}
143-
} else {
156+
mPageListeningToSlider = -1;
157+
} else if (mLastScrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
158+
// Whether dragging or settling, if the last state was idle, we use this signal
159+
// to update the current page who will receive events from the sliding challenge.
160+
// We resize the frame as appropriate.
161+
mPageListeningToSlider = mPagedView.getNextPage();
162+
KeyguardWidgetFrame frame = mPagedView.getWidgetPageAt(mPageListeningToSlider);
163+
if (frame == null) return;
164+
165+
frame.showFrame(this);
166+
167+
// As soon as the security begins sliding, the widget becomes small (if it wasn't
168+
// small to begin with).
169+
if (!frame.isSmall()) {
170+
// We need to fetch the final page, in case the pages are in motion.
171+
mPageListeningToSlider = mPagedView.getNextPage();
172+
System.out.println("Shrink widget from scroll state changed!");
173+
shrinkWidget(frame);
174+
}
144175
// View is on the move. Pause the security view until it completes.
145176
mKeyguardSecurityContainer.onPause();
146177
}
178+
mLastScrollState = scrollState;
179+
}
180+
181+
@Override
182+
public void onScrollPositionChanged(float scrollPosition, int challengeTop) {
183+
mChallengeTop = challengeTop;
184+
KeyguardWidgetFrame frame = mPagedView.getWidgetPageAt(mPageListeningToSlider);
185+
if (frame != null) {
186+
frame.adjustFrame(getChallengeTopRelativeToFrame(frame, mChallengeTop));
187+
}
147188
}
148189

149190
public void showUsabilityHints() {
@@ -164,10 +205,4 @@ public void run() {
164205

165206
mMainQueue.postDelayed(mHideHintsRunnable, SCREEN_ON_HINT_DURATION);
166207
}
167-
168-
@Override
169-
public void onScrollPositionChanged(float scrollPosition, int challengeTop) {
170-
mChallengeTop = challengeTop;
171-
}
172-
173208
}

policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java

Lines changed: 78 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
package com.android.internal.policy.impl.keyguard;
1818

19+
import android.animation.Animator;
20+
import android.animation.ObjectAnimator;
21+
import android.animation.PropertyValuesHolder;
1922
import android.appwidget.AppWidgetHostView;
2023
import android.content.Context;
2124
import android.content.res.Resources;
@@ -49,13 +52,20 @@ public class KeyguardWidgetFrame extends FrameLayout {
4952
private final Rect mForegroundRect = new Rect();
5053
private int mForegroundAlpha = 0;
5154
private CheckLongPressHelper mLongPressHelper;
55+
private Animator mFrameFade;
56+
private boolean mIsSmall = false;
5257

5358
private float mBackgroundAlpha;
5459
private float mContentAlpha;
5560
private float mBackgroundAlphaMultiplier = 1.0f;
5661
private Drawable mBackgroundDrawable;
5762
private Rect mBackgroundRect = new Rect();
5863

64+
// Multiple callers may try and adjust the alpha of the frame. When a caller shows
65+
// the outlines, we give that caller control, and nobody else can fade them out.
66+
// This prevents animation conflicts.
67+
private Object mBgAlphaController;
68+
5969
public KeyguardWidgetFrame(Context context) {
6070
this(context, null, 0);
6171
}
@@ -80,6 +90,11 @@ public KeyguardWidgetFrame(Context context, AttributeSet attrs, int defStyle) {
8090
mGradientPaint.setXfermode(sAddBlendMode);
8191
}
8292

93+
@Override
94+
protected void onDetachedFromWindow() {
95+
cancelLongPress();
96+
}
97+
8398
@Override
8499
public boolean onInterceptTouchEvent(MotionEvent ev) {
85100
// Watch for longpress events at this level to make sure
@@ -237,12 +252,29 @@ public void setContentAlpha(float alpha) {
237252
}
238253
}
239254

255+
/**
256+
* Set the top location of the challenge.
257+
*
258+
* @param top The top of the challenge, in _local_ coordinates, or -1 to indicate the challenge
259+
* is down.
260+
*/
261+
private void setChallengeTop(int top, boolean updateWidgetSize) {
262+
// The widget starts below the padding, and extends to the top of the challengs.
263+
int widgetHeight = top - getPaddingTop();
264+
int frameHeight = top + getPaddingBottom();
265+
setFrameHeight(frameHeight);
266+
if (updateWidgetSize) {
267+
setWidgetHeight(widgetHeight);
268+
}
269+
}
270+
240271
/**
241272
* Depending on whether the security is up, the widget size needs to change
242273
*
243274
* @param height The height of the widget, -1 for full height
244275
*/
245-
public void setWidgetHeight(int height) {
276+
private void setWidgetHeight(int height) {
277+
System.out.println("Set widget height: " + this + " : " + height);
246278
boolean needLayout = false;
247279
View widget = getContent();
248280
if (widget != null) {
@@ -257,22 +289,56 @@ public void setWidgetHeight(int height) {
257289
}
258290
}
259291

260-
/**
261-
* Set the top location of the challenge.
262-
*
263-
* @param top The top of the challenge, in _local_ coordinates, or -1 to indicate the challenge
264-
* is down.
265-
*/
266-
public void setChallengeTop(int top) {
267-
// The widget starts below the padding, and extends to the top of the challengs.
268-
int widgetHeight = top - getPaddingTop();
269-
setWidgetHeight(widgetHeight);
292+
public boolean isSmall() {
293+
return mIsSmall;
294+
}
295+
296+
public void adjustFrame(int challengeTop) {
297+
setChallengeTop(challengeTop, false);
298+
}
299+
300+
public void shrinkWidget(int challengeTop) {
301+
mIsSmall = true;
302+
setChallengeTop(challengeTop, true);
270303
}
271304

272305
public void resetSize() {
306+
mIsSmall = false;
307+
setFrameHeight(getMeasuredHeight());
273308
setWidgetHeight(LayoutParams.MATCH_PARENT);
274309
}
275310

311+
public void setFrameHeight(int height) {
312+
height = Math.min(height, getMeasuredHeight());
313+
mBackgroundRect.set(0, 0, getMeasuredWidth(), height);
314+
invalidate();
315+
}
316+
317+
public void hideFrame(Object caller) {
318+
fadeFrame(caller, false, 0f, 150);
319+
}
320+
321+
public void showFrame(Object caller) {
322+
fadeFrame(caller, true, 1f, 150);
323+
}
324+
325+
public void fadeFrame(Object caller, boolean takeControl, float alpha, int duration) {
326+
if (takeControl) {
327+
mBgAlphaController = caller;
328+
}
329+
330+
if (mBgAlphaController != caller) return;
331+
332+
if (mFrameFade != null) {
333+
mFrameFade.cancel();
334+
mFrameFade = null;
335+
}
336+
PropertyValuesHolder bgAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", alpha);
337+
mFrameFade = ObjectAnimator.ofPropertyValuesHolder(this, bgAlpha);
338+
mFrameFade.setDuration(duration);
339+
mFrameFade.start();
340+
}
341+
276342
@Override
277343
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
278344
super.onSizeChanged(w, h, oldw, oldh);
@@ -285,6 +351,7 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
285351
mRightToLeftGradient = new LinearGradient(x1, 0f, x0, 0f,
286352
mGradientColor, 0, Shader.TileMode.CLAMP);
287353
mBackgroundRect.set(0, 0, w, h);
354+
invalidate();
288355
}
289356

290357
void setOverScrollAmount(float r, boolean left) {

policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -433,9 +433,11 @@ void animateOutlinesAndSidePages(final boolean show) {
433433

434434
int count = getChildCount();
435435
PropertyValuesHolder alpha;
436-
PropertyValuesHolder outlineAlpha;
437436
ArrayList<Animator> anims = new ArrayList<Animator>();
438437

438+
int duration = show ? CHILDREN_OUTLINE_FADE_IN_DURATION :
439+
CHILDREN_OUTLINE_FADE_OUT_DURATION;
440+
439441
int curPage = getNextPage();
440442
for (int i = 0; i < count; i++) {
441443
float finalContentAlpha;
@@ -446,16 +448,15 @@ void animateOutlinesAndSidePages(final boolean show) {
446448
} else {
447449
finalContentAlpha = 0f;
448450
}
449-
float finalOutlineAlpha = show ? getAlphaForPage(mScreenCenter, i) : 0f;
450451
KeyguardWidgetFrame child = getWidgetPageAt(i);
451452
alpha = PropertyValuesHolder.ofFloat("contentAlpha", finalContentAlpha);
452-
outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha",finalOutlineAlpha);
453-
ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha);
453+
ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha);
454454
anims.add(a);
455+
456+
float finalOutlineAlpha = show ? getAlphaForPage(mScreenCenter, i) : 0f;
457+
child.fadeFrame(this, show, finalOutlineAlpha, duration);
455458
}
456459

457-
int duration = show ? CHILDREN_OUTLINE_FADE_IN_DURATION :
458-
CHILDREN_OUTLINE_FADE_OUT_DURATION;
459460
mChildrenOutlineFadeAnimation = new AnimatorSet();
460461
mChildrenOutlineFadeAnimation.playTogether(anims);
461462

policy/src/com/android/internal/policy/impl/keyguard/MultiPaneChallengeLayout.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import android.content.res.TypedArray;
2121
import android.graphics.Rect;
2222
import android.util.AttributeSet;
23-
import android.util.Log;
2423
import android.view.Gravity;
2524
import android.view.View;
2625
import android.view.ViewGroup;

policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ void setScrollState(int state) {
374374
mScrollState = state;
375375

376376
animateHandle(state == SCROLL_STATE_IDLE && !mChallengeShowing);
377-
animateFrame(state != SCROLL_STATE_IDLE, false);
377+
animateFrame(false , false);
378378
if (mScrollListener != null) {
379379
mScrollListener.onScrollStateChanged(state);
380380
}
@@ -845,6 +845,14 @@ public void draw(Canvas c) {
845845
}
846846
}
847847

848+
public int getMaxChallengeTop() {
849+
if (mChallengeView == null) return 0;
850+
851+
final int layoutBottom = getLayoutBottom();
852+
final int challengeHeight = mChallengeView.getHeight();
853+
return layoutBottom - challengeHeight;
854+
}
855+
848856
/**
849857
* Move the bottom edge of mChallengeView to a new position and notify the listener
850858
* if it represents a change in position. Changes made through this method will

0 commit comments

Comments
 (0)