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