diff options
author | Jim Miller <jaggies@google.com> | 2013-09-10 18:37:01 -0700 |
---|---|---|
committer | Jim Miller <jaggies@google.com> | 2013-09-19 17:14:59 -0700 |
commit | caf24fc2c4bb9747eb80138bf3ce0be067851749 (patch) | |
tree | a81859dd75a9ca17e752c32f1ecf0b40a62df1bd /packages/Keyguard/src/com/android | |
parent | f429247867ac524cf63bc01499ac47a90ebcaca9 (diff) | |
download | frameworks_base-caf24fc2c4bb9747eb80138bf3ce0be067851749.zip frameworks_base-caf24fc2c4bb9747eb80138bf3ce0be067851749.tar.gz frameworks_base-caf24fc2c4bb9747eb80138bf3ce0be067851749.tar.bz2 |
Add camera affordance to navigation bar on phones
This adds a camera button on phones that can be used to show
and launch the camera.
- Minor refactoring of touch event dispatch in PagedView.
- Disables usability hints when keyguard loads.
- Only add a touch handler for camera icon once during layout.
- Update after review.
- Updated with latest UX camera and camera background assets
Change-Id: I09cd5cb0e501fd0f4659bea96d00c92b07f805c4
Diffstat (limited to 'packages/Keyguard/src/com/android')
7 files changed, 230 insertions, 70 deletions
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java index fbe3a9c..0787286 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java @@ -1650,4 +1650,9 @@ public class KeyguardHostView extends KeyguardViewBase { mActivityLauncher.launchActivityWithAnimation( intent, false, opts.toBundle(), null, null); } + + public void dispatch(MotionEvent event) { + mAppWidgetContainer.handleExternalCameraEvent(event); + } + } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java b/packages/Keyguard/src/com/android/keyguard/KeyguardService.java index a70e5bd..77006c5 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardService.java @@ -28,6 +28,7 @@ import android.os.Bundle; import android.os.Debug; import android.os.IBinder; import android.util.Log; +import android.view.MotionEvent; import com.android.internal.policy.IKeyguardService; import com.android.internal.policy.IKeyguardExitCallback; @@ -132,6 +133,10 @@ public class KeyguardService extends Service { checkPermission(); mKeyguardViewMediator.showAssistant(); } + public void dispatch(MotionEvent event) { + checkPermission(); + mKeyguardViewMediator.dispatch(event); + } }; } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java index 35bea26..4837458 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java @@ -38,6 +38,7 @@ import android.util.Slog; import android.util.SparseArray; import android.view.KeyEvent; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewManager; @@ -425,4 +426,10 @@ public class KeyguardViewManager { mKeyguardView.showAssistant(); } } + + public void dispatch(MotionEvent event) { + if (mKeyguardView != null) { + mKeyguardView.dispatch(event); + } + } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java index e746f72..478096c 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java @@ -49,6 +49,7 @@ import android.util.EventLog; import android.util.Log; import android.util.Slog; import android.view.KeyEvent; +import android.view.MotionEvent; import android.view.WindowManager; import android.view.WindowManagerPolicy; @@ -120,6 +121,7 @@ public class KeyguardViewMediator { private static final int SET_HIDDEN = 12; private static final int KEYGUARD_TIMEOUT = 13; private static final int SHOW_ASSISTANT = 14; + private static final int DISPATCH_EVENT = 15; /** * The default amount of time we stay awake (used for all key input) @@ -1066,6 +1068,9 @@ public class KeyguardViewMediator { case SHOW_ASSISTANT: handleShowAssistant(); break; + case DISPATCH_EVENT: + handleDispatchEvent((MotionEvent) msg.obj); + break; } } }; @@ -1102,6 +1107,10 @@ public class KeyguardViewMediator { sendUserPresentBroadcast(); } + protected void handleDispatchEvent(MotionEvent event) { + mKeyguardViewManager.dispatch(event); + } + private void sendUserPresentBroadcast() { final UserHandle currentUser = new UserHandle(mLockPatternUtils.getCurrentUser()); mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, currentUser); @@ -1327,4 +1336,9 @@ public class KeyguardViewMediator { public static MultiUserAvatarCache getAvatarCache() { return sMultiUserAvatarCache; } + + public void dispatch(MotionEvent event) { + Message msg = mHandler.obtainMessage(DISPATCH_EVENT, event); + mHandler.sendMessage(msg); + } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java index e85f6df..0539e82 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java @@ -23,6 +23,7 @@ public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChallengeScrolledListener, ChallengeLayout.OnBouncerStateChangedListener { + private static final int WARP_FADE_DURATION = 250; private KeyguardWidgetPager mKeyguardWidgetPager; private ChallengeLayout mChallengeLayout; private KeyguardHostView mKeyguardHostView; @@ -32,6 +33,7 @@ public class KeyguardViewStateManager implements private KeyguardSecurityView mKeyguardSecurityContainer; private static final int SCREEN_ON_HINT_DURATION = 1000; private static final int SCREEN_ON_RING_HINT_DELAY = 300; + private static final boolean SHOW_INITIAL_PAGE_HINTS = false; Handler mMainQueue = new Handler(Looper.myLooper()); int mLastScrollState = SlidingChallengeLayout.SCROLL_STATE_IDLE; @@ -167,6 +169,16 @@ public class KeyguardViewStateManager implements mCurrentPage = newPageIndex; } + public void onPageBeginWarp() { + // fadeOutSecurity(WARP_FADE_DURATION); + // mKeyguardWidgetPager.showNonWarpViews(WARP_FADE_DURATION, false); + } + + public void onPageEndWarp() { + // fadeInSecurity(WARP_FADE_DURATION); + // mKeyguardWidgetPager.showNonWarpViews(WARP_FADE_DURATION, true); + } + private int getChallengeTopRelativeToFrame(KeyguardWidgetFrame frame, int top) { mTmpPoint[0] = 0; mTmpPoint[1] = top; @@ -296,7 +308,9 @@ public class KeyguardViewStateManager implements mKeyguardSecurityContainer.showUsabilityHint(); } } , SCREEN_ON_RING_HINT_DELAY); - mKeyguardWidgetPager.showInitialPageHints(); + if (SHOW_INITIAL_PAGE_HINTS) { + mKeyguardWidgetPager.showInitialPageHints(); + } if (mHideHintsRunnable != null) { mMainQueue.postDelayed(mHideHintsRunnable, SCREEN_ON_HINT_DURATION); } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java index c566457..8d2f21b 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardWidgetPager.java @@ -186,6 +186,16 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit } @Override + public void onPageBeginWarp() { + mViewStateManager.onPageBeginWarp(); + } + + @Override + public void onPageEndWarp() { + mViewStateManager.onPageEndWarp(); + } + + @Override public void sendAccessibilityEvent(int eventType) { if (eventType != AccessibilityEvent.TYPE_VIEW_SCROLLED || isPageMoving()) { super.sendAccessibilityEvent(eventType); @@ -923,4 +933,27 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit return flags; } + + public void handleExternalCameraEvent(MotionEvent event) { + beginCameraEvent(); + int cameraPage = getPageCount() - 1; + boolean endWarp = false; + if (isCameraPage(cameraPage)) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + userActivity(); + startWarp(cameraPage); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + endWarp = true; + break; + } + dispatchTouchEvent(event); + // This has to happen after the event has been handled by the real widget pager + if (endWarp) endWarp(); + } + endCameraEvent(); + } + } diff --git a/packages/Keyguard/src/com/android/keyguard/PagedView.java b/packages/Keyguard/src/com/android/keyguard/PagedView.java index 881d14d..cbf7946 100644 --- a/packages/Keyguard/src/com/android/keyguard/PagedView.java +++ b/packages/Keyguard/src/com/android/keyguard/PagedView.java @@ -62,6 +62,7 @@ import java.util.ArrayList; public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarchyChangeListener { private static final String TAG = "WidgetPagedView"; private static final boolean DEBUG = false; + private static final boolean DEBUG_WARP = false; protected static final int INVALID_PAGE = -1; // the min drag distance for a fling to register, to prevent random page shifts @@ -130,6 +131,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc protected final static int TOUCH_STATE_REORDERING = 4; protected final static float ALPHA_QUANTIZE_LEVEL = 0.0001f; + protected final static float TOUCH_SLOP_SCALE = 1.0f; protected int mTouchState = TOUCH_STATE_REST; protected boolean mForceScreenScrolled = false; @@ -250,6 +252,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc // Bouncer private boolean mTopAlignPageWhenShrinkingForBouncer = false; + // Page warping + private int mPageSwapIndex = -1; + private boolean mIsCameraEvent; + public interface PageSwitchListener { void onPageSwitching(View newPage, int newPageIndex); void onPageSwitched(View newPage, int newPageIndex); @@ -469,15 +475,26 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } protected void pageBeginMoving() { + if (DEBUG_WARP) Log.v(TAG, "pageBeginMoving(" + mIsPageMoving + ")"); if (!mIsPageMoving) { mIsPageMoving = true; + if (mPageSwapIndex != -1) { + onPageBeginWarp(); + swapPages(mPageSwapIndex, getPageCount() - 1); + } onPageBeginMoving(); } } protected void pageEndMoving() { + if (DEBUG_WARP) Log.v(TAG, "pageEndMoving(" + mIsPageMoving + ")"); if (mIsPageMoving) { mIsPageMoving = false; + if (mPageSwapIndex != -1) { + swapPages(mPageSwapIndex, getPageCount() - 1); + onPageEndWarp(); + mPageSwapIndex = -1; + } onPageEndMoving(); } } @@ -737,6 +754,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc setHorizontalScrollBarEnabled(true); mFirstLayout = false; } + // If a page was swapped when we rebuilt the layout, swap it again now. + if (mPageSwapIndex != -1) { + if (DEBUG_WARP) Log.v(TAG, "onLayout: swapping pages"); + swapPages(mPageSwapIndex, getPageCount() - 1); + } } protected void screenScrolled(int screenCenter) { @@ -1071,7 +1093,9 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc * whether the user has moved far enough from his original down touch. */ if (mActivePointerId != INVALID_POINTER) { - determineScrollingStart(ev); + if (mIsCameraEvent || determineScrollingStart(ev)) { + startScrolling(ev); + } break; } // if mActivePointerId is INVALID_POINTER, then we must have missed an ACTION_DOWN @@ -1082,27 +1106,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } case MotionEvent.ACTION_DOWN: { - final float x = ev.getX(); - final float y = ev.getY(); - // Remember location of down touch - mDownMotionX = x; - mDownMotionY = y; - mDownScrollX = getScrollX(); - mLastMotionX = x; - mLastMotionY = y; - float[] p = mapPointFromViewToParent(this, x, y); - mParentDownMotionX = p[0]; - mParentDownMotionY = p[1]; - mLastMotionXRemainder = 0; - mTotalMotionX = 0; - mActivePointerId = ev.getPointerId(0); - - // Determine if the down event is within the threshold to be an edge swipe - int leftEdgeBoundary = getViewportOffsetX() + mEdgeSwipeRegionSize; - int rightEdgeBoundary = getMeasuredWidth() - getViewportOffsetX() - mEdgeSwipeRegionSize; - if ((mDownMotionX <= leftEdgeBoundary || mDownMotionX >= rightEdgeBoundary)) { - mDownEventOnEdge = true; - } + // Remember where the motion event started + saveDownState(ev); /* * If being flinged and user touches the screen, initiate drag; @@ -1112,25 +1117,29 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc final int xDist = Math.abs(mScroller.getFinalX() - mScroller.getCurrX()); final boolean finishedScrolling = (mScroller.isFinished() || xDist < mTouchSlop); if (finishedScrolling) { - mTouchState = TOUCH_STATE_REST; + setTouchState(TOUCH_STATE_REST); mScroller.abortAnimation(); } else { - if (isTouchPointInViewportWithBuffer((int) mDownMotionX, (int) mDownMotionY)) { - mTouchState = TOUCH_STATE_SCROLLING; + if (mIsCameraEvent || isTouchPointInViewportWithBuffer( + (int) mDownMotionX, (int) mDownMotionY)) { + setTouchState(TOUCH_STATE_SCROLLING); } else { - mTouchState = TOUCH_STATE_REST; + setTouchState(TOUCH_STATE_REST); } } // check if this can be the beginning of a tap on the side of the pages // to scroll the current page if (!DISABLE_TOUCH_SIDE_PAGES) { - if (mTouchState != TOUCH_STATE_PREV_PAGE && mTouchState != TOUCH_STATE_NEXT_PAGE) { + if (mTouchState != TOUCH_STATE_PREV_PAGE + && mTouchState != TOUCH_STATE_NEXT_PAGE) { if (getChildCount() > 0) { + float x = ev.getX(); + float y = ev.getY(); if (hitsPreviousPage(x, y)) { - mTouchState = TOUCH_STATE_PREV_PAGE; + setTouchState(TOUCH_STATE_PREV_PAGE); } else if (hitsNextPage(x, y)) { - mTouchState = TOUCH_STATE_NEXT_PAGE; + setTouchState(TOUCH_STATE_NEXT_PAGE); } } } @@ -1160,48 +1169,85 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc return mTouchState != TOUCH_STATE_REST; } - protected void determineScrollingStart(MotionEvent ev) { - determineScrollingStart(ev, 1.0f); + private void setTouchState(int touchState) { + if (mTouchState != touchState) { + onTouchStateChanged(touchState); + mTouchState = touchState; + } + } + + void onTouchStateChanged(int newTouchState) { + if (DEBUG) { + Log.v(TAG, "onTouchStateChanged(old="+ mTouchState + ", new=" + newTouchState + ")"); + } + } + + /** + * Save the state when we get {@link MotionEvent#ACTION_DOWN} + * @param ev + */ + private void saveDownState(MotionEvent ev) { + // Remember where the motion event started + mDownMotionX = mLastMotionX = ev.getX(); + mDownMotionY = mLastMotionY = ev.getY(); + mDownScrollX = getScrollX(); + float[] p = mapPointFromViewToParent(this, mLastMotionX, mLastMotionY); + mParentDownMotionX = p[0]; + mParentDownMotionY = p[1]; + mLastMotionXRemainder = 0; + mTotalMotionX = 0; + mActivePointerId = ev.getPointerId(0); + + // Determine if the down event is within the threshold to be an edge swipe + int leftEdgeBoundary = getViewportOffsetX() + mEdgeSwipeRegionSize; + int rightEdgeBoundary = getMeasuredWidth() - getViewportOffsetX() - mEdgeSwipeRegionSize; + if ((mDownMotionX <= leftEdgeBoundary || mDownMotionX >= rightEdgeBoundary)) { + mDownEventOnEdge = true; + } } /* * Determines if we should change the touch state to start scrolling after the * user moves their touch point too far. */ - protected void determineScrollingStart(MotionEvent ev, float touchSlopScale) { + protected boolean determineScrollingStart(MotionEvent ev) { // Disallow scrolling if we don't have a valid pointer index final int pointerIndex = ev.findPointerIndex(mActivePointerId); - if (pointerIndex == -1) return; + if (pointerIndex == -1) return false; // Disallow scrolling if we started the gesture from outside the viewport final float x = ev.getX(pointerIndex); final float y = ev.getY(pointerIndex); - if (!isTouchPointInViewportWithBuffer((int) x, (int) y)) return; + if (!isTouchPointInViewportWithBuffer((int) x, (int) y)) return false; // If we're only allowing edge swipes, we break out early if the down event wasn't // at the edge. - if (mOnlyAllowEdgeSwipes && !mDownEventOnEdge) return; + if (mOnlyAllowEdgeSwipes && !mDownEventOnEdge) return false; final int xDiff = (int) Math.abs(x - mLastMotionX); final int yDiff = (int) Math.abs(y - mLastMotionY); - final int touchSlop = Math.round(touchSlopScale * mTouchSlop); + final int touchSlop = Math.round(TOUCH_SLOP_SCALE * mTouchSlop); boolean xPaged = xDiff > mPagingTouchSlop; boolean xMoved = xDiff > touchSlop; boolean yMoved = yDiff > touchSlop; - if (xMoved || xPaged || yMoved) { - if (mUsePagingTouchSlop ? xPaged : xMoved) { - // Scroll if the user moved far enough along the X axis - mTouchState = TOUCH_STATE_SCROLLING; - mTotalMotionX += Math.abs(mLastMotionX - x); - mLastMotionX = x; - mLastMotionXRemainder = 0; - mTouchX = getViewportOffsetX() + getScrollX(); - mSmoothingTime = System.nanoTime() / NANOTIME_DIV; - pageBeginMoving(); - } - } + return (xMoved || xPaged || yMoved) && (mUsePagingTouchSlop ? xPaged : xMoved); + } + + private void startScrolling(MotionEvent ev) { + // Ignore if we don't have a valid pointer index + final int pointerIndex = ev.findPointerIndex(mActivePointerId); + if (pointerIndex == -1) return; + + final float x = ev.getX(pointerIndex); + setTouchState(TOUCH_STATE_SCROLLING); + mTotalMotionX += Math.abs(mLastMotionX - x); + mLastMotionX = x; + mLastMotionXRemainder = 0; + mTouchX = getViewportOffsetX() + getScrollX(); + mSmoothingTime = System.nanoTime() / NANOTIME_DIV; + pageBeginMoving(); } protected float getMaxScrollProgress() { @@ -1322,22 +1368,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } // Remember where the motion event started - mDownMotionX = mLastMotionX = ev.getX(); - mDownMotionY = mLastMotionY = ev.getY(); - mDownScrollX = getScrollX(); - float[] p = mapPointFromViewToParent(this, mLastMotionX, mLastMotionY); - mParentDownMotionX = p[0]; - mParentDownMotionY = p[1]; - mLastMotionXRemainder = 0; - mTotalMotionX = 0; - mActivePointerId = ev.getPointerId(0); - - // Determine if the down event is within the threshold to be an edge swipe - int leftEdgeBoundary = getViewportOffsetX() + mEdgeSwipeRegionSize; - int rightEdgeBoundary = getMeasuredWidth() - getViewportOffsetX() - mEdgeSwipeRegionSize; - if ((mDownMotionX <= leftEdgeBoundary || mDownMotionX >= rightEdgeBoundary)) { - mDownEventOnEdge = true; - } + saveDownState(ev); if (mTouchState == TOUCH_STATE_SCROLLING) { pageBeginMoving(); @@ -1479,8 +1510,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc removeCallbacks(mSidePageHoverRunnable); mSidePageHoverIndex = -1; } - } else { - determineScrollingStart(ev); + } else if (mIsCameraEvent || determineScrollingStart(ev)) { + startScrolling(ev); } break; @@ -1604,7 +1635,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc private void resetTouchState() { releaseVelocityTracker(); endReordering(); - mTouchState = TOUCH_STATE_REST; + setTouchState(TOUCH_STATE_REST); mActivePointerId = INVALID_POINTER; mDownEventOnEdge = false; } @@ -1821,8 +1852,17 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc protected void snapToPage(int whichPage, int delta, int duration) { snapToPage(whichPage, delta, duration, false); } + protected void snapToPage(int whichPage, int delta, int duration, boolean immediate) { - mNextPage = whichPage; + if (mPageSwapIndex != -1 && whichPage == mPageSwapIndex) { + // jump to the last page + mNextPage = getPageCount() - 1; + if (DEBUG_WARP) Log.v(TAG, "snapToPage(" + whichPage + ") : reset mPageSwapIndex"); + mPageSwapIndex = -1; + } else { + mNextPage = whichPage; + } + notifyPageSwitching(whichPage); View focusedChild = getFocusedChild(); if (focusedChild != null && whichPage != mCurrentPage && @@ -2102,7 +2142,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } // Set the touch state to reordering (allows snapping to pages, dragging a child, etc.) - mTouchState = TOUCH_STATE_REORDERING; + setTouchState(TOUCH_STATE_REORDERING); mIsReordering = true; // Mark all the non-widget pages as invisible @@ -2564,4 +2604,46 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc public boolean onHoverEvent(android.view.MotionEvent event) { return true; } + + void beginCameraEvent() { + mIsCameraEvent = true; + } + + void endCameraEvent() { + mIsCameraEvent = false; + } + + /** + * Swaps the position of the views by setting the left and right edges appropriately. + */ + void swapPages(int indexA, int indexB) { + View viewA = getPageAt(indexA); + View viewB = getPageAt(indexB); + if (viewA != viewB && viewA != null && viewB != null) { + int deltaX = viewA.getLeft() - viewB.getLeft(); + viewA.offsetLeftAndRight(-deltaX); + viewB.offsetLeftAndRight(deltaX); + } + } + + public void startWarp(int pageIndex) { + if (DEBUG_WARP) Log.v(TAG, "START WARP"); + if (pageIndex != mCurrentPage + 1) { + mPageSwapIndex = mCurrentPage + 1; + } + } + + public void endWarp() { + if (DEBUG_WARP) Log.v(TAG, "END WARP"); + // mPageSwapIndex is reset in snapToPage() after the scroll animation completes + } + + public void onPageBeginWarp() { + + } + + public void onPageEndWarp() { + + } + } |