SlidingChallengeLayout.java revision c238af5112bee38b3143a65849bd41785c3744b0
1d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller/* 2d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * Copyright (C) 2012 The Android Open Source Project 3d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * 4d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * Licensed under the Apache License, Version 2.0 (the "License"); 5d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * you may not use this file except in compliance with the License. 6d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * You may obtain a copy of the License at 7d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * 8d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * http://www.apache.org/licenses/LICENSE-2.0 9d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * 10d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * Unless required by applicable law or agreed to in writing, software 11d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * distributed under the License is distributed on an "AS IS" BASIS, 12d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * See the License for the specific language governing permissions and 14d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * limitations under the License. 15d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller */ 16d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 17d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Millerpackage com.android.internal.policy.impl.keyguard; 18d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 19cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powellimport android.animation.Animator; 20cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powellimport android.animation.AnimatorListenerAdapter; 216f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powellimport android.animation.ObjectAnimator; 22d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Millerimport android.content.Context; 23fa668cc930544e8b231c1fbf3ad496374b7aa21cAdam Powellimport android.content.res.Resources; 24d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Millerimport android.content.res.TypedArray; 25d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Millerimport android.graphics.Canvas; 261bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandlerimport android.graphics.Paint; 27cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powellimport android.graphics.Rect; 28d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Millerimport android.graphics.drawable.Drawable; 29d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Millerimport android.util.AttributeSet; 306f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powellimport android.util.FloatProperty; 31d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Millerimport android.util.Log; 3274bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganovimport android.util.MathUtils; 336f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powellimport android.util.Property; 34d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Millerimport android.view.MotionEvent; 35d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Millerimport android.view.VelocityTracker; 36d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Millerimport android.view.View; 37d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Millerimport android.view.ViewConfiguration; 38d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Millerimport android.view.ViewGroup; 3974bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganovimport android.view.accessibility.AccessibilityManager; 40d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Millerimport android.view.animation.Interpolator; 41d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Millerimport android.widget.Scroller; 42d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 43d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Millerimport com.android.internal.R; 44d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 45d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller/** 46d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * This layout handles interaction with the sliding security challenge views 47d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * that overlay/resize other keyguard contents. 48d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller */ 4919a5267003e7dc70100a4bd4f1f449523b2ff38bJim Millerpublic class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout { 50d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private static final String TAG = "SlidingChallengeLayout"; 511bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler private static final boolean DEBUG = false; 52d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 53c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler // The drag handle is measured in dp above & below the top edge of the 54c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler // challenge view; these parameters change based on whether the challenge 55c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler // is open or closed. 56cfc3086b18396df03f982fb98112649dc5b5a6f2Adam Powell private static final int DRAG_HANDLE_CLOSED_ABOVE = 64; // dp 57cfc3086b18396df03f982fb98112649dc5b5a6f2Adam Powell private static final int DRAG_HANDLE_CLOSED_BELOW = 0; // dp 58c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler private static final int DRAG_HANDLE_OPEN_ABOVE = 8; // dp 59c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler private static final int DRAG_HANDLE_OPEN_BELOW = 0; // dp 60c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler 61c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler private static final int HANDLE_ANIMATE_DURATION = 200; // ms 62c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler 63d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // Drawn to show the drag handle in closed state; crossfades to the challenge view 64d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // when challenge is fully visible 656f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell private Drawable mFrameDrawable; 66cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell private boolean mEdgeCaptured; 67d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 68d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // Initialized during measurement from child layoutparams 6974bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov private View mExpandChallengeView; 70d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private View mChallengeView; 71eee209313d564be37b8fc068f785b3844cd6597eAdam Powell private View mScrimView; 72cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell private View mWidgetsView; 73d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 74d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // Range: 0 (fully hidden) to 1 (fully visible) 75d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private float mChallengeOffset = 1.f; 76d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private boolean mChallengeShowing = true; 77eee209313d564be37b8fc068f785b3844cd6597eAdam Powell private boolean mIsBouncing = false; 78d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 79d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private final Scroller mScroller; 80d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private int mScrollState; 810b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell private OnChallengeScrolledListener mScrollListener; 820b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell private OnBouncerStateChangedListener mBouncerListener; 83d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 84d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public static final int SCROLL_STATE_IDLE = 0; 85d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public static final int SCROLL_STATE_DRAGGING = 1; 86d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public static final int SCROLL_STATE_SETTLING = 2; 87d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 88d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private static final int MAX_SETTLE_DURATION = 600; // ms 89d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 90d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // ID of the pointer in charge of a current drag 91d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private int mActivePointerId = INVALID_POINTER; 92d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private static final int INVALID_POINTER = -1; 93d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 94d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // True if the user is currently dragging the slider 95d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private boolean mDragging; 96d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // True if the user may not drag until a new gesture begins 97d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private boolean mBlockDrag; 98d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 99d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private VelocityTracker mVelocityTracker; 100d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private int mMinVelocity; 101d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private int mMaxVelocity; 102c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler private float mGestureStartX, mGestureStartY; // where did you first touch the screen? 103b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler private int mGestureStartChallengeBottom; // where was the challenge at that time? 104c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler 105c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler private int mDragHandleClosedBelow; // handle hitrect extension into the challenge view 106c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler private int mDragHandleClosedAbove; // extend the handle's hitrect this far above the line 107c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler private int mDragHandleOpenBelow; // handle hitrect extension into the challenge view 108c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler private int mDragHandleOpenAbove; // extend the handle's hitrect this far above the line 109c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler 1100b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell private int mDragHandleEdgeSlop; 11167625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell private int mChallengeBottomBound; // Number of pixels from the top of the challenge view 11267625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell // that should remain on-screen 113c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler 114c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler private int mTouchSlop; 11574bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov private int mTouchSlopSquare; 116c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler 1176f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell float mHandleAlpha; 1186f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell float mFrameAlpha; 119cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell float mFrameAnimationTarget = Float.MIN_VALUE; 1206f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell private ObjectAnimator mHandleAnimation; 1216f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell private ObjectAnimator mFrameAnimation; 1226f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell 123cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell private final Rect mTempRect = new Rect(); 124cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell 125cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell private boolean mHasGlowpad; 126cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell 1276f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell static final Property<SlidingChallengeLayout, Float> HANDLE_ALPHA = 1286f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell new FloatProperty<SlidingChallengeLayout>("handleAlpha") { 1296f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell @Override 1306f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell public void setValue(SlidingChallengeLayout view, float value) { 1316f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell view.mHandleAlpha = value; 1326f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell view.invalidate(); 1336f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell } 1346f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell 1356f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell @Override 1366f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell public Float get(SlidingChallengeLayout view) { 1376f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell return view.mHandleAlpha; 1386f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell } 1396f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell }; 1406f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell 1416f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell static final Property<SlidingChallengeLayout, Float> FRAME_ALPHA = 1426f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell new FloatProperty<SlidingChallengeLayout>("frameAlpha") { 1436f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell @Override 1446f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell public void setValue(SlidingChallengeLayout view, float value) { 1456f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell if (view.mFrameDrawable != null) { 1466f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell view.mFrameAlpha = value; 1476f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell view.mFrameDrawable.setAlpha((int) (value * 0xFF)); 1486f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell view.mFrameDrawable.invalidateSelf(); 1496f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell } 1506f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell } 1516f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell 1526f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell @Override 1536f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell public Float get(SlidingChallengeLayout view) { 1546f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell return view.mFrameAlpha; 1556f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell } 1566f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell }; 157d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 158d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // True if at least one layout pass has happened since the view was attached. 159d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private boolean mHasLayout; 160d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 161d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private static final Interpolator sMotionInterpolator = new Interpolator() { 162d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public float getInterpolation(float t) { 163d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller t -= 1.0f; 164d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return t * t * t * t * t + 1.0f; 165d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 166d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller }; 167d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 168d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private static final Interpolator sHandleFadeInterpolator = new Interpolator() { 169d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public float getInterpolation(float t) { 170d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return t * t; 171d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 172d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller }; 173d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 174d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private final Runnable mEndScrollRunnable = new Runnable () { 175d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public void run() { 176d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller completeChallengeScroll(); 177d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 178d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller }; 179d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 180eee209313d564be37b8fc068f785b3844cd6597eAdam Powell private final OnClickListener mScrimClickListener = new OnClickListener() { 181eee209313d564be37b8fc068f785b3844cd6597eAdam Powell @Override 182eee209313d564be37b8fc068f785b3844cd6597eAdam Powell public void onClick(View v) { 183eee209313d564be37b8fc068f785b3844cd6597eAdam Powell hideBouncer(); 184eee209313d564be37b8fc068f785b3844cd6597eAdam Powell } 185eee209313d564be37b8fc068f785b3844cd6597eAdam Powell }; 186eee209313d564be37b8fc068f785b3844cd6597eAdam Powell 18774bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov private final OnClickListener mExpandChallengeClickListener = new OnClickListener() { 18874bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov @Override 18974bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov public void onClick(View v) { 19074bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov if (!isChallengeShowing()) { 19174bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov showChallenge(true); 19274bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov } 19374bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov } 19474bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov }; 19574bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov 196d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller /** 197d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * Listener interface that reports changes in scroll state of the challenge area. 198d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller */ 199d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public interface OnChallengeScrolledListener { 200d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller /** 201d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * The scroll state itself changed. 202d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * 203d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * <p>scrollState will be one of the following:</p> 204d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * 205d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * <ul> 206d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * <li><code>SCROLL_STATE_IDLE</code> - The challenge area is stationary.</li> 207d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * <li><code>SCROLL_STATE_DRAGGING</code> - The user is actively dragging 208d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * the challenge area.</li> 209d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * <li><code>SCROLL_STATE_SETTLING</code> - The challenge area is animating 210d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * into place.</li> 211d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * </ul> 212d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * 213d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * <p>Do not perform expensive operations (e.g. layout) 214d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * while the scroll state is not <code>SCROLL_STATE_IDLE</code>.</p> 215d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * 216d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * @param scrollState The new scroll state of the challenge area. 217d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller */ 218d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public void onScrollStateChanged(int scrollState); 219d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 220d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller /** 221d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * The precise position of the challenge area has changed. 222d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * 223d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * <p>NOTE: It is NOT safe to modify layout or call any View methods that may 224d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * result in a requestLayout anywhere in your view hierarchy as a result of this call. 225d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * It may be called during drawing.</p> 226d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * 227d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * @param scrollPosition New relative position of the challenge area. 228d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * 1.f = fully visible/ready to be interacted with. 229d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * 0.f = fully invisible/inaccessible to the user. 230d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * @param challengeTop Position of the top edge of the challenge view in px in the 231d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * SlidingChallengeLayout's coordinate system. 232d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller */ 233d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public void onScrollPositionChanged(float scrollPosition, int challengeTop); 234d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 235d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 236d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public SlidingChallengeLayout(Context context) { 237d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller this(context, null); 238d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 239d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 240d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public SlidingChallengeLayout(Context context, AttributeSet attrs) { 241d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller this(context, attrs, 0); 242d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 243d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 244d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public SlidingChallengeLayout(Context context, AttributeSet attrs, int defStyle) { 245d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller super(context, attrs, defStyle); 246d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 247d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mScroller = new Scroller(context, sMotionInterpolator); 248d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 249d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final ViewConfiguration vc = ViewConfiguration.get(context); 250d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mMinVelocity = vc.getScaledMinimumFlingVelocity(); 251d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mMaxVelocity = vc.getScaledMaximumFlingVelocity(); 252d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 253fa668cc930544e8b231c1fbf3ad496374b7aa21cAdam Powell final Resources res = getResources(); 254fa668cc930544e8b231c1fbf3ad496374b7aa21cAdam Powell mDragHandleEdgeSlop = res.getDimensionPixelSize(R.dimen.kg_edge_swipe_region_size); 2550b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell 256c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 25774bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov mTouchSlopSquare = mTouchSlop * mTouchSlop; 258c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler 259fa668cc930544e8b231c1fbf3ad496374b7aa21cAdam Powell final float density = res.getDisplayMetrics().density; 2601bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler 2611bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler // top half of the lock icon, plus another 25% to be sure 262c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler mDragHandleClosedAbove = (int) (DRAG_HANDLE_CLOSED_ABOVE * density + 0.5f); 263c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler mDragHandleClosedBelow = (int) (DRAG_HANDLE_CLOSED_BELOW * density + 0.5f); 264c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler mDragHandleOpenAbove = (int) (DRAG_HANDLE_OPEN_ABOVE * density + 0.5f); 265c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler mDragHandleOpenBelow = (int) (DRAG_HANDLE_OPEN_BELOW * density + 0.5f); 266c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler 267c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler // how much space to account for in the handle when closed 268fa668cc930544e8b231c1fbf3ad496374b7aa21cAdam Powell mChallengeBottomBound = res.getDimensionPixelSize(R.dimen.kg_widget_pager_bottom_padding); 2691bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler 270cfc3086b18396df03f982fb98112649dc5b5a6f2Adam Powell setWillNotDraw(false); 271cfc3086b18396df03f982fb98112649dc5b5a6f2Adam Powell } 272cfc3086b18396df03f982fb98112649dc5b5a6f2Adam Powell 2736e36f1019cb6d7098b49e036e1640c8cfc6880cfJohn Spurlock public void setHandleAlpha(float alpha) { 2746e36f1019cb6d7098b49e036e1640c8cfc6880cfJohn Spurlock if (mExpandChallengeView != null) { 2756e36f1019cb6d7098b49e036e1640c8cfc6880cfJohn Spurlock mExpandChallengeView.setAlpha(alpha); 2766f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell } 2776f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell } 2786f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell 2796f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell void animateHandle(boolean visible) { 2806f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell if (mHandleAnimation != null) { 2816f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell mHandleAnimation.cancel(); 28267625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell mHandleAnimation = null; 283d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 28467625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell final float targetAlpha = visible ? 1.f : 0.f; 28567625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell if (targetAlpha == mHandleAlpha) { 28667625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell return; 28767625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell } 28867625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell mHandleAnimation = ObjectAnimator.ofFloat(this, HANDLE_ALPHA, targetAlpha); 2896f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell mHandleAnimation.setInterpolator(sHandleFadeInterpolator); 2906f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell mHandleAnimation.setDuration(HANDLE_ANIMATE_DURATION); 2916f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell mHandleAnimation.start(); 2926f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell } 2936f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell 294cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell void animateFrame(final boolean visible, final boolean full) { 2956f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell if (mFrameDrawable == null) return; 2966f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell 297cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell final float targetAlpha = visible ? (full ? 1.f : 0.5f) : 0.f; 298cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell if (mFrameAnimation != null && targetAlpha != mFrameAnimationTarget) { 2996f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell mFrameAnimation.cancel(); 300cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mFrameAnimationTarget = Float.MIN_VALUE; 30167625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell } 302cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell if (targetAlpha == mFrameAlpha || targetAlpha == mFrameAnimationTarget) { 30367625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell return; 304d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 305cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mFrameAnimationTarget = targetAlpha; 30667625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell 30767625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell mFrameAnimation = ObjectAnimator.ofFloat(this, FRAME_ALPHA, targetAlpha); 3086f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell mFrameAnimation.setInterpolator(sHandleFadeInterpolator); 3096f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell mFrameAnimation.setDuration(HANDLE_ANIMATE_DURATION); 310cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mFrameAnimation.addListener(new AnimatorListenerAdapter() { 311cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell @Override 312cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell public void onAnimationEnd(Animator animation) { 313cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mFrameAnimationTarget = Float.MIN_VALUE; 314cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell 315cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell if (!visible && full && mChallengeView != null) { 316cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell // Mess with padding/margin to remove insets on the bouncer frame. 317cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mChallengeView.setPadding(0, 0, 0, 0); 318cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell LayoutParams lp = (LayoutParams) mChallengeView.getLayoutParams(); 319cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell lp.leftMargin = lp.rightMargin = getChallengeMargin(true); 320cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mChallengeView.setLayoutParams(lp); 321cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } 322cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mFrameAnimation = null; 323cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } 324cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell 325cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell @Override 326cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell public void onAnimationCancel(Animator animation) { 327cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mFrameAnimationTarget = Float.MIN_VALUE; 328cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mFrameAnimation = null; 329cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } 330cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell }); 3316f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell mFrameAnimation.start(); 332d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 333d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 334d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private void sendInitialListenerUpdates() { 3350b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell if (mScrollListener != null) { 336d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller int challengeTop = mChallengeView != null ? mChallengeView.getTop() : 0; 3370b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell mScrollListener.onScrollPositionChanged(mChallengeOffset, challengeTop); 3380b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell mScrollListener.onScrollStateChanged(mScrollState); 339d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 340d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 341d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 342d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public void setOnChallengeScrolledListener(OnChallengeScrolledListener listener) { 3430b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell mScrollListener = listener; 344d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (mHasLayout) { 345d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller sendInitialListenerUpdates(); 346d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 347d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 348d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 3490b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell public void setOnBouncerStateChangedListener(OnBouncerStateChangedListener listener) { 3500b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell mBouncerListener = listener; 3510b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell } 3520b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell 353d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller @Override 354d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public void onAttachedToWindow() { 355d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller super.onAttachedToWindow(); 356d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 357d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mHasLayout = false; 358d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 359d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 360d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller @Override 361d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public void onDetachedFromWindow() { 362d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller super.onDetachedFromWindow(); 363d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 364d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller removeCallbacks(mEndScrollRunnable); 365d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mHasLayout = false; 366d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 367d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 3680b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell @Override 3690b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell public void requestChildFocus(View child, View focused) { 3700b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell if (mIsBouncing && child != mChallengeView) { 3710b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell // Clear out of the bouncer if the user tries to move focus outside of 3720b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell // the security challenge view. 3730b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell hideBouncer(); 3740b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell } 3750b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell super.requestChildFocus(child, focused); 3760b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell } 3770b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell 378d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // We want the duration of the page snap animation to be influenced by the distance that 379d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // the screen has to travel, however, we don't want this duration to be effected in a 380d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // purely linear fashion. Instead, we use this method to moderate the effect that the distance 381d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // of travel has on the overall snap duration. 382d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller float distanceInfluenceForSnapDuration(float f) { 383d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller f -= 0.5f; // center the values about 0. 384d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller f *= 0.3f * Math.PI / 2.0f; 385d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return (float) Math.sin(f); 386d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 387d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 388d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller void setScrollState(int state) { 389d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (mScrollState != state) { 390d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mScrollState = state; 391d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 3926f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell animateHandle(state == SCROLL_STATE_IDLE && !mChallengeShowing); 393cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell if (!mIsBouncing) { 394cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell animateFrame(false, false); 395cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } 3960b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell if (mScrollListener != null) { 3970b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell mScrollListener.onScrollStateChanged(state); 398d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 399d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 400d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 401d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 402d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller void completeChallengeScroll() { 403d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller setChallengeShowing(mChallengeOffset != 0); 404d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller setScrollState(SCROLL_STATE_IDLE); 405cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mChallengeView.setLayerType(LAYER_TYPE_NONE, null); 406d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 407d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 408eee209313d564be37b8fc068f785b3844cd6597eAdam Powell void setScrimView(View scrim) { 409eee209313d564be37b8fc068f785b3844cd6597eAdam Powell if (mScrimView != null) { 410eee209313d564be37b8fc068f785b3844cd6597eAdam Powell mScrimView.setOnClickListener(null); 411eee209313d564be37b8fc068f785b3844cd6597eAdam Powell } 412eee209313d564be37b8fc068f785b3844cd6597eAdam Powell mScrimView = scrim; 413eee209313d564be37b8fc068f785b3844cd6597eAdam Powell mScrimView.setVisibility(mIsBouncing ? VISIBLE : GONE); 414eee209313d564be37b8fc068f785b3844cd6597eAdam Powell mScrimView.setFocusable(true); 415eee209313d564be37b8fc068f785b3844cd6597eAdam Powell mScrimView.setOnClickListener(mScrimClickListener); 416eee209313d564be37b8fc068f785b3844cd6597eAdam Powell } 417eee209313d564be37b8fc068f785b3844cd6597eAdam Powell 418d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller /** 419d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * Animate the bottom edge of the challenge view to the given position. 420d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * 421d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * @param y desired final position for the bottom edge of the challenge view in px 422d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * @param velocity velocity in 423d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller */ 424d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller void animateChallengeTo(int y, int velocity) { 425d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (mChallengeView == null) { 426d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // Nothing to do. 427d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return; 428d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 42967625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell final int sy = mChallengeView.getBottom(); 43067625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell final int dy = y - sy; 431d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (dy == 0) { 432d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller completeChallengeScroll(); 433d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return; 434d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 435d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 436d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller setScrollState(SCROLL_STATE_SETTLING); 437d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 438d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int childHeight = mChallengeView.getHeight(); 439d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int halfHeight = childHeight / 2; 440d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dy) / childHeight); 441d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final float distance = halfHeight + halfHeight * 442d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller distanceInfluenceForSnapDuration(distanceRatio); 443d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 444d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller int duration = 0; 445d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller velocity = Math.abs(velocity); 446d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (velocity > 0) { 447d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller duration = 4 * Math.round(1000 * Math.abs(distance / velocity)); 448d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } else { 449d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final float childDelta = (float) Math.abs(dy) / childHeight; 450d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller duration = (int) ((childDelta + 1) * 100); 451d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 452d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller duration = Math.min(duration, MAX_SETTLE_DURATION); 453d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 454d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mScroller.startScroll(0, sy, 0, dy, duration); 455d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller postInvalidateOnAnimation(); 456d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 457d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 458d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private void setChallengeShowing(boolean showChallenge) { 45974bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov if (mChallengeShowing == showChallenge) { 46074bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov return; 46174bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov } 46267625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell mChallengeShowing = showChallenge; 46374bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov if (mChallengeShowing) { 46474bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov mExpandChallengeView.setVisibility(View.INVISIBLE); 46574bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov mChallengeView.setVisibility(View.VISIBLE); 46674bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov if (AccessibilityManager.getInstance(mContext).isEnabled()) { 46774bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov mChallengeView.requestAccessibilityFocus(); 46874bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov mChallengeView.announceForAccessibility(mContext.getString( 46974bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov R.string.keyguard_accessibility_unlock_area_expanded)); 47074bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov } 47174bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov } else { 47274bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov mExpandChallengeView.setVisibility(View.VISIBLE); 47374bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov mChallengeView.setVisibility(View.INVISIBLE); 47474bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov if (AccessibilityManager.getInstance(mContext).isEnabled()) { 47574bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov mExpandChallengeView.requestAccessibilityFocus(); 47674bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov mChallengeView.announceForAccessibility(mContext.getString( 47774bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov R.string.keyguard_accessibility_unlock_area_collapsed)); 47874bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov } 47974bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov } 480d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 481d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 482d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller /** 483d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * @return true if the challenge is at all visible. 484d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller */ 485d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public boolean isChallengeShowing() { 486d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return mChallengeShowing; 487d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 488d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 489d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller @Override 49019a5267003e7dc70100a4bd4f1f449523b2ff38bJim Miller public boolean isChallengeOverlapping() { 49119a5267003e7dc70100a4bd4f1f449523b2ff38bJim Miller return mChallengeShowing; 49219a5267003e7dc70100a4bd4f1f449523b2ff38bJim Miller } 49319a5267003e7dc70100a4bd4f1f449523b2ff38bJim Miller 49419a5267003e7dc70100a4bd4f1f449523b2ff38bJim Miller @Override 495eee209313d564be37b8fc068f785b3844cd6597eAdam Powell public boolean isBouncing() { 496eee209313d564be37b8fc068f785b3844cd6597eAdam Powell return mIsBouncing; 497eee209313d564be37b8fc068f785b3844cd6597eAdam Powell } 498eee209313d564be37b8fc068f785b3844cd6597eAdam Powell 499eee209313d564be37b8fc068f785b3844cd6597eAdam Powell @Override 500eee209313d564be37b8fc068f785b3844cd6597eAdam Powell public void showBouncer() { 501eee209313d564be37b8fc068f785b3844cd6597eAdam Powell if (mIsBouncing) return; 502eee209313d564be37b8fc068f785b3844cd6597eAdam Powell showChallenge(true); 503eee209313d564be37b8fc068f785b3844cd6597eAdam Powell mIsBouncing = true; 504eee209313d564be37b8fc068f785b3844cd6597eAdam Powell if (mScrimView != null) { 5056f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell mScrimView.setVisibility(VISIBLE); 506eee209313d564be37b8fc068f785b3844cd6597eAdam Powell } 507cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell 508cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell // Mess with padding/margin to inset the bouncer frame. 509cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell // We have more space available to us otherwise. 510cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell if (mChallengeView != null) { 511cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell if (mFrameDrawable == null || !mFrameDrawable.getPadding(mTempRect)) { 512cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mTempRect.set(0, 0, 0, 0); 513cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } 514cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mChallengeView.setPadding(mTempRect.left, mTempRect.top, mTempRect.right, 515cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mTempRect.bottom); 516cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell final LayoutParams lp = (LayoutParams) mChallengeView.getLayoutParams(); 517cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell lp.leftMargin = lp.rightMargin = getChallengeMargin(false); 518cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mChallengeView.setLayoutParams(lp); 519cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } 520cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell 5216f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell animateFrame(true, true); 522cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell 5230b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell if (mBouncerListener != null) { 5240b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell mBouncerListener.onBouncerStateChanged(true); 5250b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell } 526eee209313d564be37b8fc068f785b3844cd6597eAdam Powell } 527eee209313d564be37b8fc068f785b3844cd6597eAdam Powell 528eee209313d564be37b8fc068f785b3844cd6597eAdam Powell @Override 529eee209313d564be37b8fc068f785b3844cd6597eAdam Powell public void hideBouncer() { 530eee209313d564be37b8fc068f785b3844cd6597eAdam Powell if (!mIsBouncing) return; 531cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell showChallenge(false); 532eee209313d564be37b8fc068f785b3844cd6597eAdam Powell mIsBouncing = false; 533eee209313d564be37b8fc068f785b3844cd6597eAdam Powell if (mScrimView != null) { 534eee209313d564be37b8fc068f785b3844cd6597eAdam Powell mScrimView.setVisibility(GONE); 535eee209313d564be37b8fc068f785b3844cd6597eAdam Powell } 536cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell animateFrame(false, true); 5370b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell if (mBouncerListener != null) { 5380b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell mBouncerListener.onBouncerStateChanged(false); 5390b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell } 540eee209313d564be37b8fc068f785b3844cd6597eAdam Powell } 541eee209313d564be37b8fc068f785b3844cd6597eAdam Powell 542cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell private int getChallengeMargin(boolean expanded) { 543cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell return expanded && mHasGlowpad ? 0 : mDragHandleEdgeSlop; 544cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } 545cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell 546fa668cc930544e8b231c1fbf3ad496374b7aa21cAdam Powell private float getChallengeAlpha() { 547fa668cc930544e8b231c1fbf3ad496374b7aa21cAdam Powell float x = mChallengeOffset - 1; 548fa668cc930544e8b231c1fbf3ad496374b7aa21cAdam Powell return x * x * x + 1.f; 549fa668cc930544e8b231c1fbf3ad496374b7aa21cAdam Powell } 550fa668cc930544e8b231c1fbf3ad496374b7aa21cAdam Powell 551eee209313d564be37b8fc068f785b3844cd6597eAdam Powell @Override 552d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public void requestDisallowInterceptTouchEvent(boolean allowIntercept) { 553d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // We'll intercept whoever we feel like! ...as long as it isn't a challenge view. 554d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // If there are one or more pointers in the challenge view before we take over 555d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // touch events, onInterceptTouchEvent will set mBlockDrag. 556d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 557d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 558d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller @Override 559d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public boolean onInterceptTouchEvent(MotionEvent ev) { 560d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (mVelocityTracker == null) { 561d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mVelocityTracker = VelocityTracker.obtain(); 562d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 563d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mVelocityTracker.addMovement(ev); 564d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 565d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int action = ev.getActionMasked(); 566d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller switch (action) { 567022554e3da6e496524387a5d3ecc67ef9749b587Jim Miller case MotionEvent.ACTION_DOWN: 568c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler mGestureStartX = ev.getX(); 569b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler mGestureStartY = ev.getY(); 570995270f01175234d0615a0e1900576f142a3b4adAdam Powell mBlockDrag = false; 571022554e3da6e496524387a5d3ecc67ef9749b587Jim Miller break; 572022554e3da6e496524387a5d3ecc67ef9749b587Jim Miller 573d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller case MotionEvent.ACTION_CANCEL: 574d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller case MotionEvent.ACTION_UP: 575d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller resetTouch(); 576d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller break; 577d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 578d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller case MotionEvent.ACTION_MOVE: 579d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int count = ev.getPointerCount(); 580d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller for (int i = 0; i < count; i++) { 581d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final float x = ev.getX(i); 582d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final float y = ev.getY(i); 58374bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov if (!mIsBouncing && mActivePointerId == INVALID_POINTER 584c238af5112bee38b3143a65849bd41785c3744b0Adam Powell && ((isInDragHandle(x, y) && MathUtils.sq(x - mGestureStartX) 585c238af5112bee38b3143a65849bd41785c3744b0Adam Powell + MathUtils.sq(y - mGestureStartY) > mTouchSlopSquare) 586c238af5112bee38b3143a65849bd41785c3744b0Adam Powell || crossedDragHandle(x, y, mGestureStartY) 587c238af5112bee38b3143a65849bd41785c3744b0Adam Powell || (isInChallengeView(x, y) && 588c238af5112bee38b3143a65849bd41785c3744b0Adam Powell mScrollState == SCROLL_STATE_SETTLING))) { 589d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mActivePointerId = ev.getPointerId(i); 590c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler mGestureStartX = x; 591c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler mGestureStartY = y; 592b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler mGestureStartChallengeBottom = getChallengeBottom(); 593d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mDragging = true; 594cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mChallengeView.setLayerType(LAYER_TYPE_HARDWARE, null); 595d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } else if (isInChallengeView(x, y)) { 596d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mBlockDrag = true; 597d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 598d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 599d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller break; 600d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 601d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 602d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (mBlockDrag) { 603d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mActivePointerId = INVALID_POINTER; 604d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mDragging = false; 605d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 606d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 607d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return mDragging; 608d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 609d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 610d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private void resetTouch() { 611d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mVelocityTracker.recycle(); 612d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mVelocityTracker = null; 613d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mActivePointerId = INVALID_POINTER; 614d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mDragging = mBlockDrag = false; 615d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 616d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 617d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller @Override 618d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public boolean onTouchEvent(MotionEvent ev) { 619d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (mVelocityTracker == null) { 620d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mVelocityTracker = VelocityTracker.obtain(); 621d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 622d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mVelocityTracker.addMovement(ev); 623d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 624d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int action = ev.getActionMasked(); 625d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller switch (action) { 626995270f01175234d0615a0e1900576f142a3b4adAdam Powell case MotionEvent.ACTION_DOWN: 627995270f01175234d0615a0e1900576f142a3b4adAdam Powell mBlockDrag = false; 628c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler mGestureStartX = ev.getX(); 629995270f01175234d0615a0e1900576f142a3b4adAdam Powell mGestureStartY = ev.getY(); 630995270f01175234d0615a0e1900576f142a3b4adAdam Powell break; 631995270f01175234d0615a0e1900576f142a3b4adAdam Powell 632d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller case MotionEvent.ACTION_CANCEL: 633d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (mDragging) { 634d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller showChallenge(0); 635d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 636d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller resetTouch(); 637d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller break; 638d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 639d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller case MotionEvent.ACTION_POINTER_UP: 640d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (mActivePointerId != ev.getPointerId(ev.getActionIndex())) { 641d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller break; 642d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 643d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller case MotionEvent.ACTION_UP: 64474bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov if (mDragging) { 645d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity); 646d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller showChallenge((int) mVelocityTracker.getYVelocity(mActivePointerId)); 647d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 648d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller resetTouch(); 649d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller break; 650d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 651d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller case MotionEvent.ACTION_MOVE: 6526f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell if (!mDragging && !mBlockDrag && !mIsBouncing) { 653d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int count = ev.getPointerCount(); 654d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller for (int i = 0; i < count; i++) { 655d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final float x = ev.getX(i); 656d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final float y = ev.getY(i); 657d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 658b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler if ((isInDragHandle(x, y) || crossedDragHandle(x, y, mGestureStartY) || 659d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller (isInChallengeView(x, y) && mScrollState == SCROLL_STATE_SETTLING)) 660d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller && mActivePointerId == INVALID_POINTER) { 661c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler mGestureStartX = x; 662b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler mGestureStartY = y; 663d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mActivePointerId = ev.getPointerId(i); 664b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler mGestureStartChallengeBottom = getChallengeBottom(); 665d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mDragging = true; 666cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mChallengeView.setLayerType(LAYER_TYPE_HARDWARE, null); 667d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller break; 668d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 669d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 670d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 671d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // Not an else; this can be set above. 672d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (mDragging) { 673d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // No-op if already in this state, but set it here in case we arrived 674d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // at this point from either intercept or the above. 675d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller setScrollState(SCROLL_STATE_DRAGGING); 676d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 677d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int index = ev.findPointerIndex(mActivePointerId); 678d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (index < 0) { 679d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // Oops, bogus state. We lost some touch events somewhere. 680d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // Just drop it with no velocity and let things settle. 681d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller resetTouch(); 682d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller showChallenge(0); 683d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return true; 684d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 685b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler final float y = ev.getY(index); 686b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler final float pos = Math.min(y - mGestureStartY, 68767625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell getLayoutBottom() - mChallengeBottomBound); 688b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler 689b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler moveChallengeTo(mGestureStartChallengeBottom + (int) pos); 690d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 691d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller break; 692d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 693d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return true; 694d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 695d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 696b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler /** 697cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell * The lifecycle of touch events is subtle and it's very easy to do something 698cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell * that will cause bugs that will be nasty to track when overriding this method. 699cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell * Normally one should always override onInterceptTouchEvent instead. 700cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell * 701cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell * To put it another way, don't try this at home. 702cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell */ 703cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell @Override 704cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell public boolean dispatchTouchEvent(MotionEvent ev) { 705cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell final int action = ev.getActionMasked(); 706cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell boolean handled = false; 707cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell if (action == MotionEvent.ACTION_DOWN) { 708cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell // Defensive programming: if we didn't get the UP or CANCEL, reset anyway. 709cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mEdgeCaptured = false; 710cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } 711cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell if (mWidgetsView != null && !mIsBouncing && (mEdgeCaptured || isEdgeSwipeBeginEvent(ev))) { 712cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell // Normally we would need to do a lot of extra stuff here. 713cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell // We can only get away with this because we haven't padded in 714cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell // the widget pager or otherwise transformed it during layout. 715cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell // We also don't support things like splitting MotionEvents. 716cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell 717cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell // We set handled to captured even if dispatch is returning false here so that 718cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell // we don't send a different view a busted or incomplete event stream. 719cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell handled = mEdgeCaptured |= mWidgetsView.dispatchTouchEvent(ev); 720cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } 721cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell 722cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell if (!handled && !mEdgeCaptured) { 723cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell handled = super.dispatchTouchEvent(ev); 724cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } 725cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell 726cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { 727cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mEdgeCaptured = false; 728cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } 729cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell 730cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell return handled; 731cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } 732cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell 733cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell private boolean isEdgeSwipeBeginEvent(MotionEvent ev) { 734cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell if (ev.getActionMasked() != MotionEvent.ACTION_DOWN) { 735cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell return false; 736cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } 737cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell 738cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell final float x = ev.getX(); 739cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell return x < mDragHandleEdgeSlop || x >= getWidth() - mDragHandleEdgeSlop; 740cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } 741cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell 742cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell /** 743b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler * We only want to add additional vertical space to the drag handle when the panel is fully 744b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler * closed. 745b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler */ 746c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler private int getDragHandleSizeAbove() { 747c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler return isChallengeShowing() ? mDragHandleOpenAbove : mDragHandleClosedAbove; 748c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler } 749c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler private int getDragHandleSizeBelow() { 750c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler return isChallengeShowing() ? mDragHandleOpenBelow : mDragHandleClosedBelow; 751b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler } 752b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler 753d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private boolean isInChallengeView(float x, float y) { 75474bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov return isPointInView(x, y, mChallengeView); 755d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 756d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 757d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private boolean isInDragHandle(float x, float y) { 75874bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov return isPointInView(x, y, mExpandChallengeView); 75974bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov } 760d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 76174bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov private boolean isPointInView(float x, float y, View view) { 76274bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov if (view == null) { 76374bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov return false; 76474bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov } 76574bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov return x >= view.getLeft() && y >= view.getTop() 76674bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov && x < view.getRight() && y < view.getBottom(); 767d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 768d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 769b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler private boolean crossedDragHandle(float x, float y, float initialY) { 770022554e3da6e496524387a5d3ecc67ef9749b587Jim Miller final int challengeTop = mChallengeView.getTop(); 7711bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler return x >= 0 && 7721bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler x < getWidth() && 773c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler initialY < (challengeTop - getDragHandleSizeAbove()) && 774c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler y > challengeTop + getDragHandleSizeBelow(); 775022554e3da6e496524387a5d3ecc67ef9749b587Jim Miller } 776022554e3da6e496524387a5d3ecc67ef9749b587Jim Miller 777d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller @Override 778d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller protected void onMeasure(int widthSpec, int heightSpec) { 779d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (MeasureSpec.getMode(widthSpec) != MeasureSpec.EXACTLY || 780d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller MeasureSpec.getMode(heightSpec) != MeasureSpec.EXACTLY) { 781d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller throw new IllegalArgumentException( 782d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller "SlidingChallengeLayout must be measured with an exact size"); 783d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 784d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 785d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int width = MeasureSpec.getSize(widthSpec); 786d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int height = MeasureSpec.getSize(heightSpec); 787d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller setMeasuredDimension(width, height); 788d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 789d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // Find one and only one challenge view. 790d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final View oldChallengeView = mChallengeView; 79174bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov final View oldExpandChallengeView = mChallengeView; 792d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mChallengeView = null; 79374bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov mExpandChallengeView = null; 794d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int count = getChildCount(); 7958a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen 7968a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen // First iteration through the children finds special children and sets any associated 7978a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen // state. 798d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller for (int i = 0; i < count; i++) { 799d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final View child = getChildAt(i); 800d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 801eee209313d564be37b8fc068f785b3844cd6597eAdam Powell if (lp.childType == LayoutParams.CHILD_TYPE_CHALLENGE) { 802d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (mChallengeView != null) { 803d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller throw new IllegalStateException( 804d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller "There may only be one child with layout_isChallenge=\"true\""); 805d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 806d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mChallengeView = child; 807d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (mChallengeView != oldChallengeView) { 808d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mChallengeView.setVisibility(mChallengeShowing ? VISIBLE : INVISIBLE); 809d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 8106f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell // We're going to play silly games with the frame's background drawable later. 8116f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell mFrameDrawable = mChallengeView.getBackground(); 812cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell if (!mHasLayout) { 813cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell // Set up the margin correctly based on our content for the first run. 814cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mHasGlowpad = child.findViewById(R.id.keyguard_selector_view) != null; 815cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell lp.leftMargin = lp.rightMargin = getChallengeMargin(true); 816cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } 81774bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov } else if (lp.childType == LayoutParams.CHILD_TYPE_EXPAND_CHALLENGE_HANDLE) { 81874bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov if (mExpandChallengeView != null) { 81974bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov throw new IllegalStateException( 82074bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov "There may only be one child with layout_childType" 82174bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov + "=\"expandChallengeHandle\""); 82274bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov } 82374bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov mExpandChallengeView = child; 82474bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov if (mExpandChallengeView != oldExpandChallengeView) { 82574bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov mExpandChallengeView.setVisibility(mChallengeShowing ? INVISIBLE : VISIBLE); 82674bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov mExpandChallengeView.setOnClickListener(mExpandChallengeClickListener); 82774bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov } 828eee209313d564be37b8fc068f785b3844cd6597eAdam Powell } else if (lp.childType == LayoutParams.CHILD_TYPE_SCRIM) { 829eee209313d564be37b8fc068f785b3844cd6597eAdam Powell setScrimView(child); 830cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell } else if (lp.childType == LayoutParams.CHILD_TYPE_WIDGETS) { 831cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell mWidgetsView = child; 832d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 8338a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen } 8348a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen 8355be14ded6762bc51fabbbecb1b2ec01a8c758631Adam Cohen // We want to measure the challenge view first, since the KeyguardWidgetPager 8365be14ded6762bc51fabbbecb1b2ec01a8c758631Adam Cohen // needs to do things its measure pass that are dependent on the challenge view 8375be14ded6762bc51fabbbecb1b2ec01a8c758631Adam Cohen // having been measured. 83874bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov if (mChallengeView != null && mChallengeView.getVisibility() != View.GONE) { 8398a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen measureChildWithMargins(mChallengeView, widthSpec, 0, heightSpec, 0); 8408a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen } 841d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 8428a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen // Measure the rest of the children 8438a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen for (int i = 0; i < count; i++) { 8448a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen final View child = getChildAt(i); 84574bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov if (child.getVisibility() == GONE) { 84674bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov continue; 84774bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov } 8488a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen // Don't measure the challenge view twice! 8498a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen if (child != mChallengeView) { 8508a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen measureChildWithMargins(child, widthSpec, 0, heightSpec, 0); 8518a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen } 852d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 853d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 854d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 855d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller @Override 856d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller protected void onLayout(boolean changed, int l, int t, int r, int b) { 857d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int paddingLeft = getPaddingLeft(); 858d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int paddingTop = getPaddingTop(); 859d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int paddingRight = getPaddingRight(); 860d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int paddingBottom = getPaddingBottom(); 861d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int width = r - l; 862d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int height = b - t; 863d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 864d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int count = getChildCount(); 865d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller for (int i = 0; i < count; i++) { 866d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final View child = getChildAt(i); 867d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 868d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (child.getVisibility() == GONE) continue; 869d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 870d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 871d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 872eee209313d564be37b8fc068f785b3844cd6597eAdam Powell if (lp.childType == LayoutParams.CHILD_TYPE_CHALLENGE) { 873d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // Challenge views pin to the bottom, offset by a portion of their height, 874d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // and center horizontally. 875d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int center = (paddingLeft + width - paddingRight) / 2; 876d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int childWidth = child.getMeasuredWidth(); 877d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int childHeight = child.getMeasuredHeight(); 878d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int left = center - childWidth / 2; 879d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int layoutBottom = height - paddingBottom - lp.bottomMargin; 880d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // We use the top of the challenge view to position the handle, so 881d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // we never want less than the handle size showing at the bottom. 88267625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell final int bottom = layoutBottom + (int) ((childHeight - mChallengeBottomBound) 883d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * (1 - mChallengeOffset)); 884fa668cc930544e8b231c1fbf3ad496374b7aa21cAdam Powell child.setAlpha(getChallengeAlpha()); 885d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller child.layout(left, bottom - childHeight, left + childWidth, bottom); 88674bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov } else if (lp.childType == LayoutParams.CHILD_TYPE_EXPAND_CHALLENGE_HANDLE) { 8870f87a72d59a224c819e18cfed4374f4d484198d6Svetoslav Ganov final int center = (paddingLeft + width - paddingRight) / 2; 8880f87a72d59a224c819e18cfed4374f4d484198d6Svetoslav Ganov final int left = center - child.getMeasuredWidth() / 2; 8890f87a72d59a224c819e18cfed4374f4d484198d6Svetoslav Ganov final int right = left + child.getMeasuredWidth(); 8900f87a72d59a224c819e18cfed4374f4d484198d6Svetoslav Ganov final int bottom = height - paddingBottom - lp.bottomMargin; 8910f87a72d59a224c819e18cfed4374f4d484198d6Svetoslav Ganov final int top = bottom - child.getMeasuredHeight(); 8920f87a72d59a224c819e18cfed4374f4d484198d6Svetoslav Ganov child.layout(left, top, right, bottom); 893d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } else { 894d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller // Non-challenge views lay out from the upper left, layered. 895d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller child.layout(paddingLeft + lp.leftMargin, 896d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller paddingTop + lp.topMargin, 897d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller paddingLeft + child.getMeasuredWidth(), 898d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller paddingTop + child.getMeasuredHeight()); 899d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 900d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 901d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 902d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (!mHasLayout) { 90367625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell if (mFrameDrawable != null) { 90467625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell mFrameDrawable.setAlpha(0); 90567625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell } 9066f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell mHasLayout = true; 907d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 908d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 909d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 910d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller @Override 911d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public void draw(Canvas c) { 912d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller super.draw(c); 9131bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler if (DEBUG) { 91474bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov final Paint debugPaint = new Paint(); 9151bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler debugPaint.setColor(0x40FF00CC); 9161bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler // show the isInDragHandle() rect 9171bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler c.drawRect(mDragHandleEdgeSlop, 918c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler mChallengeView.getTop() - getDragHandleSizeAbove(), 9191bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler getWidth() - mDragHandleEdgeSlop, 920c606bf1af953bb8a682589a29809e714c648c291Daniel Sandler mChallengeView.getTop() + getDragHandleSizeBelow(), 9211bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler debugPaint); 9221bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler } 92374bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov } 9241bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler 92574bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov public void computeScroll() { 92674bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov super.computeScroll(); 9276f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell 92874bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov if (!mScroller.isFinished()) { 92974bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov if (mChallengeView == null) { 93074bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov // Can't scroll if the view is missing. 93174bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov Log.e(TAG, "Challenge view missing in computeScroll"); 93274bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov mScroller.abortAnimation(); 93374bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov return; 9341bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler } 9351bfcc82184824c8dc648a0948303f4b3611ac087Daniel Sandler 93674bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov mScroller.computeScrollOffset(); 93774bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov moveChallengeTo(mScroller.getCurrY()); 93874bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov 93974bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov if (mScroller.isFinished()) { 94074bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov post(mEndScrollRunnable); 9416f35209e728a7a9a56afbbdefd3d7bfa1e05ea73Adam Powell } 942d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 943d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 944d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 945e3643138c89d49a01ba6a622ffaf71c9a95d5cdcAdam Cohen public int getMaxChallengeTop() { 946e3643138c89d49a01ba6a622ffaf71c9a95d5cdcAdam Cohen if (mChallengeView == null) return 0; 947e3643138c89d49a01ba6a622ffaf71c9a95d5cdcAdam Cohen 948e3643138c89d49a01ba6a622ffaf71c9a95d5cdcAdam Cohen final int layoutBottom = getLayoutBottom(); 9498a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen final int challengeHeight = mChallengeView.getMeasuredHeight(); 950e3643138c89d49a01ba6a622ffaf71c9a95d5cdcAdam Cohen return layoutBottom - challengeHeight; 951e3643138c89d49a01ba6a622ffaf71c9a95d5cdcAdam Cohen } 952e3643138c89d49a01ba6a622ffaf71c9a95d5cdcAdam Cohen 953d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller /** 954d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * Move the bottom edge of mChallengeView to a new position and notify the listener 955d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * if it represents a change in position. Changes made through this method will 956d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * be stable across layout passes. If this method is called before first layout of 957d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * this SlidingChallengeLayout it will have no effect. 958d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * 959d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * @param bottom New bottom edge in px in this SlidingChallengeLayout's coordinate system. 960d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * @return true if the challenge view was moved 961d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller */ 962d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private boolean moveChallengeTo(int bottom) { 963d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (mChallengeView == null || !mHasLayout) { 964d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return false; 965d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 966d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 967b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler final int layoutBottom = getLayoutBottom(); 968d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final int challengeHeight = mChallengeView.getHeight(); 969d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 970d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller bottom = Math.max(layoutBottom, 97167625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell Math.min(bottom, layoutBottom + challengeHeight - mChallengeBottomBound)); 972d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 97367625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell float offset = 1.f - (float) (bottom - layoutBottom) / 97467625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell (challengeHeight - mChallengeBottomBound); 975d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mChallengeOffset = offset; 976d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (offset > 0 && !mChallengeShowing) { 977d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller setChallengeShowing(true); 978d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 979d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 980d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller mChallengeView.layout(mChallengeView.getLeft(), 981d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller bottom - mChallengeView.getHeight(), mChallengeView.getRight(), bottom); 982d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 983fa668cc930544e8b231c1fbf3ad496374b7aa21cAdam Powell mChallengeView.setAlpha(getChallengeAlpha()); 9840b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell if (mScrollListener != null) { 9850b1b552268bc6641cc5d01fb80c12258da9c6985Adam Powell mScrollListener.onScrollPositionChanged(offset, mChallengeView.getTop()); 986d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 987d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller postInvalidateOnAnimation(); 988d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return true; 989d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 990d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 991b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler /** 992b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler * The bottom edge of this SlidingChallengeLayout's coordinate system; will coincide with 993b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler * the bottom edge of mChallengeView when the challenge is fully opened. 994b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler */ 995b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler private int getLayoutBottom() { 996b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler final int bottomMargin = (mChallengeView == null) 997b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler ? 0 998b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler : ((LayoutParams) mChallengeView.getLayoutParams()).bottomMargin; 9998a7785c7aa2df74203276299e10b0d9056cd0560Adam Cohen final int layoutBottom = getMeasuredHeight() - getPaddingBottom() - bottomMargin; 1000b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler return layoutBottom; 1001b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler } 1002b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler 1003b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler /** 1004b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler * The bottom edge of mChallengeView; essentially, where the sliding challenge 'is'. 1005b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler */ 1006d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private int getChallengeBottom() { 1007d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (mChallengeView == null) return 0; 1008d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1009d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return mChallengeView.getBottom(); 1010d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1011d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1012b42b842ee873160acf317fc3ff6339243514b008Daniel Sandler /** 1013d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * Show or hide the challenge view, animating it if necessary. 1014d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller * @param show true to show, false to hide 1015d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller */ 1016d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public void showChallenge(boolean show) { 1017d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller showChallenge(show, 0); 1018995270f01175234d0615a0e1900576f142a3b4adAdam Powell if (!show) { 1019995270f01175234d0615a0e1900576f142a3b4adAdam Powell // Block any drags in progress so that callers can use this to disable dragging 1020995270f01175234d0615a0e1900576f142a3b4adAdam Powell // for other touch interactions. 1021995270f01175234d0615a0e1900576f142a3b4adAdam Powell mBlockDrag = true; 1022995270f01175234d0615a0e1900576f142a3b4adAdam Powell } 1023d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1024d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1025d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private void showChallenge(int velocity) { 1026d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller boolean show = false; 1027d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (Math.abs(velocity) > mMinVelocity) { 1028d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller show = velocity < 0; 1029d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } else { 1030d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller show = mChallengeOffset >= 0.5f; 1031d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1032d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller showChallenge(show, velocity); 1033d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1034d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1035d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller private void showChallenge(boolean show, int velocity) { 1036d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (mChallengeView == null) { 1037d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller setChallengeShowing(false); 1038d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return; 1039d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1040d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1041d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller if (mHasLayout) { 104267625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell final int layoutBottom = getLayoutBottom(); 1043d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller animateChallengeTo(show ? layoutBottom : 104467625e29208a97afeb8dca22a73c52ad7b4619baAdam Powell layoutBottom + mChallengeView.getHeight() - mChallengeBottomBound, velocity); 1045d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1046d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1047d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 104819a5267003e7dc70100a4bd4f1f449523b2ff38bJim Miller @Override 1049d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { 1050d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return new LayoutParams(getContext(), attrs); 1051d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1052d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1053d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller @Override 1054d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 1055d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return p instanceof LayoutParams ? new LayoutParams((LayoutParams) p) : 1056d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller p instanceof MarginLayoutParams ? new LayoutParams((MarginLayoutParams) p) : 1057d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller new LayoutParams(p); 1058d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1059d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1060d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller @Override 1061d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller protected ViewGroup.LayoutParams generateDefaultLayoutParams() { 1062d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return new LayoutParams(); 1063d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1064d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1065d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller @Override 1066d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 1067d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller return p instanceof LayoutParams; 1068d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1069d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1070d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public static class LayoutParams extends MarginLayoutParams { 1071eee209313d564be37b8fc068f785b3844cd6597eAdam Powell public int childType = CHILD_TYPE_NONE; 1072eee209313d564be37b8fc068f785b3844cd6597eAdam Powell public static final int CHILD_TYPE_NONE = 0; 1073eee209313d564be37b8fc068f785b3844cd6597eAdam Powell public static final int CHILD_TYPE_CHALLENGE = 2; 1074eee209313d564be37b8fc068f785b3844cd6597eAdam Powell public static final int CHILD_TYPE_SCRIM = 4; 1075cdf8b487456115a1bcc626f53b8da63308dc42ddAdam Powell public static final int CHILD_TYPE_WIDGETS = 5; 107674bdd21629681528dbe7f3ea363d99c8514e026bSvetoslav Ganov public static final int CHILD_TYPE_EXPAND_CHALLENGE_HANDLE = 6; 1077d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1078d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public LayoutParams() { 1079d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller this(MATCH_PARENT, WRAP_CONTENT); 1080d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1081d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1082d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public LayoutParams(int width, int height) { 1083d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller super(width, height); 1084d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1085d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1086d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public LayoutParams(android.view.ViewGroup.LayoutParams source) { 1087d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller super(source); 1088d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1089d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1090d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public LayoutParams(MarginLayoutParams source) { 1091d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller super(source); 1092d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1093d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1094d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public LayoutParams(LayoutParams source) { 1095d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller super(source); 1096d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1097eee209313d564be37b8fc068f785b3844cd6597eAdam Powell childType = source.childType; 1098d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1099d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1100d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller public LayoutParams(Context c, AttributeSet attrs) { 1101d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller super(c, attrs); 1102d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller 1103d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller final TypedArray a = c.obtainStyledAttributes(attrs, 1104d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller R.styleable.SlidingChallengeLayout_Layout); 1105eee209313d564be37b8fc068f785b3844cd6597eAdam Powell childType = a.getInt(R.styleable.SlidingChallengeLayout_Layout_layout_childType, 1106eee209313d564be37b8fc068f785b3844cd6597eAdam Powell CHILD_TYPE_NONE); 1107d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller a.recycle(); 1108d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1109d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller } 1110d6523da1ad7bae805a3dbea8d7b398d86cd3c181Jim Miller} 1111