Beginnings of bouncer support; add scrims and state tracking
Integrating from prototype app Change-Id: Ib142cf371c5997f547266d8af7e25129fb4e1343
This commit is contained in:
@@ -41,6 +41,13 @@
|
||||
androidprv:layout_maxWidth="480dp"
|
||||
androidprv:layout_maxHeight="480dp" />
|
||||
|
||||
<include layout="@layout/keyguard_multi_user_selector"/>
|
||||
|
||||
<View android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_childType="scrim"
|
||||
android:background="#99000000" />
|
||||
|
||||
<com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer
|
||||
android:id="@+id/keyguard_security_container"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -61,8 +68,6 @@
|
||||
</com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper>
|
||||
</com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer>
|
||||
|
||||
<include layout="@layout/keyguard_multi_user_selector"/>
|
||||
|
||||
</com.android.internal.policy.impl.keyguard.MultiPaneChallengeLayout>
|
||||
</com.android.internal.policy.impl.keyguard.KeyguardHostView>
|
||||
|
||||
|
||||
@@ -43,11 +43,16 @@
|
||||
android:layout_gravity="center"/>
|
||||
</FrameLayout>
|
||||
|
||||
<View android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
androidprv:layout_childType="scrim"
|
||||
android:background="#99000000" />
|
||||
|
||||
<com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer
|
||||
android:id="@+id/keyguard_security_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
androidprv:layout_isChallenge="true"
|
||||
androidprv:layout_childType="challenge"
|
||||
android:gravity="bottom|center_horizontal"
|
||||
android:background="@drawable/security_frame">
|
||||
<com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper
|
||||
|
||||
@@ -42,6 +42,13 @@
|
||||
androidprv:layout_maxWidth="480dp"
|
||||
androidprv:layout_maxHeight="480dp" />
|
||||
|
||||
<include layout="@layout/keyguard_multi_user_selector"/>
|
||||
|
||||
<View android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
androidprv:layout_childType="scrim"
|
||||
android:background="#99000000" />
|
||||
|
||||
<com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer
|
||||
android:id="@+id/keyguard_security_container"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -62,7 +69,5 @@
|
||||
</com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper>
|
||||
</com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer>
|
||||
|
||||
<include layout="@layout/keyguard_multi_user_selector"/>
|
||||
|
||||
</com.android.internal.policy.impl.keyguard.MultiPaneChallengeLayout>
|
||||
</com.android.internal.policy.impl.keyguard.KeyguardHostView>
|
||||
|
||||
@@ -5776,12 +5776,31 @@
|
||||
<attr name="leftToRight" format="boolean" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- Some child types have special behavior. -->
|
||||
<attr name="layout_childType">
|
||||
<!-- No special behavior. Layout will proceed as normal. -->
|
||||
<enum name="none" value="0" />
|
||||
<!-- Widget container.
|
||||
This will be resized in response to certain events. -->
|
||||
<enum name="widget" value="1" />
|
||||
<!-- Security challenge container.
|
||||
This will be dismissed/shown in response to certain events,
|
||||
possibly obscuring widget elements. -->
|
||||
<enum name="challenge" value="2" />
|
||||
<!-- User switcher.
|
||||
This will consume space from the total layout area. -->
|
||||
<enum name="userSwitcher" value="3" />
|
||||
<!-- Scrim. This will block access to child views that
|
||||
come before it in the child list in bouncer mode. -->
|
||||
<enum name="scrim" value="4" />
|
||||
</attr>
|
||||
|
||||
<declare-styleable name="SlidingChallengeLayout">
|
||||
<attr name="dragHandle" format="reference" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="SlidingChallengeLayout_Layout">
|
||||
<attr name="layout_isChallenge" format="boolean" />
|
||||
<attr name="layout_childType" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- Attributes that can be used with <code><FragmentBreadCrumbs></code>
|
||||
@@ -5800,21 +5819,7 @@
|
||||
If 0/default, the view will be measured by standard rules
|
||||
as if this were a FrameLayout. -->
|
||||
<attr name="layout_centerWithinArea" format="float" />
|
||||
<!-- Some child types have special behavior. -->
|
||||
<attr name="layout_childType">
|
||||
<!-- No special behavior. Layout will proceed as normal. -->
|
||||
<enum name="none" value="0" />
|
||||
<!-- Widget container.
|
||||
This will be resized in response to certain events. -->
|
||||
<enum name="widget" value="1" />
|
||||
<!-- Security challenge container.
|
||||
This will be dismissed/shown in response to certain events,
|
||||
possibly obscuring widget elements. -->
|
||||
<enum name="challenge" value="2" />
|
||||
<!-- User switcher.
|
||||
This will consume space from the total layout area. -->
|
||||
<enum name="userSwitcher" value="3" />
|
||||
</attr>
|
||||
<attr name="layout_childType" />
|
||||
<attr name="layout_gravity" />
|
||||
<attr name="layout_maxWidth" format="dimension" />
|
||||
<attr name="layout_maxHeight" />
|
||||
|
||||
@@ -45,4 +45,16 @@ public interface ChallengeLayout {
|
||||
* Show the bouncer challenge. This may block access to other child views.
|
||||
*/
|
||||
void showBouncer();
|
||||
|
||||
/**
|
||||
* Hide the bouncer challenge if it is currently showing.
|
||||
* This may restore previously blocked access to other child views.
|
||||
*/
|
||||
void hideBouncer();
|
||||
|
||||
/**
|
||||
* Returns true if the challenge is currently in bouncer mode,
|
||||
* potentially blocking access to other child views.
|
||||
*/
|
||||
boolean isBouncing();
|
||||
}
|
||||
|
||||
@@ -32,15 +32,24 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
|
||||
private static final String TAG = "MultiPaneChallengeLayout";
|
||||
|
||||
final int mOrientation;
|
||||
private boolean mIsBouncing;
|
||||
|
||||
public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
|
||||
public static final int VERTICAL = LinearLayout.VERTICAL;
|
||||
|
||||
private View mChallengeView;
|
||||
private View mUserSwitcherView;
|
||||
private View mScrimView;
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
|
||||
private final OnClickListener mScrimClickListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
hideBouncer();
|
||||
}
|
||||
};
|
||||
|
||||
public MultiPaneChallengeLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
@@ -75,7 +84,35 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
|
||||
|
||||
@Override
|
||||
public void showBouncer() {
|
||||
// TODO Block access to other views
|
||||
if (mIsBouncing) return;
|
||||
mIsBouncing = true;
|
||||
if (mScrimView != null) {
|
||||
mScrimView.setVisibility(GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideBouncer() {
|
||||
if (!mIsBouncing) return;
|
||||
mIsBouncing = false;
|
||||
if (mScrimView != null) {
|
||||
mScrimView.setVisibility(GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBouncing() {
|
||||
return mIsBouncing;
|
||||
}
|
||||
|
||||
void setScrimView(View scrim) {
|
||||
if (mScrimView != null) {
|
||||
mScrimView.setOnClickListener(null);
|
||||
}
|
||||
mScrimView = scrim;
|
||||
mScrimView.setVisibility(mIsBouncing ? VISIBLE : GONE);
|
||||
mScrimView.setFocusable(true);
|
||||
mScrimView.setOnClickListener(mScrimClickListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -139,6 +176,9 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
|
||||
} else if (Gravity.isHorizontal(lp.gravity)) {
|
||||
widthUsed += child.getMeasuredWidth() * 1.5f;
|
||||
}
|
||||
} else if (lp.childType == LayoutParams.CHILD_TYPE_SCRIM) {
|
||||
setScrimView(child);
|
||||
child.measure(widthSpec, heightSpec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,6 +188,7 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
|
||||
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
||||
|
||||
if (lp.childType == LayoutParams.CHILD_TYPE_USER_SWITCHER ||
|
||||
lp.childType == LayoutParams.CHILD_TYPE_SCRIM ||
|
||||
child.getVisibility() == GONE) {
|
||||
// Don't need to measure GONE children, and the user switcher was already measured.
|
||||
continue;
|
||||
@@ -208,6 +249,11 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
|
||||
// We did the user switcher above if we have one.
|
||||
if (child == mUserSwitcherView || child.getVisibility() == GONE) continue;
|
||||
|
||||
if (child == mScrimView) {
|
||||
child.layout(0, 0, width, height);
|
||||
continue;
|
||||
}
|
||||
|
||||
layoutWithGravity(width, height, child, padding, false);
|
||||
}
|
||||
}
|
||||
@@ -333,6 +379,7 @@ public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayo
|
||||
public static final int CHILD_TYPE_WIDGET = 1;
|
||||
public static final int CHILD_TYPE_CHALLENGE = 2;
|
||||
public static final int CHILD_TYPE_USER_SWITCHER = 3;
|
||||
public static final int CHILD_TYPE_SCRIM = 4;
|
||||
|
||||
public int gravity = Gravity.NO_GRAVITY;
|
||||
|
||||
|
||||
@@ -46,10 +46,12 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
|
||||
// Initialized during measurement from child layoutparams
|
||||
private View mChallengeView;
|
||||
private View mScrimView;
|
||||
|
||||
// Range: 0 (fully hidden) to 1 (fully visible)
|
||||
private float mChallengeOffset = 1.f;
|
||||
private boolean mChallengeShowing = true;
|
||||
private boolean mIsBouncing = false;
|
||||
|
||||
private final Scroller mScroller;
|
||||
private int mScrollState;
|
||||
@@ -100,6 +102,13 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
}
|
||||
};
|
||||
|
||||
private final OnClickListener mScrimClickListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
hideBouncer();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Listener interface that reports changes in scroll state of the challenge area.
|
||||
*/
|
||||
@@ -232,6 +241,16 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
setScrollState(SCROLL_STATE_IDLE);
|
||||
}
|
||||
|
||||
void setScrimView(View scrim) {
|
||||
if (mScrimView != null) {
|
||||
mScrimView.setOnClickListener(null);
|
||||
}
|
||||
mScrimView = scrim;
|
||||
mScrimView.setVisibility(mIsBouncing ? VISIBLE : GONE);
|
||||
mScrimView.setFocusable(true);
|
||||
mScrimView.setOnClickListener(mScrimClickListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate the bottom edge of the challenge view to the given position.
|
||||
*
|
||||
@@ -293,6 +312,31 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
return mChallengeShowing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBouncing() {
|
||||
return mIsBouncing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showBouncer() {
|
||||
if (mIsBouncing) return;
|
||||
showChallenge(true);
|
||||
mIsBouncing = true;
|
||||
if (mScrimView != null) {
|
||||
mScrimView.setVisibility(GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideBouncer() {
|
||||
if (!mIsBouncing) return;
|
||||
setChallengeShowing(false);
|
||||
mIsBouncing = false;
|
||||
if (mScrimView != null) {
|
||||
mScrimView.setVisibility(GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestDisallowInterceptTouchEvent(boolean allowIntercept) {
|
||||
// We'll intercept whoever we feel like! ...as long as it isn't a challenge view.
|
||||
@@ -463,7 +507,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
final View child = getChildAt(i);
|
||||
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
||||
|
||||
if (lp.isChallenge) {
|
||||
if (lp.childType == LayoutParams.CHILD_TYPE_CHALLENGE) {
|
||||
if (mChallengeView != null) {
|
||||
throw new IllegalStateException(
|
||||
"There may only be one child with layout_isChallenge=\"true\"");
|
||||
@@ -472,6 +516,8 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
if (mChallengeView != oldChallengeView) {
|
||||
mChallengeView.setVisibility(mChallengeShowing ? VISIBLE : INVISIBLE);
|
||||
}
|
||||
} else if (lp.childType == LayoutParams.CHILD_TYPE_SCRIM) {
|
||||
setScrimView(child);
|
||||
}
|
||||
|
||||
if (child.getVisibility() == GONE) continue;
|
||||
@@ -497,7 +543,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
|
||||
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
|
||||
|
||||
if (lp.isChallenge) {
|
||||
if (lp.childType == LayoutParams.CHILD_TYPE_CHALLENGE) {
|
||||
// Challenge views pin to the bottom, offset by a portion of their height,
|
||||
// and center horizontally.
|
||||
final int center = (paddingLeft + width - paddingRight) / 2;
|
||||
@@ -657,12 +703,6 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showBouncer() {
|
||||
// TODO Block access to other views
|
||||
showChallenge(true);
|
||||
}
|
||||
|
||||
public void showHandle(boolean show) {
|
||||
mShowHandle = show;
|
||||
invalidate();
|
||||
@@ -691,7 +731,10 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
}
|
||||
|
||||
public static class LayoutParams extends MarginLayoutParams {
|
||||
public boolean isChallenge = false;
|
||||
public int childType = CHILD_TYPE_NONE;
|
||||
public static final int CHILD_TYPE_NONE = 0;
|
||||
public static final int CHILD_TYPE_CHALLENGE = 2;
|
||||
public static final int CHILD_TYPE_SCRIM = 4;
|
||||
|
||||
public LayoutParams() {
|
||||
this(MATCH_PARENT, WRAP_CONTENT);
|
||||
@@ -712,7 +755,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
public LayoutParams(LayoutParams source) {
|
||||
super(source);
|
||||
|
||||
isChallenge = source.isChallenge;
|
||||
childType = source.childType;
|
||||
}
|
||||
|
||||
public LayoutParams(Context c, AttributeSet attrs) {
|
||||
@@ -720,8 +763,8 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
|
||||
|
||||
final TypedArray a = c.obtainStyledAttributes(attrs,
|
||||
R.styleable.SlidingChallengeLayout_Layout);
|
||||
isChallenge = a.getBoolean(R.styleable.SlidingChallengeLayout_Layout_layout_isChallenge,
|
||||
false);
|
||||
childType = a.getInt(R.styleable.SlidingChallengeLayout_Layout_layout_childType,
|
||||
CHILD_TYPE_NONE);
|
||||
a.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user