- Add simplified KeyguardHostView - Move common functions to KeyguardViewBase.java - Create new KeyguardSimpleHostView class for simplified view implementation. Bug 12135931 Change-Id: I8d6b0a61c36a0c7ceb87da4da54b1dfbed0054ff
362 lines
14 KiB
Java
362 lines
14 KiB
Java
/*
|
|
* Copyright (C) 2012 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.keyguard;
|
|
|
|
import android.animation.Animator;
|
|
import android.animation.Animator.AnimatorListener;
|
|
import android.animation.AnimatorListenerAdapter;
|
|
import android.os.Handler;
|
|
import android.os.Looper;
|
|
import android.view.View;
|
|
|
|
public class KeyguardViewStateManager implements
|
|
SlidingChallengeLayout.OnChallengeScrolledListener,
|
|
ChallengeLayout.OnBouncerStateChangedListener {
|
|
|
|
private static final String TAG = "KeyguardViewStateManager";
|
|
private KeyguardWidgetPager mKeyguardWidgetPager;
|
|
private ChallengeLayout mChallengeLayout;
|
|
private KeyguardHostView mKeyguardHostView;
|
|
private int[] mTmpPoint = new int[2];
|
|
private int[] mTmpLoc = new int[2];
|
|
|
|
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;
|
|
|
|
// Paged view state
|
|
private int mPageListeningToSlider = -1;
|
|
private int mCurrentPage = -1;
|
|
private int mPageIndexOnPageBeginMoving = -1;
|
|
|
|
int mChallengeTop = 0;
|
|
|
|
private final AnimatorListener mPauseListener = new AnimatorListenerAdapter() {
|
|
public void onAnimationEnd(Animator animation) {
|
|
mKeyguardSecurityContainer.onPause();
|
|
}
|
|
};
|
|
|
|
private final AnimatorListener mResumeListener = new AnimatorListenerAdapter() {
|
|
public void onAnimationEnd(Animator animation) {
|
|
if (((View)mKeyguardSecurityContainer).isShown()) {
|
|
mKeyguardSecurityContainer.onResume(0);
|
|
}
|
|
}
|
|
};
|
|
|
|
public KeyguardViewStateManager(KeyguardHostView hostView) {
|
|
mKeyguardHostView = hostView;
|
|
}
|
|
|
|
public void setPagedView(KeyguardWidgetPager pagedView) {
|
|
mKeyguardWidgetPager = pagedView;
|
|
updateEdgeSwiping();
|
|
}
|
|
|
|
public void setChallengeLayout(ChallengeLayout layout) {
|
|
mChallengeLayout = layout;
|
|
updateEdgeSwiping();
|
|
}
|
|
|
|
private void updateEdgeSwiping() {
|
|
if (mChallengeLayout != null && mKeyguardWidgetPager != null) {
|
|
if (mChallengeLayout.isChallengeOverlapping()) {
|
|
mKeyguardWidgetPager.setOnlyAllowEdgeSwipes(true);
|
|
} else {
|
|
mKeyguardWidgetPager.setOnlyAllowEdgeSwipes(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
public boolean isChallengeShowing() {
|
|
if (mChallengeLayout != null) {
|
|
return mChallengeLayout.isChallengeShowing();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public boolean isChallengeOverlapping() {
|
|
if (mChallengeLayout != null) {
|
|
return mChallengeLayout.isChallengeOverlapping();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void setSecurityViewContainer(KeyguardSecurityView container) {
|
|
mKeyguardSecurityContainer = container;
|
|
}
|
|
|
|
public void showBouncer(boolean show) {
|
|
mChallengeLayout.showBouncer();
|
|
}
|
|
|
|
public boolean isBouncing() {
|
|
return mChallengeLayout.isBouncing();
|
|
}
|
|
|
|
public void fadeOutSecurity(int duration) {
|
|
((View) mKeyguardSecurityContainer).animate().alpha(0f).setDuration(duration)
|
|
.setListener(mPauseListener);
|
|
}
|
|
|
|
public void fadeInSecurity(int duration) {
|
|
((View) mKeyguardSecurityContainer).animate().alpha(1f).setDuration(duration)
|
|
.setListener(mResumeListener);
|
|
}
|
|
|
|
public void onPageBeginMoving() {
|
|
if (mChallengeLayout.isChallengeOverlapping() &&
|
|
mChallengeLayout instanceof SlidingChallengeLayout) {
|
|
SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
|
|
scl.fadeOutChallenge();
|
|
mPageIndexOnPageBeginMoving = mKeyguardWidgetPager.getCurrentPage();
|
|
}
|
|
// We use mAppWidgetToShow to show a particular widget after you add it--
|
|
// once the user swipes a page we clear that behavior
|
|
if (mKeyguardHostView != null) {
|
|
mKeyguardHostView.clearAppWidgetToShow();
|
|
mKeyguardHostView.setOnDismissAction(null);
|
|
}
|
|
if (mHideHintsRunnable != null) {
|
|
mMainQueue.removeCallbacks(mHideHintsRunnable);
|
|
mHideHintsRunnable = null;
|
|
}
|
|
}
|
|
|
|
public void onPageEndMoving() {
|
|
mPageIndexOnPageBeginMoving = -1;
|
|
}
|
|
|
|
public void onPageSwitching(View newPage, int newPageIndex) {
|
|
if (mKeyguardWidgetPager != null && mChallengeLayout instanceof SlidingChallengeLayout) {
|
|
boolean isCameraPage = newPage instanceof CameraWidgetFrame;
|
|
if (isCameraPage) {
|
|
CameraWidgetFrame camera = (CameraWidgetFrame) newPage;
|
|
camera.setUseFastTransition(mKeyguardWidgetPager.isWarping());
|
|
}
|
|
SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
|
|
scl.setChallengeInteractive(!isCameraPage);
|
|
final int currentFlags = mKeyguardWidgetPager.getSystemUiVisibility();
|
|
final int newFlags = isCameraPage ? (currentFlags | View.STATUS_BAR_DISABLE_SEARCH)
|
|
: (currentFlags & ~View.STATUS_BAR_DISABLE_SEARCH);
|
|
mKeyguardWidgetPager.setSystemUiVisibility(newFlags);
|
|
}
|
|
|
|
// If the page we're settling to is the same as we started on, and the action of
|
|
// moving the page hid the security, we restore it immediately.
|
|
if (mPageIndexOnPageBeginMoving == mKeyguardWidgetPager.getNextPage() &&
|
|
mChallengeLayout instanceof SlidingChallengeLayout) {
|
|
SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
|
|
scl.fadeInChallenge();
|
|
mKeyguardWidgetPager.setWidgetToResetOnPageFadeOut(-1);
|
|
}
|
|
mPageIndexOnPageBeginMoving = -1;
|
|
}
|
|
|
|
public void onPageSwitched(View newPage, int newPageIndex) {
|
|
// 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 the page hasn't switched, don't bother with any of this
|
|
if (mCurrentPage == newPageIndex) return;
|
|
|
|
if (mKeyguardWidgetPager != null && mChallengeLayout != null) {
|
|
KeyguardWidgetFrame prevPage = mKeyguardWidgetPager.getWidgetPageAt(mCurrentPage);
|
|
if (prevPage != null && mCurrentPage != mPageListeningToSlider && mCurrentPage
|
|
!= mKeyguardWidgetPager.getWidgetToResetOnPageFadeOut()) {
|
|
prevPage.resetSize();
|
|
}
|
|
|
|
KeyguardWidgetFrame newCurPage = mKeyguardWidgetPager.getWidgetPageAt(newPageIndex);
|
|
boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
|
|
if (challengeOverlapping && !newCurPage.isSmall()
|
|
&& mPageListeningToSlider != newPageIndex) {
|
|
newCurPage.shrinkWidget(true);
|
|
}
|
|
}
|
|
|
|
mCurrentPage = newPageIndex;
|
|
}
|
|
|
|
public void onPageBeginWarp() {
|
|
fadeOutSecurity(SlidingChallengeLayout.CHALLENGE_FADE_OUT_DURATION);
|
|
View frame = mKeyguardWidgetPager.getPageAt(mKeyguardWidgetPager.getPageWarpIndex());
|
|
((KeyguardWidgetFrame)frame).showFrame(this);
|
|
}
|
|
|
|
public void onPageEndWarp() {
|
|
fadeInSecurity(SlidingChallengeLayout.CHALLENGE_FADE_IN_DURATION);
|
|
View frame = mKeyguardWidgetPager.getPageAt(mKeyguardWidgetPager.getPageWarpIndex());
|
|
((KeyguardWidgetFrame)frame).hideFrame(this);
|
|
}
|
|
|
|
private int getChallengeTopRelativeToFrame(KeyguardWidgetFrame frame, int top) {
|
|
mTmpPoint[0] = 0;
|
|
mTmpPoint[1] = top;
|
|
mapPoint((View) mChallengeLayout, frame, mTmpPoint);
|
|
return mTmpPoint[1];
|
|
}
|
|
|
|
/**
|
|
* Simple method to map a point from one view's coordinates to another's. Note: this method
|
|
* doesn't account for transforms, so if the views will be transformed, this should not be used.
|
|
*
|
|
* @param fromView The view to which the point is relative
|
|
* @param toView The view into which the point should be mapped
|
|
* @param pt The point
|
|
*/
|
|
private void mapPoint(View fromView, View toView, int pt[]) {
|
|
fromView.getLocationInWindow(mTmpLoc);
|
|
|
|
int x = mTmpLoc[0];
|
|
int y = mTmpLoc[1];
|
|
|
|
toView.getLocationInWindow(mTmpLoc);
|
|
int vX = mTmpLoc[0];
|
|
int vY = mTmpLoc[1];
|
|
|
|
pt[0] += x - vX;
|
|
pt[1] += y - vY;
|
|
}
|
|
|
|
private void userActivity() {
|
|
if (mKeyguardHostView != null) {
|
|
mKeyguardHostView.onUserActivityTimeoutChanged();
|
|
mKeyguardHostView.userActivity();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onScrollStateChanged(int scrollState) {
|
|
if (mKeyguardWidgetPager == null || mChallengeLayout == null) return;
|
|
|
|
boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
|
|
|
|
if (scrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
|
|
KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
|
|
if (frame == null) return;
|
|
|
|
if (!challengeOverlapping) {
|
|
if (!mKeyguardWidgetPager.isPageMoving()) {
|
|
frame.resetSize();
|
|
userActivity();
|
|
} else {
|
|
mKeyguardWidgetPager.setWidgetToResetOnPageFadeOut(mPageListeningToSlider);
|
|
}
|
|
}
|
|
if (frame.isSmall()) {
|
|
// This is to make sure that if the scroller animation gets cut off midway
|
|
// that the frame doesn't stay in a partial down position.
|
|
frame.setFrameHeight(frame.getSmallFrameHeight());
|
|
}
|
|
if (scrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
|
|
frame.hideFrame(this);
|
|
}
|
|
updateEdgeSwiping();
|
|
|
|
if (mChallengeLayout.isChallengeShowing()) {
|
|
mKeyguardSecurityContainer.onResume(KeyguardSecurityView.VIEW_REVEALED);
|
|
} else {
|
|
mKeyguardSecurityContainer.onPause();
|
|
}
|
|
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 = mKeyguardWidgetPager.getNextPage();
|
|
KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
|
|
if (frame == null) return;
|
|
|
|
// Skip showing the frame and shrinking the widget if we are
|
|
if (!mChallengeLayout.isBouncing()) {
|
|
if (scrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
|
|
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 = mKeyguardWidgetPager.getNextPage();
|
|
frame.shrinkWidget(false);
|
|
}
|
|
} else {
|
|
if (!frame.isSmall()) {
|
|
// We need to fetch the final page, in case the pages are in motion.
|
|
mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
|
|
}
|
|
}
|
|
|
|
// 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 = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
|
|
if (frame != null && mLastScrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
|
|
frame.adjustFrame(getChallengeTopRelativeToFrame(frame, mChallengeTop));
|
|
}
|
|
}
|
|
|
|
private Runnable mHideHintsRunnable = new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
if (mKeyguardWidgetPager != null) {
|
|
mKeyguardWidgetPager.hideOutlinesAndSidePages();
|
|
}
|
|
}
|
|
};
|
|
|
|
public void showUsabilityHints() {
|
|
mMainQueue.postDelayed( new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
mKeyguardSecurityContainer.showUsabilityHint();
|
|
}
|
|
} , SCREEN_ON_RING_HINT_DELAY);
|
|
if (SHOW_INITIAL_PAGE_HINTS) {
|
|
mKeyguardWidgetPager.showInitialPageHints();
|
|
}
|
|
if (mHideHintsRunnable != null) {
|
|
mMainQueue.postDelayed(mHideHintsRunnable, SCREEN_ON_HINT_DURATION);
|
|
}
|
|
}
|
|
|
|
// ChallengeLayout.OnBouncerStateChangedListener
|
|
@Override
|
|
public void onBouncerStateChanged(boolean bouncerActive) {
|
|
if (bouncerActive) {
|
|
mKeyguardWidgetPager.zoomOutToBouncer();
|
|
} else {
|
|
mKeyguardWidgetPager.zoomInFromBouncer();
|
|
if (mKeyguardHostView != null) {
|
|
mKeyguardHostView.setOnDismissAction(null);
|
|
}
|
|
}
|
|
}
|
|
}
|