blob: d204e0f1c0e4e552a55941c3f8fbe9362f2b3e78 [file] [log] [blame]
yueg0b4755c2017-12-18 10:01:03 -08001/*
2 * Copyright (C) 2017 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
17package com.android.newbubble;
18
19import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
21import android.animation.ValueAnimator;
22import android.graphics.Outline;
23import android.graphics.Rect;
24import android.view.View;
25import android.view.ViewOutlineProvider;
26
27/**
28 * A {@link ViewOutlineProvider} that provides an outline that interpolates between two radii and
29 * two {@link Rect}s.
30 *
31 * <p>An example usage of this provider is an outline that starts out as a circle and ends as a
32 * rounded rectangle.
33 */
34public class RoundedRectRevealOutlineProvider extends ViewOutlineProvider {
35 private final float mStartRadius;
36 private final float mEndRadius;
37
38 private final Rect mStartRect;
39 private final Rect mEndRect;
40
41 private final Rect mOutline;
42 private float mOutlineRadius;
43
44 public RoundedRectRevealOutlineProvider(
45 float startRadius, float endRadius, Rect startRect, Rect endRect) {
46 mStartRadius = startRadius;
47 mEndRadius = endRadius;
48 mStartRect = startRect;
49 mEndRect = endRect;
50
51 mOutline = new Rect();
52 }
53
54 @Override
55 public void getOutline(View v, Outline outline) {
56 outline.setRoundRect(mOutline, mOutlineRadius);
57 }
58
59 /** Sets the progress, from 0 to 1, of the reveal animation. */
60 public void setProgress(float progress) {
61 mOutlineRadius = (1 - progress) * mStartRadius + progress * mEndRadius;
62
63 mOutline.left = (int) ((1 - progress) * mStartRect.left + progress * mEndRect.left);
64 mOutline.top = (int) ((1 - progress) * mStartRect.top + progress * mEndRect.top);
65 mOutline.right = (int) ((1 - progress) * mStartRect.right + progress * mEndRect.right);
66 mOutline.bottom = (int) ((1 - progress) * mStartRect.bottom + progress * mEndRect.bottom);
67 }
68
69 ValueAnimator createRevealAnimator(final View revealView, boolean isReversed) {
70 ValueAnimator valueAnimator =
71 isReversed ? ValueAnimator.ofFloat(1f, 0f) : ValueAnimator.ofFloat(0f, 1f);
72
73 valueAnimator.addListener(
74 new AnimatorListenerAdapter() {
75 private boolean mWasCanceled = false;
76
77 @Override
78 public void onAnimationStart(Animator animation) {
79 revealView.setOutlineProvider(RoundedRectRevealOutlineProvider.this);
80 revealView.setClipToOutline(true);
81 }
82
83 @Override
84 public void onAnimationCancel(Animator animation) {
85 mWasCanceled = true;
86 }
87
88 @Override
89 public void onAnimationEnd(Animator animation) {
90 if (!mWasCanceled) {
91 revealView.setOutlineProvider(ViewOutlineProvider.BACKGROUND);
92 revealView.setClipToOutline(false);
93 }
94 }
95 });
96
97 valueAnimator.addUpdateListener(
98 (currentValueAnimator) -> {
99 float progress = (Float) currentValueAnimator.getAnimatedValue();
100 setProgress(progress);
101 revealView.invalidateOutline();
102 });
103 return valueAnimator;
104 }
105}