Skip to content

Commit 4baf286

Browse files
committed
Merge pull request markushi#1 from markushi/feature_animation_improvements
Improved animation handling, added BakedBezierInterpolator
2 parents 0688ca2 + 5279211 commit 4baf286

File tree

7 files changed

+125
-10
lines changed

7 files changed

+125
-10
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ repositories {
99
}
1010
1111
dependencies {
12-
compile 'com.github.markushi:android-ui:1.0'
12+
compile 'com.github.markushi:android-ui:1.1'
1313
}
1414
```
1515

example.apk

1.12 KB
Binary file not shown.

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION_NAME=1.0
1+
VERSION_NAME=1.1
22
VERSION_CODE=1
33
GROUP=com.github.markushi
44

src/main/java/at/markushi/ui/RevealColorView.java

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
import android.view.ViewGroup;
1212
import android.view.ViewPropertyAnimator;
1313

14+
import at.markushi.ui.util.BakedBezierInterpolator;
15+
import at.markushi.ui.util.UiHelper;
16+
1417
public class RevealColorView extends ViewGroup {
1518

1619
public static final int ANIMATION_REVEAL = 0;
@@ -20,7 +23,6 @@ public class RevealColorView extends ViewGroup {
2023

2124
private View inkView;
2225
private int inkColor;
23-
2426
private ShapeDrawable circle;
2527
private ViewPropertyAnimator animator;
2628

@@ -83,9 +85,11 @@ public void reveal(final int x, final int y, final int color, final int startRad
8385
circle.getPaint().setColor(color);
8486
inkView.setVisibility(View.VISIBLE);
8587

86-
final float startRadiusAsScale = startRadius * 2f / inkView.getHeight();
87-
prepareView(inkView, x, y, startRadiusAsScale);
88-
animator = inkView.animate().scaleX(SCALE).scaleY(SCALE).setDuration(duration).setListener(new Animator.AnimatorListener() {
88+
final float startScale = startRadius * 2f / inkView.getHeight();
89+
final float finalScale = calculateScale(x, y) * SCALE;
90+
91+
prepareView(inkView, x, y, startScale);
92+
animator = inkView.animate().scaleX(finalScale).scaleY(finalScale).setDuration(duration).setListener(new Animator.AnimatorListener() {
8993
@Override
9094
public void onAnimationStart(Animator animator) {
9195
if (listener != null) {
@@ -135,10 +139,12 @@ public void hide(final int x, final int y, final int color, final int endRadius,
135139
inkView.setVisibility(View.VISIBLE);
136140
setBackgroundColor(color);
137141

138-
prepareView(inkView, x, y, SCALE);
142+
final float startScale = calculateScale(x, y) * SCALE;
143+
final float finalScale = endRadius * SCALE / inkView.getWidth();
139144

140-
final float endRadiusAsScale = endRadius * SCALE / inkView.getWidth();
141-
animator = inkView.animate().scaleX(endRadiusAsScale).scaleY(endRadiusAsScale).setDuration(duration).setListener(new Animator.AnimatorListener() {
145+
prepareView(inkView, x, y, startScale);
146+
147+
animator = inkView.animate().scaleX(finalScale).scaleY(finalScale).setDuration(duration).setListener(new Animator.AnimatorListener() {
142148
@Override
143149
public void onAnimationStart(Animator animator) {
144150
if (listener != null) {
@@ -176,6 +182,7 @@ public ViewPropertyAnimator prepareAnimator(ViewPropertyAnimator animator, int t
176182
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
177183
animator.withLayer();
178184
}
185+
animator.setInterpolator(BakedBezierInterpolator.getInstance());
179186
return animator;
180187
}
181188

@@ -189,4 +196,23 @@ private void prepareView(View view, int x, int y, float scale) {
189196
view.setScaleX(scale);
190197
view.setScaleY(scale);
191198
}
199+
200+
/**
201+
* calculates the required scale of the ink-view to fill the whole view
202+
*
203+
* @param x circle center x
204+
* @param y circle center y
205+
* @return
206+
*/
207+
private float calculateScale(int x, int y) {
208+
final float centerX = getWidth() / 2f;
209+
final float centerY = getHeight() / 2f;
210+
final float maxDistance = (float) Math.sqrt(centerX * centerX + centerY * centerY);
211+
212+
final float deltaX = centerX - x;
213+
final float deltaY = centerY - y;
214+
final float distance = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY);
215+
final float scale = 0.5f + (distance / maxDistance) * 0.5f;
216+
return scale;
217+
}
192218
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright (C) 2013 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 at.markushi.ui.util;
18+
19+
import android.view.animation.Interpolator;
20+
21+
/**
22+
* A pre-baked bezier-curved interpolator for indeterminate progress animations.
23+
*/
24+
public final class BakedBezierInterpolator implements Interpolator {
25+
private static final BakedBezierInterpolator INSTANCE = new BakedBezierInterpolator();
26+
27+
public final static BakedBezierInterpolator getInstance() {
28+
return INSTANCE;
29+
}
30+
31+
/**
32+
* Use getInstance instead of instantiating.
33+
*/
34+
private BakedBezierInterpolator() {
35+
super();
36+
}
37+
38+
/**
39+
* Lookup table values.
40+
* Generated using a Bezier curve from (0,0) to (1,1) with control points:
41+
* P0 (0,0)
42+
* P1 (0.4, 0)
43+
* P2 (0.2, 1.0)
44+
* P3 (1.0, 1.0)
45+
*
46+
* Values sampled with x at regular intervals between 0 and 1.
47+
*/
48+
private static final float[] VALUES = new float[] {
49+
0.0f, 0.0002f, 0.0009f, 0.0019f, 0.0036f, 0.0059f, 0.0086f, 0.0119f, 0.0157f, 0.0209f,
50+
0.0257f, 0.0321f, 0.0392f, 0.0469f, 0.0566f, 0.0656f, 0.0768f, 0.0887f, 0.1033f, 0.1186f,
51+
0.1349f, 0.1519f, 0.1696f, 0.1928f, 0.2121f, 0.237f, 0.2627f, 0.2892f, 0.3109f, 0.3386f,
52+
0.3667f, 0.3952f, 0.4241f, 0.4474f, 0.4766f, 0.5f, 0.5234f, 0.5468f, 0.5701f, 0.5933f,
53+
0.6134f, 0.6333f, 0.6531f, 0.6698f, 0.6891f, 0.7054f, 0.7214f, 0.7346f, 0.7502f, 0.763f,
54+
0.7756f, 0.7879f, 0.8f, 0.8107f, 0.8212f, 0.8326f, 0.8415f, 0.8503f, 0.8588f, 0.8672f,
55+
0.8754f, 0.8833f, 0.8911f, 0.8977f, 0.9041f, 0.9113f, 0.9165f, 0.9232f, 0.9281f, 0.9328f,
56+
0.9382f, 0.9434f, 0.9476f, 0.9518f, 0.9557f, 0.9596f, 0.9632f, 0.9662f, 0.9695f, 0.9722f,
57+
0.9753f, 0.9777f, 0.9805f, 0.9826f, 0.9847f, 0.9866f, 0.9884f, 0.9901f, 0.9917f, 0.9931f,
58+
0.9944f, 0.9955f, 0.9964f, 0.9973f, 0.9981f, 0.9986f, 0.9992f, 0.9995f, 0.9998f, 1.0f, 1.0f
59+
};
60+
61+
private static final float STEP_SIZE = 1.0f / (VALUES.length - 1);
62+
63+
@Override
64+
public float getInterpolation(float input) {
65+
if (input >= 1.0f) {
66+
return 1.0f;
67+
}
68+
69+
if (input <= 0f) {
70+
return 0f;
71+
}
72+
73+
int position = Math.min(
74+
(int)(input * (VALUES.length - 1)),
75+
VALUES.length - 2);
76+
77+
float quantized = position * STEP_SIZE;
78+
float difference = input - quantized;
79+
float weight = difference / STEP_SIZE;
80+
81+
return VALUES[position] + weight * (VALUES[position + 1] - VALUES[position]);
82+
}
83+
84+
}

src/main/java/at/markushi/ui/UiHelper.java renamed to src/main/java/at/markushi/ui/util/UiHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package at.markushi.ui;
1+
package at.markushi.ui.util;
22

33
import android.graphics.drawable.Drawable;
44
import android.os.Build;

src/main/res/values/values.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<integer name="rcv_animationDurationHide">420</integer>
4+
<integer name="rcv_animationDurationReveal">420</integer>
5+
</resources>

0 commit comments

Comments
 (0)