Keyguard bouncer notifications; focus moving and the bouncer; slops

Integrate changes from prototype app

* Add callbacks for bouncer state changes

* Dismiss the bouncer if focus leaves the challenge area

* Increase edge swipe region, treat this as a slop for
  SlidingChallengeLayout's drag handle. (This allows edge swipes in
  the drag handle area to still page widgets instead.)

Change-Id: I732de1a8d999a34c7cc8aa8ed99e24b597f3444c
This commit is contained in:
Adam Powell
2012-10-25 13:39:30 -07:00
parent b3975088b6
commit 0b1b552268
8 changed files with 102 additions and 17 deletions

View File

@@ -28,6 +28,5 @@
android:paddingBottom="25dp"
android:clipChildren="false"
android:clipToPadding="false"
androidprv:pageSpacing="10dp"
androidprv:edgeSwipeRegionSize="8dp">
</com.android.internal.policy.impl.keyguard.KeyguardWidgetPager>
androidprv:pageSpacing="10dp">
</com.android.internal.policy.impl.keyguard.KeyguardWidgetPager>

View File

@@ -5766,7 +5766,6 @@
<!-- The padding for the scroll indicator area -->
<attr name="scrollIndicatorPaddingLeft" format="dimension" />
<attr name="scrollIndicatorPaddingRight" format="dimension" />
<attr name="edgeSwipeRegionSize" format="dimension" />
</declare-styleable>
<declare-styleable name="KeyguardGlowStripView">

View File

@@ -323,4 +323,8 @@
<!-- Size of the text under the avator on the multiuser lockscreen. -->
<dimen name="keyguard_avatar_name_size">10sp</dimen>
<!-- Size of the region along the edge of the screen that will accept
swipes to scroll the widget area. -->
<dimen name="kg_edge_swipe_region_size">16dp</dimen>
</resources>

View File

@@ -1214,6 +1214,7 @@
<java-symbol type="dimen" name="keyguard_avatar_size" />
<java-symbol type="dimen" name="keyguard_avatar_frame_stroke_width" />
<java-symbol type="dimen" name="keyguard_avatar_frame_shadow_radius" />
<java-symbol type="dimen" name="kg_edge_swipe_region_size" />
<java-symbol type="drawable" name="ic_jog_dial_sound_off" />
<java-symbol type="drawable" name="ic_jog_dial_sound_on" />
<java-symbol type="drawable" name="ic_jog_dial_unlock" />

View File

@@ -57,4 +57,36 @@ public interface ChallengeLayout {
* potentially blocking access to other child views.
*/
boolean isBouncing();
/**
* Set a listener that will respond to changes in bouncer state.
*
* @param listener listener to register
*/
void setOnBouncerStateChangedListener(OnBouncerStateChangedListener listener);
/**
* Listener interface that reports changes in bouncer state.
* The bouncer is
*/
public interface OnBouncerStateChangedListener {
/**
* Called when the bouncer state changes.
* The bouncer is activated when the user must pass a security challenge
* to proceed with the requested action.
*
* <p>This differs from simply showing or hiding the security challenge
* as the bouncer will prevent interaction with other elements of the UI.
* If the user attempts to escape from the bouncer, it will be dismissed,
* this method will be called with false as the parameter, and the action
* should be canceled. If the security component reports a successful
* authentication and the containing code calls hideBouncer() as a result,
* this method will also be called with a false parameter. It is up to the
* caller of hideBouncer to be ready for this.</p>
*
* @param bouncerActive true if the bouncer is now active,
* false if the bouncer was dismissed.
*/
public void onBouncerStateChanged(boolean bouncerActive);
}
}

View File

@@ -40,6 +40,7 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
private View mChallengeView;
private View mUserSwitcherView;
private View mScrimView;
private OnBouncerStateChangedListener mBouncerListener;
private final Rect mTempRect = new Rect();
@@ -89,6 +90,9 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
if (mScrimView != null) {
mScrimView.setVisibility(GONE);
}
if (mBouncerListener != null) {
mBouncerListener.onBouncerStateChanged(true);
}
}
@Override
@@ -98,6 +102,9 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
if (mScrimView != null) {
mScrimView.setVisibility(GONE);
}
if (mBouncerListener != null) {
mBouncerListener.onBouncerStateChanged(false);
}
}
@Override
@@ -105,6 +112,21 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
return mIsBouncing;
}
@Override
public void setOnBouncerStateChangedListener(OnBouncerStateChangedListener listener) {
mBouncerListener = listener;
}
@Override
public void requestChildFocus(View child, View focused) {
if (mIsBouncing && child != mChallengeView) {
// Clear out of the bouncer if the user tries to move focus outside of
// the security challenge view.
hideBouncer();
}
super.requestChildFocus(child, focused);
}
void setScrimView(View scrim) {
if (mScrimView != null) {
mScrimView.setOnClickListener(null);

View File

@@ -253,11 +253,12 @@ public class PagedView extends ViewGroup implements ViewGroup.OnHierarchyChangeL
mScrollIndicatorPaddingLeft =
a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingLeft, 0);
mScrollIndicatorPaddingRight =
a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingRight, 0);
mEdgeSwipeRegionSize =
a.getDimensionPixelSize(R.styleable.PagedView_edgeSwipeRegionSize, 0);
a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingRight, 0);
a.recycle();
mEdgeSwipeRegionSize =
getResources().getDimensionPixelSize(R.dimen.kg_edge_swipe_region_size);
setHapticFeedbackEnabled(false);
init();
}

View File

@@ -55,7 +55,8 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
private final Scroller mScroller;
private int mScrollState;
private OnChallengeScrolledListener mListener;
private OnChallengeScrolledListener mScrollListener;
private OnBouncerStateChangedListener mBouncerListener;
public static final int SCROLL_STATE_IDLE = 0;
public static final int SCROLL_STATE_DRAGGING = 1;
@@ -77,6 +78,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
private int mMaxVelocity;
private float mLastTouchY;
private int mDragHandleSize;
private int mDragHandleEdgeSlop;
private static final int DRAG_HANDLE_DEFAULT_SIZE = 32; // dp
@@ -172,6 +174,9 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
mMinVelocity = vc.getScaledMinimumFlingVelocity();
mMaxVelocity = vc.getScaledMaximumFlingVelocity();
mDragHandleEdgeSlop = getResources().getDimensionPixelSize(
R.dimen.kg_edge_swipe_region_size);
setWillNotDraw(false);
}
@@ -187,20 +192,24 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
}
private void sendInitialListenerUpdates() {
if (mListener != null) {
if (mScrollListener != null) {
int challengeTop = mChallengeView != null ? mChallengeView.getTop() : 0;
mListener.onScrollPositionChanged(mChallengeOffset, challengeTop);
mListener.onScrollStateChanged(mScrollState);
mScrollListener.onScrollPositionChanged(mChallengeOffset, challengeTop);
mScrollListener.onScrollStateChanged(mScrollState);
}
}
public void setOnChallengeScrolledListener(OnChallengeScrolledListener listener) {
mListener = listener;
mScrollListener = listener;
if (mHasLayout) {
sendInitialListenerUpdates();
}
}
public void setOnBouncerStateChangedListener(OnBouncerStateChangedListener listener) {
mBouncerListener = listener;
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -216,6 +225,16 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
mHasLayout = false;
}
@Override
public void requestChildFocus(View child, View focused) {
if (mIsBouncing && child != mChallengeView) {
// Clear out of the bouncer if the user tries to move focus outside of
// the security challenge view.
hideBouncer();
}
super.requestChildFocus(child, focused);
}
// We want the duration of the page snap animation to be influenced by the distance that
// the screen has to travel, however, we don't want this duration to be effected in a
// purely linear fashion. Instead, we use this method to moderate the effect that the distance
@@ -230,8 +249,8 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
if (mScrollState != state) {
mScrollState = state;
if (mListener != null) {
mListener.onScrollStateChanged(state);
if (mScrollListener != null) {
mScrollListener.onScrollStateChanged(state);
}
}
}
@@ -325,6 +344,9 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
if (mScrimView != null) {
mScrimView.setVisibility(GONE);
}
if (mBouncerListener != null) {
mBouncerListener.onBouncerStateChanged(true);
}
}
@Override
@@ -335,6 +357,9 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
if (mScrimView != null) {
mScrimView.setVisibility(GONE);
}
if (mBouncerListener != null) {
mBouncerListener.onBouncerStateChanged(false);
}
}
@Override
@@ -477,7 +502,9 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
private boolean isInDragHandle(float x, float y) {
if (mChallengeView == null) return false;
return x >= 0 && y >= mChallengeView.getTop() && x < getWidth() &&
return x >= mDragHandleEdgeSlop &&
y >= mChallengeView.getTop() &&
x < getWidth() - mDragHandleEdgeSlop &&
y < mChallengeView.getTop() + mDragHandleSize;
}
@@ -644,8 +671,8 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
bottom - mChallengeView.getHeight(), mChallengeView.getRight(), bottom);
mChallengeView.setAlpha(offset);
if (mListener != null) {
mListener.onScrollPositionChanged(offset, mChallengeView.getTop());
if (mScrollListener != null) {
mScrollListener.onScrollPositionChanged(offset, mChallengeView.getTop());
}
postInvalidateOnAnimation();
return true;