• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.systemui.statusbar.phone;
18 
19 import android.animation.Animator;
20 import android.animation.AnimatorListenerAdapter;
21 import android.animation.ValueAnimator;
22 import android.content.Context;
23 import android.view.MotionEvent;
24 import android.view.VelocityTracker;
25 import android.view.View;
26 import android.view.ViewConfiguration;
27 import android.view.animation.AnimationUtils;
28 import android.view.animation.Interpolator;
29 
30 import com.android.systemui.R;
31 import com.android.systemui.statusbar.FlingAnimationUtils;
32 import com.android.systemui.statusbar.KeyguardAffordanceView;
33 
34 /**
35  * A touch handler of the keyguard which is responsible for launching phone and camera affordances.
36  */
37 public class KeyguardAffordanceHelper {
38 
39     public static final float SWIPE_RESTING_ALPHA_AMOUNT = 0.5f;
40     public static final long HINT_PHASE1_DURATION = 200;
41     private static final long HINT_PHASE2_DURATION = 350;
42     private static final float BACKGROUND_RADIUS_SCALE_FACTOR = 0.25f;
43     private static final int HINT_CIRCLE_OPEN_DURATION = 500;
44 
45     private final Context mContext;
46 
47     private FlingAnimationUtils mFlingAnimationUtils;
48     private Callback mCallback;
49     private VelocityTracker mVelocityTracker;
50     private boolean mSwipingInProgress;
51     private float mInitialTouchX;
52     private float mInitialTouchY;
53     private float mTranslation;
54     private float mTranslationOnDown;
55     private int mTouchSlop;
56     private int mMinTranslationAmount;
57     private int mMinFlingVelocity;
58     private int mHintGrowAmount;
59     private KeyguardAffordanceView mLeftIcon;
60     private KeyguardAffordanceView mCenterIcon;
61     private KeyguardAffordanceView mRightIcon;
62     private Interpolator mAppearInterpolator;
63     private Interpolator mDisappearInterpolator;
64     private Animator mSwipeAnimator;
65     private int mMinBackgroundRadius;
66     private boolean mMotionCancelled;
67     private int mTouchTargetSize;
68     private View mTargetedView;
69     private boolean mTouchSlopExeeded;
70     private AnimatorListenerAdapter mFlingEndListener = new AnimatorListenerAdapter() {
71         @Override
72         public void onAnimationEnd(Animator animation) {
73             mSwipeAnimator = null;
74             mSwipingInProgress = false;
75             mTargetedView = null;
76         }
77     };
78     private Runnable mAnimationEndRunnable = new Runnable() {
79         @Override
80         public void run() {
81             mCallback.onAnimationToSideEnded();
82         }
83     };
84 
KeyguardAffordanceHelper(Callback callback, Context context)85     KeyguardAffordanceHelper(Callback callback, Context context) {
86         mContext = context;
87         mCallback = callback;
88         initIcons();
89         updateIcon(mLeftIcon, 0.0f, mLeftIcon.getRestingAlpha(), false, false, true, false);
90         updateIcon(mCenterIcon, 0.0f, mCenterIcon.getRestingAlpha(), false, false, true, false);
91         updateIcon(mRightIcon, 0.0f, mRightIcon.getRestingAlpha(), false, false, true, false);
92         initDimens();
93     }
94 
initDimens()95     private void initDimens() {
96         final ViewConfiguration configuration = ViewConfiguration.get(mContext);
97         mTouchSlop = configuration.getScaledPagingTouchSlop();
98         mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity();
99         mMinTranslationAmount = mContext.getResources().getDimensionPixelSize(
100                 R.dimen.keyguard_min_swipe_amount);
101         mMinBackgroundRadius = mContext.getResources().getDimensionPixelSize(
102                 R.dimen.keyguard_affordance_min_background_radius);
103         mTouchTargetSize = mContext.getResources().getDimensionPixelSize(
104                 R.dimen.keyguard_affordance_touch_target_size);
105         mHintGrowAmount =
106                 mContext.getResources().getDimensionPixelSize(R.dimen.hint_grow_amount_sideways);
107         mFlingAnimationUtils = new FlingAnimationUtils(mContext, 0.4f);
108         mAppearInterpolator = AnimationUtils.loadInterpolator(mContext,
109                 android.R.interpolator.linear_out_slow_in);
110         mDisappearInterpolator = AnimationUtils.loadInterpolator(mContext,
111                 android.R.interpolator.fast_out_linear_in);
112     }
113 
initIcons()114     private void initIcons() {
115         mLeftIcon = mCallback.getLeftIcon();
116         mCenterIcon = mCallback.getCenterIcon();
117         mRightIcon = mCallback.getRightIcon();
118         updatePreviews();
119     }
120 
updatePreviews()121     public void updatePreviews() {
122         mLeftIcon.setPreviewView(mCallback.getLeftPreview());
123         mRightIcon.setPreviewView(mCallback.getRightPreview());
124     }
125 
onTouchEvent(MotionEvent event)126     public boolean onTouchEvent(MotionEvent event) {
127         int action = event.getActionMasked();
128         if (mMotionCancelled && action != MotionEvent.ACTION_DOWN) {
129             return false;
130         }
131         final float y = event.getY();
132         final float x = event.getX();
133 
134         boolean isUp = false;
135         switch (action) {
136             case MotionEvent.ACTION_DOWN:
137                 View targetView = getIconAtPosition(x, y);
138                 if (targetView == null || (mTargetedView != null && mTargetedView != targetView)) {
139                     mMotionCancelled = true;
140                     return false;
141                 }
142                 if (mTargetedView != null) {
143                     cancelAnimation();
144                 } else {
145                     mTouchSlopExeeded = false;
146                 }
147                 startSwiping(targetView);
148                 mInitialTouchX = x;
149                 mInitialTouchY = y;
150                 mTranslationOnDown = mTranslation;
151                 initVelocityTracker();
152                 trackMovement(event);
153                 mMotionCancelled = false;
154                 break;
155             case MotionEvent.ACTION_POINTER_DOWN:
156                 mMotionCancelled = true;
157                 endMotion(true /* forceSnapBack */, x, y);
158                 break;
159             case MotionEvent.ACTION_MOVE:
160                 trackMovement(event);
161                 float xDist = x - mInitialTouchX;
162                 float yDist = y - mInitialTouchY;
163                 float distance = (float) Math.hypot(xDist, yDist);
164                 if (!mTouchSlopExeeded && distance > mTouchSlop) {
165                     mTouchSlopExeeded = true;
166                 }
167                 if (mSwipingInProgress) {
168                     if (mTargetedView == mRightIcon) {
169                         distance = mTranslationOnDown - distance;
170                         distance = Math.min(0, distance);
171                     } else {
172                         distance = mTranslationOnDown + distance;
173                         distance = Math.max(0, distance);
174                     }
175                     setTranslation(distance, false /* isReset */, false /* animateReset */);
176                 }
177                 break;
178 
179             case MotionEvent.ACTION_UP:
180                 isUp = true;
181             case MotionEvent.ACTION_CANCEL:
182                 boolean hintOnTheRight = mTargetedView == mRightIcon;
183                 trackMovement(event);
184                 endMotion(!isUp, x, y);
185                 if (!mTouchSlopExeeded && isUp) {
186                     mCallback.onIconClicked(hintOnTheRight);
187                 }
188                 break;
189         }
190         return true;
191     }
192 
startSwiping(View targetView)193     private void startSwiping(View targetView) {
194         mCallback.onSwipingStarted(targetView == mRightIcon);
195         mSwipingInProgress = true;
196         mTargetedView = targetView;
197     }
198 
getIconAtPosition(float x, float y)199     private View getIconAtPosition(float x, float y) {
200         if (leftSwipePossible() && isOnIcon(mLeftIcon, x, y)) {
201             return mLeftIcon;
202         }
203         if (rightSwipePossible() && isOnIcon(mRightIcon, x, y)) {
204             return mRightIcon;
205         }
206         return null;
207     }
208 
isOnAffordanceIcon(float x, float y)209     public boolean isOnAffordanceIcon(float x, float y) {
210         return isOnIcon(mLeftIcon, x, y) || isOnIcon(mRightIcon, x, y);
211     }
212 
isOnIcon(View icon, float x, float y)213     private boolean isOnIcon(View icon, float x, float y) {
214         float iconX = icon.getX() + icon.getWidth() / 2.0f;
215         float iconY = icon.getY() + icon.getHeight() / 2.0f;
216         double distance = Math.hypot(x - iconX, y - iconY);
217         return distance <= mTouchTargetSize / 2;
218     }
219 
endMotion(boolean forceSnapBack, float lastX, float lastY)220     private void endMotion(boolean forceSnapBack, float lastX, float lastY) {
221         if (mSwipingInProgress) {
222             flingWithCurrentVelocity(forceSnapBack, lastX, lastY);
223         } else {
224             mTargetedView = null;
225         }
226         if (mVelocityTracker != null) {
227             mVelocityTracker.recycle();
228             mVelocityTracker = null;
229         }
230     }
231 
rightSwipePossible()232     private boolean rightSwipePossible() {
233         return mRightIcon.getVisibility() == View.VISIBLE;
234     }
235 
leftSwipePossible()236     private boolean leftSwipePossible() {
237         return mLeftIcon.getVisibility() == View.VISIBLE;
238     }
239 
onInterceptTouchEvent(MotionEvent ev)240     public boolean onInterceptTouchEvent(MotionEvent ev) {
241         return false;
242     }
243 
startHintAnimation(boolean right, Runnable onFinishedListener)244     public void startHintAnimation(boolean right,
245             Runnable onFinishedListener) {
246         cancelAnimation();
247         startHintAnimationPhase1(right, onFinishedListener);
248     }
249 
startHintAnimationPhase1(final boolean right, final Runnable onFinishedListener)250     private void startHintAnimationPhase1(final boolean right, final Runnable onFinishedListener) {
251         final KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon;
252         ValueAnimator animator = getAnimatorToRadius(right, mHintGrowAmount);
253         animator.addListener(new AnimatorListenerAdapter() {
254             private boolean mCancelled;
255 
256             @Override
257             public void onAnimationCancel(Animator animation) {
258                 mCancelled = true;
259             }
260 
261             @Override
262             public void onAnimationEnd(Animator animation) {
263                 if (mCancelled) {
264                     mSwipeAnimator = null;
265                     mTargetedView = null;
266                     onFinishedListener.run();
267                 } else {
268                     startUnlockHintAnimationPhase2(right, onFinishedListener);
269                 }
270             }
271         });
272         animator.setInterpolator(mAppearInterpolator);
273         animator.setDuration(HINT_PHASE1_DURATION);
274         animator.start();
275         mSwipeAnimator = animator;
276         mTargetedView = targetView;
277     }
278 
279     /**
280      * Phase 2: Move back.
281      */
startUnlockHintAnimationPhase2(boolean right, final Runnable onFinishedListener)282     private void startUnlockHintAnimationPhase2(boolean right, final Runnable onFinishedListener) {
283         ValueAnimator animator = getAnimatorToRadius(right, 0);
284         animator.addListener(new AnimatorListenerAdapter() {
285             @Override
286             public void onAnimationEnd(Animator animation) {
287                 mSwipeAnimator = null;
288                 mTargetedView = null;
289                 onFinishedListener.run();
290             }
291         });
292         animator.setInterpolator(mDisappearInterpolator);
293         animator.setDuration(HINT_PHASE2_DURATION);
294         animator.setStartDelay(HINT_CIRCLE_OPEN_DURATION);
295         animator.start();
296         mSwipeAnimator = animator;
297     }
298 
getAnimatorToRadius(final boolean right, int radius)299     private ValueAnimator getAnimatorToRadius(final boolean right, int radius) {
300         final KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon;
301         ValueAnimator animator = ValueAnimator.ofFloat(targetView.getCircleRadius(), radius);
302         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
303             @Override
304             public void onAnimationUpdate(ValueAnimator animation) {
305                 float newRadius = (float) animation.getAnimatedValue();
306                 targetView.setCircleRadiusWithoutAnimation(newRadius);
307                 float translation = getTranslationFromRadius(newRadius);
308                 mTranslation = right ? -translation : translation;
309                 updateIconsFromTranslation(targetView);
310             }
311         });
312         return animator;
313     }
314 
cancelAnimation()315     private void cancelAnimation() {
316         if (mSwipeAnimator != null) {
317             mSwipeAnimator.cancel();
318         }
319     }
320 
flingWithCurrentVelocity(boolean forceSnapBack, float lastX, float lastY)321     private void flingWithCurrentVelocity(boolean forceSnapBack, float lastX, float lastY) {
322         float vel = getCurrentVelocity(lastX, lastY);
323 
324         // We snap back if the current translation is not far enough
325         boolean snapBack = isBelowFalsingThreshold();
326 
327         // or if the velocity is in the opposite direction.
328         boolean velIsInWrongDirection = vel * mTranslation < 0;
329         snapBack |= Math.abs(vel) > mMinFlingVelocity && velIsInWrongDirection;
330         vel = snapBack ^ velIsInWrongDirection ? 0 : vel;
331         fling(vel, snapBack || forceSnapBack, mTranslation < 0);
332     }
333 
isBelowFalsingThreshold()334     private boolean isBelowFalsingThreshold() {
335         return Math.abs(mTranslation) < Math.abs(mTranslationOnDown) + getMinTranslationAmount();
336     }
337 
getMinTranslationAmount()338     private int getMinTranslationAmount() {
339         float factor = mCallback.getAffordanceFalsingFactor();
340         return (int) (mMinTranslationAmount * factor);
341     }
342 
fling(float vel, final boolean snapBack, boolean right)343     private void fling(float vel, final boolean snapBack, boolean right) {
344         float target = right ? -mCallback.getMaxTranslationDistance()
345                 : mCallback.getMaxTranslationDistance();
346         target = snapBack ? 0 : target;
347 
348         ValueAnimator animator = ValueAnimator.ofFloat(mTranslation, target);
349         mFlingAnimationUtils.apply(animator, mTranslation, target, vel);
350         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
351             @Override
352             public void onAnimationUpdate(ValueAnimator animation) {
353                 mTranslation = (float) animation.getAnimatedValue();
354             }
355         });
356         animator.addListener(mFlingEndListener);
357         if (!snapBack) {
358             startFinishingCircleAnimation(vel * 0.375f, mAnimationEndRunnable, right);
359             mCallback.onAnimationToSideStarted(right, mTranslation, vel);
360         } else {
361             reset(true);
362         }
363         animator.start();
364         mSwipeAnimator = animator;
365         if (snapBack) {
366             mCallback.onSwipingAborted();
367         }
368     }
369 
startFinishingCircleAnimation(float velocity, Runnable mAnimationEndRunnable, boolean right)370     private void startFinishingCircleAnimation(float velocity, Runnable mAnimationEndRunnable,
371             boolean right) {
372         KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon;
373         targetView.finishAnimation(velocity, mAnimationEndRunnable);
374     }
375 
setTranslation(float translation, boolean isReset, boolean animateReset)376     private void setTranslation(float translation, boolean isReset, boolean animateReset) {
377         translation = rightSwipePossible() ? translation : Math.max(0, translation);
378         translation = leftSwipePossible() ? translation : Math.min(0, translation);
379         float absTranslation = Math.abs(translation);
380         if (translation != mTranslation || isReset) {
381             KeyguardAffordanceView targetView = translation > 0 ? mLeftIcon : mRightIcon;
382             KeyguardAffordanceView otherView = translation > 0 ? mRightIcon : mLeftIcon;
383             float alpha = absTranslation / getMinTranslationAmount();
384 
385             // We interpolate the alpha of the other icons to 0
386             float fadeOutAlpha = 1.0f - alpha;
387             fadeOutAlpha = Math.max(fadeOutAlpha, 0.0f);
388 
389             boolean animateIcons = isReset && animateReset;
390             boolean forceNoCircleAnimation = isReset && !animateReset;
391             float radius = getRadiusFromTranslation(absTranslation);
392             boolean slowAnimation = isReset && isBelowFalsingThreshold();
393             if (!isReset) {
394                 updateIcon(targetView, radius, alpha + fadeOutAlpha * targetView.getRestingAlpha(),
395                         false, false, false, false);
396             } else {
397                 updateIcon(targetView, 0.0f, fadeOutAlpha * targetView.getRestingAlpha(),
398                         animateIcons, slowAnimation, false, forceNoCircleAnimation);
399             }
400             updateIcon(otherView, 0.0f, fadeOutAlpha * otherView.getRestingAlpha(),
401                     animateIcons, slowAnimation, false, forceNoCircleAnimation);
402             updateIcon(mCenterIcon, 0.0f, fadeOutAlpha * mCenterIcon.getRestingAlpha(),
403                     animateIcons, slowAnimation, false, forceNoCircleAnimation);
404 
405             mTranslation = translation;
406         }
407     }
408 
updateIconsFromTranslation(KeyguardAffordanceView targetView)409     private void updateIconsFromTranslation(KeyguardAffordanceView targetView) {
410         float absTranslation = Math.abs(mTranslation);
411         float alpha = absTranslation / getMinTranslationAmount();
412 
413         // We interpolate the alpha of the other icons to 0
414         float fadeOutAlpha =  1.0f - alpha;
415         fadeOutAlpha = Math.max(0.0f, fadeOutAlpha);
416 
417         // We interpolate the alpha of the targetView to 1
418         KeyguardAffordanceView otherView = targetView == mRightIcon ? mLeftIcon : mRightIcon;
419         updateIconAlpha(targetView, alpha + fadeOutAlpha * targetView.getRestingAlpha(), false);
420         updateIconAlpha(otherView, fadeOutAlpha * otherView.getRestingAlpha(), false);
421         updateIconAlpha(mCenterIcon, fadeOutAlpha * mCenterIcon.getRestingAlpha(), false);
422     }
423 
getTranslationFromRadius(float circleSize)424     private float getTranslationFromRadius(float circleSize) {
425         float translation = (circleSize - mMinBackgroundRadius)
426                 / BACKGROUND_RADIUS_SCALE_FACTOR;
427         return translation > 0.0f ? translation + mTouchSlop : 0.0f;
428     }
429 
getRadiusFromTranslation(float translation)430     private float getRadiusFromTranslation(float translation) {
431         if (translation <= mTouchSlop) {
432             return 0.0f;
433         }
434         return (translation - mTouchSlop)  * BACKGROUND_RADIUS_SCALE_FACTOR + mMinBackgroundRadius;
435     }
436 
animateHideLeftRightIcon()437     public void animateHideLeftRightIcon() {
438         cancelAnimation();
439         updateIcon(mRightIcon, 0f, 0f, true, false, false, false);
440         updateIcon(mLeftIcon, 0f, 0f, true, false, false, false);
441     }
442 
updateIcon(KeyguardAffordanceView view, float circleRadius, float alpha, boolean animate, boolean slowRadiusAnimation, boolean force, boolean forceNoCircleAnimation)443     private void updateIcon(KeyguardAffordanceView view, float circleRadius, float alpha,
444                             boolean animate, boolean slowRadiusAnimation, boolean force,
445                             boolean forceNoCircleAnimation) {
446         if (view.getVisibility() != View.VISIBLE && !force) {
447             return;
448         }
449         if (forceNoCircleAnimation) {
450             view.setCircleRadiusWithoutAnimation(circleRadius);
451         } else {
452             view.setCircleRadius(circleRadius, slowRadiusAnimation);
453         }
454         updateIconAlpha(view, alpha, animate);
455     }
456 
updateIconAlpha(KeyguardAffordanceView view, float alpha, boolean animate)457     private void updateIconAlpha(KeyguardAffordanceView view, float alpha, boolean animate) {
458         float scale = getScale(alpha, view);
459         alpha = Math.min(1.0f, alpha);
460         view.setImageAlpha(alpha, animate);
461         view.setImageScale(scale, animate);
462     }
463 
getScale(float alpha, KeyguardAffordanceView icon)464     private float getScale(float alpha, KeyguardAffordanceView icon) {
465         float scale = alpha / icon.getRestingAlpha() * 0.2f +
466                 KeyguardAffordanceView.MIN_ICON_SCALE_AMOUNT;
467         return Math.min(scale, KeyguardAffordanceView.MAX_ICON_SCALE_AMOUNT);
468     }
469 
trackMovement(MotionEvent event)470     private void trackMovement(MotionEvent event) {
471         if (mVelocityTracker != null) {
472             mVelocityTracker.addMovement(event);
473         }
474     }
475 
initVelocityTracker()476     private void initVelocityTracker() {
477         if (mVelocityTracker != null) {
478             mVelocityTracker.recycle();
479         }
480         mVelocityTracker = VelocityTracker.obtain();
481     }
482 
getCurrentVelocity(float lastX, float lastY)483     private float getCurrentVelocity(float lastX, float lastY) {
484         if (mVelocityTracker == null) {
485             return 0;
486         }
487         mVelocityTracker.computeCurrentVelocity(1000);
488         float aX = mVelocityTracker.getXVelocity();
489         float aY = mVelocityTracker.getYVelocity();
490         float bX = lastX - mInitialTouchX;
491         float bY = lastY - mInitialTouchY;
492         float bLen = (float) Math.hypot(bX, bY);
493         // Project the velocity onto the distance vector: a * b / |b|
494         float projectedVelocity = (aX * bX + aY * bY) / bLen;
495         if (mTargetedView == mRightIcon) {
496             projectedVelocity = -projectedVelocity;
497         }
498         return projectedVelocity;
499     }
500 
onConfigurationChanged()501     public void onConfigurationChanged() {
502         initDimens();
503         initIcons();
504     }
505 
onRtlPropertiesChanged()506     public void onRtlPropertiesChanged() {
507         initIcons();
508     }
509 
reset(boolean animate)510     public void reset(boolean animate) {
511         cancelAnimation();
512         setTranslation(0.0f, true, animate);
513         mMotionCancelled = true;
514         if (mSwipingInProgress) {
515             mCallback.onSwipingAborted();
516             mSwipingInProgress = false;
517         }
518     }
519 
isSwipingInProgress()520     public boolean isSwipingInProgress() {
521         return mSwipingInProgress;
522     }
523 
launchAffordance(boolean animate, boolean left)524     public void launchAffordance(boolean animate, boolean left) {
525         if (mSwipingInProgress) {
526             // We don't want to mess with the state if the user is actually swiping already.
527             return;
528         }
529         KeyguardAffordanceView targetView = left ? mLeftIcon : mRightIcon;
530         KeyguardAffordanceView otherView = left ? mRightIcon : mLeftIcon;
531         startSwiping(targetView);
532         if (animate) {
533             fling(0, false, !left);
534             updateIcon(otherView, 0.0f, 0, true, false, true, false);
535             updateIcon(mCenterIcon, 0.0f, 0, true, false, true, false);
536         } else {
537             mCallback.onAnimationToSideStarted(!left, mTranslation, 0);
538             mTranslation = left ? mCallback.getMaxTranslationDistance()
539                     : mCallback.getMaxTranslationDistance();
540             updateIcon(mCenterIcon, 0.0f, 0.0f, false, false, true, false);
541             updateIcon(otherView, 0.0f, 0.0f, false, false, true, false);
542             targetView.instantFinishAnimation();
543             mFlingEndListener.onAnimationEnd(null);
544             mAnimationEndRunnable.run();
545         }
546     }
547 
548     public interface Callback {
549 
550         /**
551          * Notifies the callback when an animation to a side page was started.
552          *
553          * @param rightPage Is the page animated to the right page?
554          */
onAnimationToSideStarted(boolean rightPage, float translation, float vel)555         void onAnimationToSideStarted(boolean rightPage, float translation, float vel);
556 
557         /**
558          * Notifies the callback the animation to a side page has ended.
559          */
onAnimationToSideEnded()560         void onAnimationToSideEnded();
561 
getMaxTranslationDistance()562         float getMaxTranslationDistance();
563 
onSwipingStarted(boolean rightIcon)564         void onSwipingStarted(boolean rightIcon);
565 
onSwipingAborted()566         void onSwipingAborted();
567 
onIconClicked(boolean rightIcon)568         void onIconClicked(boolean rightIcon);
569 
getLeftIcon()570         KeyguardAffordanceView getLeftIcon();
571 
getCenterIcon()572         KeyguardAffordanceView getCenterIcon();
573 
getRightIcon()574         KeyguardAffordanceView getRightIcon();
575 
getLeftPreview()576         View getLeftPreview();
577 
getRightPreview()578         View getRightPreview();
579 
580         /**
581          * @return The factor the minimum swipe amount should be multiplied with.
582          */
getAffordanceFalsingFactor()583         float getAffordanceFalsingFactor();
584     }
585 }
586