summaryrefslogtreecommitdiff
path: root/java/com/android/newbubble/NewMoveHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android/newbubble/NewMoveHandler.java')
-rw-r--r--java/com/android/newbubble/NewMoveHandler.java334
1 files changed, 0 insertions, 334 deletions
diff --git a/java/com/android/newbubble/NewMoveHandler.java b/java/com/android/newbubble/NewMoveHandler.java
deleted file mode 100644
index 12e099c3a..000000000
--- a/java/com/android/newbubble/NewMoveHandler.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.newbubble;
-
-import android.content.Context;
-import android.graphics.Point;
-import android.support.animation.FloatPropertyCompat;
-import android.support.animation.SpringAnimation;
-import android.support.animation.SpringForce;
-import android.support.annotation.NonNull;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.View.OnTouchListener;
-import android.view.ViewConfiguration;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
-import android.widget.Scroller;
-
-/** Handles touches and manages moving the bubble in response */
-class NewMoveHandler implements OnTouchListener {
-
- // Amount the ViewConfiguration's minFlingVelocity will be scaled by for our own minVelocity
- private static final int MIN_FLING_VELOCITY_FACTOR = 8;
- // The friction multiplier to control how slippery the bubble is when flung
- private static final float SCROLL_FRICTION_MULTIPLIER = 4f;
-
- private final Context context;
- private final WindowManager windowManager;
- private final NewBubble bubble;
- private final int minX;
- private final int minY;
- private final int maxX;
- private final int maxY;
- private final int bubbleSize;
- private final int bubbleShadowPaddingHorizontal;
- private final int bubbleExpandedViewWidth;
- private final float touchSlopSquared;
- private final BottomActionViewController bottomActionViewController;
-
- private boolean clickable = true;
- private boolean isMoving;
- private float firstX;
- private float firstY;
-
- private SpringAnimation moveXAnimation;
- private SpringAnimation moveYAnimation;
- private VelocityTracker velocityTracker;
- private Scroller scroller;
-
- private static float clamp(float value, float min, float max) {
- return Math.min(max, Math.max(min, value));
- }
-
- // Handles the left/right gravity conversion and centering
- private final FloatPropertyCompat<WindowManager.LayoutParams> xProperty =
- new FloatPropertyCompat<LayoutParams>("xProperty") {
- @Override
- public float getValue(LayoutParams windowParams) {
- int realX = windowParams.x;
- // Get bubble center position from real position
- if (bubble.getDrawerVisibility() == View.INVISIBLE) {
- realX += bubbleExpandedViewWidth / 2 + bubbleShadowPaddingHorizontal * 2;
- } else {
- realX += bubbleSize / 2 + bubbleShadowPaddingHorizontal;
- }
- if (relativeToRight(windowParams)) {
- // If gravity is right, get distant from bubble center position to screen right edge
- int displayWidth = context.getResources().getDisplayMetrics().widthPixels;
- realX = displayWidth - realX;
- }
- return clamp(realX, minX, maxX);
- }
-
- @Override
- public void setValue(LayoutParams windowParams, float value) {
- boolean wasOnRight = (windowParams.gravity & Gravity.RIGHT) == Gravity.RIGHT;
- int displayWidth = context.getResources().getDisplayMetrics().widthPixels;
- boolean onRight;
- Integer gravityOverride = bubble.getGravityOverride();
- if (gravityOverride == null) {
- onRight = value > displayWidth / 2;
- } else {
- onRight = (gravityOverride & Gravity.RIGHT) == Gravity.RIGHT;
- }
- // Get real position from bubble center position
- int centeringOffset;
- if (bubble.getDrawerVisibility() == View.INVISIBLE) {
- centeringOffset = bubbleExpandedViewWidth / 2 + bubbleShadowPaddingHorizontal * 2;
- } else {
- centeringOffset = bubbleSize / 2 + bubbleShadowPaddingHorizontal;
- }
- windowParams.x =
- (int) (onRight ? (displayWidth - value - centeringOffset) : value - centeringOffset);
- windowParams.gravity = Gravity.TOP | (onRight ? Gravity.RIGHT : Gravity.LEFT);
- if (bubble.isVisible()) {
- windowManager.updateViewLayout(bubble.getRootView(), windowParams);
- if (onRight != wasOnRight) {
- bubble.onLeftRightSwitch(onRight);
- }
- }
- }
- };
-
- private final FloatPropertyCompat<WindowManager.LayoutParams> yProperty =
- new FloatPropertyCompat<LayoutParams>("yProperty") {
- @Override
- public float getValue(LayoutParams object) {
- return clamp(object.y + bubbleSize, minY, maxY);
- }
-
- @Override
- public void setValue(LayoutParams object, float value) {
- object.y = (int) value - bubbleSize;
- if (bubble.isVisible()) {
- windowManager.updateViewLayout(bubble.getRootView(), object);
- }
- }
- };
-
- public NewMoveHandler(@NonNull View targetView, @NonNull NewBubble bubble) {
- this.bubble = bubble;
- context = targetView.getContext();
- windowManager = context.getSystemService(WindowManager.class);
-
- bubbleSize = context.getResources().getDimensionPixelSize(R.dimen.bubble_size);
- bubbleShadowPaddingHorizontal =
- context.getResources().getDimensionPixelSize(R.dimen.bubble_shadow_padding_size_horizontal);
- bubbleExpandedViewWidth =
- context.getResources().getDimensionPixelSize(R.dimen.bubble_expanded_width);
- // The following value is based on bubble center
- minX =
- context.getResources().getDimensionPixelOffset(R.dimen.bubble_off_screen_size_horizontal)
- + bubbleSize / 2;
- minY =
- context.getResources().getDimensionPixelOffset(R.dimen.bubble_safe_margin_vertical)
- + bubbleSize / 2;
- maxX = context.getResources().getDisplayMetrics().widthPixels - minX;
- maxY = context.getResources().getDisplayMetrics().heightPixels - minY;
-
- // Squared because it will be compared against the square of the touch delta. This is more
- // efficient than needing to take a square root.
- touchSlopSquared = (float) Math.pow(ViewConfiguration.get(context).getScaledTouchSlop(), 2);
-
- bottomActionViewController = new BottomActionViewController(context);
-
- targetView.setOnTouchListener(this);
- }
-
- public void setClickable(boolean clickable) {
- this.clickable = clickable;
- }
-
- public boolean isMoving() {
- return isMoving;
- }
-
- public void undoGravityOverride() {
- LayoutParams windowParams = bubble.getWindowParams();
- xProperty.setValue(windowParams, xProperty.getValue(windowParams));
- }
-
- public void snapToBounds() {
- ensureSprings();
-
- moveXAnimation.animateToFinalPosition(relativeToRight(bubble.getWindowParams()) ? maxX : minX);
- moveYAnimation.animateToFinalPosition(yProperty.getValue(bubble.getWindowParams()));
- }
-
- public int getMoveUpDistance(int deltaAllowed) {
- int currentY = (int) yProperty.getValue(bubble.getWindowParams());
- int currentDelta = maxY - currentY;
- return currentDelta >= deltaAllowed ? 0 : deltaAllowed - currentDelta;
- }
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- float eventX = event.getRawX();
- float eventY = event.getRawY();
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- firstX = eventX;
- firstY = eventY;
- velocityTracker = VelocityTracker.obtain();
- break;
- case MotionEvent.ACTION_MOVE:
- if (isMoving || hasExceededTouchSlop(event)) {
- if (!isMoving) {
- isMoving = true;
- bubble.onMoveStart();
- bottomActionViewController.createAndShowBottomActionView();
- }
- bottomActionViewController.highlightIfHover(eventX, eventY);
-
- ensureSprings();
-
- moveXAnimation.animateToFinalPosition(clamp(eventX, minX, maxX));
- moveYAnimation.animateToFinalPosition(clamp(eventY, minY, maxY));
- }
-
- velocityTracker.addMovement(event);
- break;
- case MotionEvent.ACTION_UP:
- if (isMoving) {
- ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
- velocityTracker.computeCurrentVelocity(
- 1000, viewConfiguration.getScaledMaximumFlingVelocity());
- float xVelocity = velocityTracker.getXVelocity();
- float yVelocity = velocityTracker.getYVelocity();
- boolean isFling = isFling(xVelocity, yVelocity);
-
- if (isFling) {
- Point target =
- findTarget(
- xVelocity,
- yVelocity,
- (int) xProperty.getValue(bubble.getWindowParams()),
- (int) yProperty.getValue(bubble.getWindowParams()));
-
- moveXAnimation.animateToFinalPosition(target.x);
- moveYAnimation.animateToFinalPosition(target.y);
- } else if (bottomActionViewController.isDismissHighlighted()) {
- bubble.bottomActionDismiss();
- } else if (bottomActionViewController.isEndCallHighlighted()) {
- bubble.bottomActionEndCall();
- } else {
- snapX();
- }
- isMoving = false;
- bubble.onMoveFinish();
- bottomActionViewController.destroyBottomActionView();
- } else {
- v.performClick();
- if (clickable) {
- bubble.primaryButtonClick();
- }
- }
- break;
- case MotionEvent.ACTION_CANCEL:
- if (isMoving) {
- snapX();
- isMoving = false;
- bubble.onMoveFinish();
- bottomActionViewController.destroyBottomActionView();
- }
- break;
- default: // fall out
- }
- return true;
- }
-
- private void ensureSprings() {
- if (moveXAnimation == null) {
- moveXAnimation = new SpringAnimation(bubble.getWindowParams(), xProperty);
- moveXAnimation.setSpring(new SpringForce());
- moveXAnimation.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY);
- // Moving when expanded makes expanded view INVISIBLE, and the whole view is not at the
- // boundary. It's time to create a viewHolder.
- moveXAnimation.addEndListener(
- (animation, canceled, value, velocity) -> {
- if (!isMoving && bubble.getDrawerVisibility() == View.INVISIBLE) {
- bubble.replaceViewHolder();
- }
- });
- }
-
- if (moveYAnimation == null) {
- moveYAnimation = new SpringAnimation(bubble.getWindowParams(), yProperty);
- moveYAnimation.setSpring(new SpringForce());
- moveYAnimation.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY);
- }
- }
-
- private Point findTarget(float xVelocity, float yVelocity, int startX, int startY) {
- if (scroller == null) {
- scroller = new Scroller(context);
- scroller.setFriction(ViewConfiguration.getScrollFriction() * SCROLL_FRICTION_MULTIPLIER);
- }
-
- // Find where a fling would end vertically
- scroller.fling(startX, startY, (int) xVelocity, (int) yVelocity, minX, maxX, minY, maxY);
- int targetY = scroller.getFinalY();
- scroller.abortAnimation();
-
- // If the x component of the velocity is above the minimum fling velocity, use velocity to
- // determine edge. Otherwise use its starting position
- boolean pullRight = isFling(xVelocity, 0) ? xVelocity > 0 : isOnRightHalf(startX);
- return new Point(pullRight ? maxX : minX, targetY);
- }
-
- private boolean isFling(float xVelocity, float yVelocity) {
- int minFlingVelocity =
- ViewConfiguration.get(context).getScaledMinimumFlingVelocity() * MIN_FLING_VELOCITY_FACTOR;
- return getMagnitudeSquared(xVelocity, yVelocity) > minFlingVelocity * minFlingVelocity;
- }
-
- private boolean isOnRightHalf(float currentX) {
- return currentX > (minX + maxX) / 2;
- }
-
- private void snapX() {
- // Check if x value is closer to min or max
- boolean pullRight = isOnRightHalf(xProperty.getValue(bubble.getWindowParams()));
- moveXAnimation.animateToFinalPosition(pullRight ? maxX : minX);
- }
-
- private boolean relativeToRight(LayoutParams windowParams) {
- return (windowParams.gravity & Gravity.RIGHT) == Gravity.RIGHT;
- }
-
- private boolean hasExceededTouchSlop(MotionEvent event) {
- return getMagnitudeSquared(event.getRawX() - firstX, event.getRawY() - firstY)
- > touchSlopSquared;
- }
-
- private float getMagnitudeSquared(float deltaX, float deltaY) {
- return deltaX * deltaX + deltaY * deltaY;
- }
-}