Skip to content

Commit 536b291

Browse files
author
Markus Hintersteiner
committed
Added RevealColorView
1 parent 1541799 commit 536b291

File tree

7 files changed

+379
-0
lines changed

7 files changed

+379
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

build.gradle

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
buildscript {
2+
repositories {
3+
mavenCentral()
4+
}
5+
dependencies {
6+
classpath 'com.android.tools.build:gradle:0.12.+'
7+
}
8+
}
9+
apply plugin: 'android-library'
10+
11+
repositories {
12+
mavenCentral()
13+
}
14+
15+
android {
16+
compileSdkVersion 19
17+
buildToolsVersion "20"
18+
19+
defaultConfig {
20+
minSdkVersion 14
21+
versionName = VERSION_NAME
22+
versionCode = VERSION_CODE
23+
}
24+
}
25+
26+
dependencies {
27+
28+
}
29+
30+
allprojects {
31+
version = VERSION_NAME
32+
group = GROUP
33+
34+
repositories {
35+
mavenCentral()
36+
}
37+
}
38+
39+
apply from: 'maven.gradle'

gradle.properties

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
VERSION_NAME=1.0
2+
VERSION_CODE=1
3+
GROUP=com.github.markushi
4+
5+
POM_NAME=Android UI Library
6+
POM_ARTIFACT_ID=android-ui
7+
POM_PACKAGING=aar
8+
9+
POM_DESCRIPTION=Android UI Library
10+
POM_URL=https://github.com/markushi/android-ui
11+
POM_SCM_URL=https://github.com/markushi/android-ui
12+
POM_SCM_CONNECTION=scm:[email protected]:markushi/android-ui.git
13+
POM_SCM_DEV_CONNECTION=scm:[email protected]:markushi/android-ui.git
14+
POM_LICENCE_NAME=The Apache Software License, Version 2.0
15+
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
16+
POM_LICENCE_DIST=repo
17+
POM_DEVELOPER_ID=markushi
18+
POM_DEVELOPER_NAME=Markus Hintersteiner

maven.gradle

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
apply plugin: 'maven'
2+
apply plugin: 'signing'
3+
4+
ext {
5+
version = VERSION_NAME
6+
group = GROUP
7+
}
8+
9+
def isReleaseBuild() {
10+
return VERSION_NAME.contains("SNAPSHOT") == false
11+
}
12+
13+
if (isReleaseBuild()) {
14+
println 'RELEASE BUILD'
15+
} else {
16+
println 'SNAPSHOT BUILD'
17+
}
18+
19+
def getRepositoryUrl() {
20+
if (isReleaseBuild()) {
21+
return "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
22+
} else {
23+
return "https://oss.sonatype.org/content/repositories/snapshots/"
24+
}
25+
}
26+
27+
def getRepositoryUsername() {
28+
return hasProperty('nexusUsername') ? nexusUsername : ""
29+
}
30+
31+
def getRepositoryPassword() {
32+
return hasProperty('nexusPassword') ? nexusPassword : ""
33+
}
34+
35+
afterEvaluate { project ->
36+
uploadArchives {
37+
repositories {
38+
mavenDeployer {
39+
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
40+
41+
pom.artifactId = POM_ARTIFACT_ID
42+
43+
repository(url: getRepositoryUrl()) {
44+
authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
45+
}
46+
47+
pom.project {
48+
name POM_NAME
49+
packaging POM_PACKAGING
50+
description POM_DESCRIPTION
51+
url POM_URL
52+
53+
scm {
54+
url POM_SCM_URL
55+
connection POM_SCM_CONNECTION
56+
developerConnection POM_SCM_DEV_CONNECTION
57+
}
58+
59+
licenses {
60+
license {
61+
name POM_LICENCE_NAME
62+
url POM_LICENCE_URL
63+
distribution POM_LICENCE_DIST
64+
}
65+
}
66+
67+
developers {
68+
developer {
69+
id POM_DEVELOPER_ID
70+
name POM_DEVELOPER_NAME
71+
}
72+
}
73+
}
74+
}
75+
}
76+
}
77+
78+
signing {
79+
required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
80+
sign configurations.archives
81+
}
82+
83+
task androidJavadocs(type: Javadoc) {
84+
options {
85+
linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference"
86+
}
87+
source = android.sourceSets.main.java.sourceFiles
88+
classpath += project.files(project.android.getBootClasspath().join(File.pathSeparator))
89+
}
90+
91+
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
92+
classifier = 'javadoc'
93+
from androidJavadocs.destinationDir
94+
}
95+
96+
task androidSourcesJar(type: Jar) {
97+
classifier = 'sources'
98+
from android.sourceSets.main.java.sourceFiles
99+
}
100+
101+
artifacts {
102+
archives androidSourcesJar
103+
archives androidJavadocsJar
104+
}
105+
}

src/main/AndroidManifest.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<manifest
2+
xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="at.markushi.ui">
4+
<application>
5+
6+
</application>
7+
</manifest>
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
package at.markushi.ui;
2+
3+
import android.animation.Animator;
4+
import android.content.Context;
5+
import android.graphics.Color;
6+
import android.graphics.drawable.ShapeDrawable;
7+
import android.graphics.drawable.shapes.OvalShape;
8+
import android.os.Build;
9+
import android.util.AttributeSet;
10+
import android.view.View;
11+
import android.view.ViewGroup;
12+
import android.view.ViewPropertyAnimator;
13+
14+
public class RevealColorView extends ViewGroup {
15+
16+
public static final int ANIMATION_REVEAL = 0;
17+
public static final int ANIMATION_HIDE = 2;
18+
19+
private static final float SCALE = 8f;
20+
21+
private View inkView;
22+
private int inkColor;
23+
24+
private ShapeDrawable circle;
25+
private ViewPropertyAnimator animator;
26+
27+
public RevealColorView(Context context) {
28+
this(context, null);
29+
}
30+
31+
public RevealColorView(Context context, AttributeSet attrs) {
32+
this(context, attrs, 0);
33+
}
34+
35+
public RevealColorView(Context context, AttributeSet attrs, int defStyleAttr) {
36+
super(context, attrs, defStyleAttr);
37+
38+
if (isInEditMode()) {
39+
return;
40+
}
41+
42+
inkView = new View(context);
43+
addView(inkView);
44+
45+
circle = new ShapeDrawable(new OvalShape());
46+
47+
UiHelper.setBackground(inkView, circle);
48+
inkView.setVisibility(View.INVISIBLE);
49+
}
50+
51+
@Override
52+
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
53+
inkView.layout(left, top, left + inkView.getMeasuredWidth(), top + inkView.getMeasuredHeight());
54+
}
55+
56+
@Override
57+
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
58+
final int width = MeasureSpec.getSize(widthMeasureSpec);
59+
final int height = MeasureSpec.getSize(heightMeasureSpec);
60+
setMeasuredDimension(width, height);
61+
62+
final float circleSize = (float) Math.sqrt(width * width + height * height) * 2f;
63+
final int size = (int) (circleSize / SCALE);
64+
final int sizeSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
65+
inkView.measure(sizeSpec, sizeSpec);
66+
}
67+
68+
public void reveal(final int x, final int y, final int color, Animator.AnimatorListener listener) {
69+
final int duration = getResources().getInteger(R.integer.rcv_animationDurationReveal);
70+
reveal(x, y, color, 0, duration, listener);
71+
}
72+
73+
public void reveal(final int x, final int y, final int color, final int startRadius, long duration, final Animator.AnimatorListener listener) {
74+
if (color == inkColor) {
75+
return;
76+
}
77+
inkColor = color;
78+
79+
if (animator != null) {
80+
animator.cancel();
81+
}
82+
83+
circle.getPaint().setColor(color);
84+
inkView.setVisibility(View.VISIBLE);
85+
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() {
89+
@Override
90+
public void onAnimationStart(Animator animator) {
91+
if (listener != null) {
92+
listener.onAnimationStart(animator);
93+
}
94+
}
95+
96+
@Override
97+
public void onAnimationEnd(Animator animation) {
98+
setBackgroundColor(color);
99+
inkView.setVisibility(View.INVISIBLE);
100+
if (listener != null) {
101+
listener.onAnimationEnd(animation);
102+
}
103+
}
104+
105+
@Override
106+
public void onAnimationCancel(Animator animator) {
107+
if (listener != null) {
108+
listener.onAnimationCancel(animator);
109+
}
110+
}
111+
112+
@Override
113+
public void onAnimationRepeat(Animator animator) {
114+
if (listener != null) {
115+
listener.onAnimationRepeat(animator);
116+
}
117+
}
118+
});
119+
prepareAnimator(animator, ANIMATION_REVEAL);
120+
animator.start();
121+
}
122+
123+
public void hide(final int x, final int y, final int color, final Animator.AnimatorListener listener) {
124+
final int duration = getResources().getInteger(R.integer.rcv_animationDurationHide);
125+
hide(x, y, color, 0, duration, listener);
126+
}
127+
128+
public void hide(final int x, final int y, final int color, final int endRadius, final long duration, final Animator.AnimatorListener listener) {
129+
inkColor = Color.TRANSPARENT;
130+
131+
if (animator != null) {
132+
animator.cancel();
133+
}
134+
135+
inkView.setVisibility(View.VISIBLE);
136+
setBackgroundColor(color);
137+
138+
prepareView(inkView, x, y, SCALE);
139+
140+
final float endRadiusAsScale = endRadius * SCALE / inkView.getWidth();
141+
animator = inkView.animate().scaleX(endRadiusAsScale).scaleY(endRadiusAsScale).setDuration(duration).setListener(new Animator.AnimatorListener() {
142+
@Override
143+
public void onAnimationStart(Animator animator) {
144+
if (listener != null) {
145+
listener.onAnimationStart(animator);
146+
}
147+
}
148+
149+
@Override
150+
public void onAnimationEnd(Animator animation) {
151+
inkView.setVisibility(View.INVISIBLE);
152+
if (listener != null) {
153+
listener.onAnimationEnd(animation);
154+
}
155+
}
156+
157+
@Override
158+
public void onAnimationCancel(Animator animator) {
159+
if (listener != null) {
160+
listener.onAnimationCancel(animator);
161+
}
162+
}
163+
164+
@Override
165+
public void onAnimationRepeat(Animator animator) {
166+
if (listener != null) {
167+
listener.onAnimationRepeat(animator);
168+
}
169+
}
170+
});
171+
prepareAnimator(animator, ANIMATION_HIDE);
172+
animator.start();
173+
}
174+
175+
public ViewPropertyAnimator prepareAnimator(ViewPropertyAnimator animator, int type) {
176+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
177+
animator.withLayer();
178+
}
179+
return animator;
180+
}
181+
182+
private void prepareView(View view, int x, int y, float scale) {
183+
final int centerX = (view.getWidth() / 2);
184+
final int centerY = (view.getHeight() / 2);
185+
view.setTranslationX(x - centerX);
186+
view.setTranslationY(y - centerY);
187+
view.setPivotX(centerX);
188+
view.setPivotY(centerY);
189+
view.setScaleX(scale);
190+
view.setScaleY(scale);
191+
}
192+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package at.markushi.ui;
2+
3+
import android.graphics.drawable.Drawable;
4+
import android.os.Build;
5+
import android.view.View;
6+
7+
public class UiHelper {
8+
9+
@SuppressWarnings("deprecation")
10+
public static void setBackground(View view, Drawable d) {
11+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
12+
view.setBackground(d);
13+
} else {
14+
view.setBackgroundDrawable(d);
15+
}
16+
}
17+
}

0 commit comments

Comments
 (0)