Skip to content
This repository has been archived by the owner on Feb 9, 2023. It is now read-only.

[CD-51] Close pop with gesture, add animation #32

Merged
merged 25 commits into from
Sep 19, 2019
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 173 additions & 7 deletions hover/src/main/java/io/mattcarroll/hover/ExitView.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,20 @@
*/
package io.mattcarroll.hover;

import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.animation.PathInterpolatorCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.RelativeLayout;

/**
Expand All @@ -32,8 +38,28 @@ class ExitView extends RelativeLayout {

private static final String TAG = "ExitView";

private static final int FADE_DURATION = 250;
private static final int SHOW_HIDE_DURATION = 250;
private static final float EXIT_ICON_DEFAULT_SCALE_X = 1.0f;
private static final float EXIT_ICON_DEFAULT_SCALE_Y = 1.0f;
private static final float EXIT_ICON_TARGET_SCALE_X = 1.2f;
private static final float EXIT_ICON_TARGET_SCALE_Y = 1.2f;
private static final float EXIT_ICON_DEFAULT_ROTATION = 0f;
private static final float EXIT_ICON_TARGET_ROTATION = 90f;
private static final float EXIT_ICON_DEFAULT_ALPHA = 0.6f;
private static final float EXIT_ICON_TARGET_ALPHA = 0.75f;
private static final float EXIT_VIEW_DEFAULT_ALPHA = 0f;
private static final float EXIT_VIEW_TARGET_ALPHA = 1.0f;
private static final float EXIT_VIEW_DEFAULT_Y = 800f;
private static final float EXIT_VIEW_TARGET_Y = 0f;

private int mExitRadiusInPx;
private View mExitIcon;
private View mExitGradient;
private ViewGroup mVgExit;
private ObjectAnimator mShowEnterAnimation = null;
private ObjectAnimator mShowExitAnimation = null;
private boolean mIsShowing = false;

public ExitView(@NonNull Context context) {
this(context, null);
Expand All @@ -48,15 +74,89 @@ private void init() {
LayoutInflater.from(getContext()).inflate(R.layout.view_hover_menu_exit, this, true);

mExitIcon = findViewById(R.id.view_exit);

mVgExit = findViewById(R.id.vg_exit);
mExitGradient = findViewById(R.id.view_exit_gradient);
mExitRadiusInPx = getResources().getDimensionPixelSize(R.dimen.hover_exit_radius);
mExitIcon.setAlpha(EXIT_ICON_DEFAULT_ALPHA);

setAnimations();
}

private Interpolator getExitViewInterpolator() {
return PathInterpolatorCompat.create(0.75f, 0f, 0.25f, 1f);
}

public boolean isInExitZone(@NonNull Point position) {
Point exitCenter = getExitZoneCenter();
double distanceToExit = calculateDistance(position, exitCenter);
Log.d(TAG, "Drop point: " + position + ", Exit center: " + exitCenter + ", Distance: " + distanceToExit);
return distanceToExit <= mExitRadiusInPx;
private void setAnimations() {
PropertyValuesHolder showEnterAnimationScaleX = PropertyValuesHolder.ofFloat("scaleX", EXIT_ICON_DEFAULT_SCALE_X, EXIT_ICON_TARGET_SCALE_X);
PropertyValuesHolder showEnterAnimationScaleY = PropertyValuesHolder.ofFloat("scaleY", EXIT_ICON_DEFAULT_SCALE_Y, EXIT_ICON_TARGET_SCALE_Y);
PropertyValuesHolder showEnterAnimationRotate = PropertyValuesHolder.ofFloat("rotation", EXIT_ICON_DEFAULT_ROTATION, EXIT_ICON_TARGET_ROTATION);
PropertyValuesHolder showEnterAnimationAlpha = PropertyValuesHolder.ofFloat("alpha", EXIT_ICON_DEFAULT_ALPHA, EXIT_ICON_TARGET_ALPHA);
mShowEnterAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, showEnterAnimationScaleX, showEnterAnimationScaleY, showEnterAnimationRotate, showEnterAnimationAlpha);
mShowEnterAnimation.setDuration(SHOW_HIDE_DURATION);
mShowEnterAnimation.setInterpolator(getExitViewInterpolator());
mShowEnterAnimation.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
initExitIconViewStatus();
}

@Override
public void onAnimationEnd(Animator animator) {
}

@Override
public void onAnimationCancel(Animator animator) {
initExitIconViewStatus();
}

@Override
public void onAnimationRepeat(Animator animator) {
}
});

PropertyValuesHolder showExitAnimationScaleX = PropertyValuesHolder.ofFloat("scaleX", EXIT_ICON_TARGET_SCALE_X, EXIT_ICON_DEFAULT_SCALE_X);
PropertyValuesHolder showExitAnimationScaleY = PropertyValuesHolder.ofFloat("scaleY", EXIT_ICON_TARGET_SCALE_Y, EXIT_ICON_DEFAULT_SCALE_Y);
PropertyValuesHolder showExitAnimationRotate = PropertyValuesHolder.ofFloat("rotation", EXIT_ICON_TARGET_ROTATION, EXIT_ICON_DEFAULT_ROTATION);
PropertyValuesHolder showExitAnimationAlpha = PropertyValuesHolder.ofFloat("alpha", EXIT_ICON_TARGET_ALPHA, EXIT_ICON_DEFAULT_ALPHA);
mShowExitAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, showExitAnimationScaleX, showExitAnimationScaleY, showExitAnimationRotate, showExitAnimationAlpha);
mShowExitAnimation.setDuration(SHOW_HIDE_DURATION);
mShowExitAnimation.setInterpolator(getExitViewInterpolator());
}

private void initExitIconViewStatus() {
mExitIcon.setScaleY(EXIT_ICON_DEFAULT_SCALE_Y);
mExitIcon.setScaleX(EXIT_ICON_DEFAULT_SCALE_X);
mExitIcon.setRotation(EXIT_ICON_DEFAULT_ROTATION);
}

public boolean isInExitZone(@NonNull Point position, @NonNull Point screenSize) {
int exitXExcludeThresholdLeft = screenSize.x / 10;
int exitXExcludeThresholdRight = screenSize.x * 9 / 10;

Rect exitArea = new Rect(
0 - mExitIcon.getWidth(),
screenSize.y * 4 / 6,
screenSize.x + mExitIcon.getWidth(),
screenSize.y + mExitIcon.getHeight()
);

Rect excludedXExitAreaLeft = new Rect(
0 - mExitIcon.getWidth(),
screenSize.y * 4 / 6,
exitXExcludeThresholdLeft,
screenSize.y - mExitIcon.getHeight() / 2
);

Rect excludedXExitAreaRight = new Rect(
exitXExcludeThresholdRight,
screenSize.y * 4 / 6,
screenSize.x + mExitIcon.getWidth(),
screenSize.y - mExitIcon.getHeight() / 2
);

return exitArea.contains(position.x, position.y)
&& !excludedXExitAreaLeft.contains(position.x, position.y)
&& !excludedXExitAreaRight.contains(position.x, position.y);
}

private Point getExitZoneCenter() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isInExitZone method가 생기면서 사용을 안하는 것 같은데 없애도 되지 않을까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제거했습니다

Expand All @@ -71,4 +171,70 @@ private double calculateDistance(@NonNull Point p1, @NonNull Point p2) {
Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 method도 위치가 옮겨져서 사용을 안하는 것 같네요

);
}

public void showEnterAnimation() {
if (mShowEnterAnimation != null && !mShowEnterAnimation.isRunning() && !mIsShowing) {
mShowEnterAnimation.start();
mIsShowing = true;
}
}

public void showExitAnimation() {
if (mShowExitAnimation != null && !mShowExitAnimation.isRunning() && mIsShowing) {
mShowExitAnimation.start();
mIsShowing = false;
}
}

public void show() {
resetExitButtonAnimation();

ObjectAnimator exitGradientAnimator = ObjectAnimator.ofFloat(mExitGradient, "alpha", EXIT_VIEW_TARGET_ALPHA);
exitGradientAnimator.setDuration(FADE_DURATION);
exitGradientAnimator.setInterpolator(getExitViewInterpolator());
exitGradientAnimator.start();

ObjectAnimator vgExitAnimator = ObjectAnimator.ofFloat(mVgExit, "y", EXIT_VIEW_DEFAULT_Y, EXIT_VIEW_TARGET_Y);
vgExitAnimator.setDuration(FADE_DURATION);
vgExitAnimator.setInterpolator(getExitViewInterpolator());
vgExitAnimator.start();

setVisibility(VISIBLE);
}

public void resetExitButtonAnimation() {
mIsShowing = false;
initExitIconViewStatus();
}

public void hide() {
ObjectAnimator vgExitAnimator = ObjectAnimator.ofFloat(mVgExit, "y", EXIT_VIEW_TARGET_Y, EXIT_VIEW_DEFAULT_Y);
vgExitAnimator.setDuration(FADE_DURATION);
vgExitAnimator.setInterpolator(getExitViewInterpolator());
vgExitAnimator.start();

ObjectAnimator exitGradientAnimator = ObjectAnimator.ofFloat(mExitGradient, "alpha", EXIT_VIEW_DEFAULT_ALPHA);
exitGradientAnimator.setDuration(FADE_DURATION);
exitGradientAnimator.setInterpolator(getExitViewInterpolator());
exitGradientAnimator.start();

exitGradientAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}

@Override
public void onAnimationEnd(Animator animation) {
setVisibility(GONE);
}

@Override
public void onAnimationCancel(Animator animation) {
}

@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
}
36 changes: 36 additions & 0 deletions hover/src/main/java/io/mattcarroll/hover/FloatingTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,42 @@ public void onAnimationUpdate(ValueAnimator animation) {
});
}

public void closeAnimation(Point targetPosition, @Nullable final Runnable onDocked) {
Point destinationCornerPosition = convertCenterToCorner(targetPosition);
Log.d(TAG, "Docking to destination point: " + destinationCornerPosition);

ObjectAnimator xAnimation = ObjectAnimator.ofFloat(this, "x", targetPosition.x);
xAnimation.setDuration(500);
xAnimation.setInterpolator(new OvershootInterpolator());
ObjectAnimator yAnimation = ObjectAnimator.ofFloat(this, "y", targetPosition.y);
yAnimation.setDuration(500);
yAnimation.setInterpolator(new OvershootInterpolator());
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(xAnimation).with(yAnimation);
animatorSet.start();

animatorSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}

@Override
public void onAnimationEnd(Animator animation) {
if (null != onDocked) {
onDocked.run();
}
}

@Override
public void onAnimationCancel(Animator animation) {
}

@Override
public void onAnimationRepeat(Animator animation) {
}
});
}

public void dockImmediately() {
moveCenterTo(mDock.position());
}
Expand Down
Loading