summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas <tschneider.ac@gmail.com>2023-01-13 16:19:50 +0100
committerThomas <tschneider.ac@gmail.com>2023-01-13 16:19:50 +0100
commit107ac13e1547c50424497f29116d1aaf9bc6ab69 (patch)
treee7f37e97b66858ef8e42183937fc22ec16daa027
parentd70c285beaf058f8817dffc04b980f9c3cb93e31 (diff)
Fix issue #745 - Update library for bottom buttons.
-rw-r--r--app/build.gradle5
-rw-r--r--app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java13
-rw-r--r--app/src/main/res/drawable/ic_round_bookmark_24.xml2
-rw-r--r--app/src/main/res/drawable/ic_round_repeat_active_24.xml10
-rw-r--r--app/src/main/res/drawable/ic_round_star_24.xml2
-rw-r--r--app/src/main/res/layout/drawer_status.xml36
-rw-r--r--settings.gradle1
-rw-r--r--sparkbutton/.gitignore1
-rw-r--r--sparkbutton/build.gradle27
-rw-r--r--sparkbutton/gradle.properties3
-rw-r--r--sparkbutton/maven-push.gradle96
-rw-r--r--sparkbutton/proguard-rules.pro17
-rw-r--r--sparkbutton/src/main/AndroidManifest.xml4
-rw-r--r--sparkbutton/src/main/java/com/varunest/sparkbutton/SparkButton.java313
-rw-r--r--sparkbutton/src/main/java/com/varunest/sparkbutton/SparkButtonBuilder.java61
-rw-r--r--sparkbutton/src/main/java/com/varunest/sparkbutton/SparkEventListener.java10
-rw-r--r--sparkbutton/src/main/java/com/varunest/sparkbutton/helpers/SparkAnimationView.java249
-rw-r--r--sparkbutton/src/main/java/com/varunest/sparkbutton/helpers/Utils.java30
-rw-r--r--sparkbutton/src/main/res/values/attrs.xml11
-rw-r--r--sparkbutton/src/main/res/values/colors.xml6
-rw-r--r--sparkbutton/src/main/res/values/strings.xml3
21 files changed, 865 insertions, 35 deletions
diff --git a/app/build.gradle b/app/build.gradle
index eaabe38d4..63041b029 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -78,7 +78,7 @@ allprojects {
}
dependencies {
implementation project(':autoimageslider')
- implementation 'androidx.appcompat:appcompat:1.5.1'
+ implementation 'androidx.appcompat:appcompat:1.6.0'
implementation 'com.google.android.material:material:1.7.0'
@@ -94,7 +94,6 @@ dependencies {
implementation "org.conscrypt:conscrypt-android:2.5.2"
implementation 'com.vanniktech:emoji-one:0.6.0'
implementation 'com.github.GrenderG:Toasty:1.5.2'
- implementation 'org.framagit.tom79:SparkButton:1.0.13'
implementation "com.github.bumptech.glide:glide:4.14.2"
implementation "com.github.bumptech.glide:okhttp3-integration:4.14.2"
implementation("com.github.bumptech.glide:recyclerview-integration:4.14.2") {
@@ -107,7 +106,7 @@ dependencies {
implementation 'com.github.mergehez:ArgPlayer:v3.1'
implementation project(path: ':mytransl')
implementation project(path: ':ratethisapp')
-
+ implementation project(path: ':sparkbutton')
implementation 'com.burhanrashid52:photoeditor:1.5.1'
implementation("com.vanniktech:android-image-cropper:4.3.3")
diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java
index ca686c881..450473b35 100644
--- a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java
+++ b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java
@@ -638,21 +638,13 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
}
- holder.binding.actionButtonFavorite.pressOnTouch(false);
- holder.binding.actionButtonBoost.pressOnTouch(false);
- holder.binding.actionButtonBookmark.pressOnTouch(false);
+
holder.binding.actionButtonFavorite.setActiveImage(R.drawable.ic_round_star_24);
holder.binding.actionButtonFavorite.setInactiveImage(R.drawable.ic_round_star_border_24);
holder.binding.actionButtonBookmark.setActiveImage(R.drawable.ic_round_bookmark_24);
holder.binding.actionButtonBookmark.setInactiveImage(R.drawable.ic_round_bookmark_border_24);
holder.binding.actionButtonBoost.setActiveImage(R.drawable.ic_round_repeat_24);
holder.binding.actionButtonBoost.setInactiveImage(R.drawable.ic_round_repeat_24);
- holder.binding.actionButtonFavorite.setDisableCircle(true);
- holder.binding.actionButtonBoost.setDisableCircle(true);
- holder.binding.actionButtonBookmark.setDisableCircle(true);
- holder.binding.actionButtonFavorite.setActiveImageTint(R.color.marked_icon);
- holder.binding.actionButtonBoost.setActiveImageTint(R.color.boost_icon);
- holder.binding.actionButtonBookmark.setActiveImageTint(R.color.marked_icon);
applyColor(context, holder);
if (status.pinned) {
@@ -2319,9 +2311,6 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
Helper.changeDrawableColor(context, R.drawable.ic_bot, theme_icons_color);
Helper.changeDrawableColor(context, R.drawable.ic_round_reply_24, theme_icons_color);
Helper.changeDrawableColor(context, holder.binding.actionButtonTranslate, theme_icons_color);
- holder.binding.actionButtonFavorite.setInActiveImageTintColor(theme_icons_color);
- holder.binding.actionButtonBookmark.setInActiveImageTintColor(theme_icons_color);
- holder.binding.actionButtonBoost.setInActiveImageTintColor(theme_icons_color);
holder.binding.replyCount.setTextColor(theme_icons_color);
}
if (theme_statuses_color != -1) {
diff --git a/app/src/main/res/drawable/ic_round_bookmark_24.xml b/app/src/main/res/drawable/ic_round_bookmark_24.xml
index fdc2c64d4..f8e4675ec 100644
--- a/app/src/main/res/drawable/ic_round_bookmark_24.xml
+++ b/app/src/main/res/drawable/ic_round_bookmark_24.xml
@@ -1,7 +1,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
- android:tint="?attr/colorControlNormal"
+ android:tint="@color/marked_icon"
android:viewportWidth="24"
android:viewportHeight="24">
<path
diff --git a/app/src/main/res/drawable/ic_round_repeat_active_24.xml b/app/src/main/res/drawable/ic_round_repeat_active_24.xml
new file mode 100644
index 000000000..75e67ce56
--- /dev/null
+++ b/app/src/main/res/drawable/ic_round_repeat_active_24.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="@color/boost_icon"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="?attr/colorControlNormal"
+ android:pathData="M7,7h10v1.79c0,0.45 0.54,0.67 0.85,0.35l2.79,-2.79c0.2,-0.2 0.2,-0.51 0,-0.71l-2.79,-2.79c-0.31,-0.31 -0.85,-0.09 -0.85,0.36L17,5L6,5c-0.55,0 -1,0.45 -1,1v4c0,0.55 0.45,1 1,1s1,-0.45 1,-1L7,7zM17,17L7,17v-1.79c0,-0.45 -0.54,-0.67 -0.85,-0.35l-2.79,2.79c-0.2,0.2 -0.2,0.51 0,0.71l2.79,2.79c0.31,0.31 0.85,0.09 0.85,-0.36L7,19h11c0.55,0 1,-0.45 1,-1v-4c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1v3z" />
+</vector>
diff --git a/app/src/main/res/drawable/ic_round_star_24.xml b/app/src/main/res/drawable/ic_round_star_24.xml
index 3421678ad..335e3bd84 100644
--- a/app/src/main/res/drawable/ic_round_star_24.xml
+++ b/app/src/main/res/drawable/ic_round_star_24.xml
@@ -1,7 +1,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
- android:tint="?attr/colorControlNormal"
+ android:tint="@color/marked_icon"
android:viewportWidth="24"
android:viewportHeight="24">
<path
diff --git a/app/src/main/res/layout/drawer_status.xml b/app/src/main/res/layout/drawer_status.xml
index 443a3e57d..4c062eee6 100644
--- a/app/src/main/res/layout/drawer_status.xml
+++ b/app/src/main/res/layout/drawer_status.xml
@@ -17,6 +17,7 @@
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
+ xmlns:sparkbutton="http://schemas.android.com/apk/res-auto"
android:id="@+id/cardview_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -655,12 +656,11 @@
android:layout_height="48dp"
android:adjustViewBounds="true"
android:contentDescription="@string/reblog_add"
- app:sparkbutton_activeImage="@drawable/ic_round_repeat_24"
- app:sparkbutton_animationSpeed="1.5"
- app:sparkbutton_iconSize="24dp"
- app:sparkbutton_inActiveImage="@drawable/ic_round_repeat_24"
- app:sparkbutton_primaryColor="@color/boost_icon"
- app:sparkbutton_secondaryColor="@color/boost_icon" />
+ app:activeImage="@drawable/ic_round_repeat_active_24"
+ app:iconSize="28dp"
+ app:inactiveImage="@drawable/ic_round_repeat_24"
+ app:primaryColor="@color/boost_icon"
+ app:secondaryColor="@color/boost_icon" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/action_button_quote"
@@ -691,12 +691,12 @@
android:layout_gravity="center"
android:adjustViewBounds="true"
android:contentDescription="@string/favourite_add"
- app:sparkbutton_activeImage="@drawable/ic_round_star_24"
- app:sparkbutton_animationSpeed="1.5"
- app:sparkbutton_iconSize="24dp"
- app:sparkbutton_inActiveImage="@drawable/ic_round_star_border_24"
- app:sparkbutton_primaryColor="@color/marked_icon"
- app:sparkbutton_secondaryColor="@color/marked_icon" />
+ app:activeImage="@drawable/ic_round_star_24"
+ app:animationSpeed="1.5"
+ app:inactiveImage="@drawable/ic_round_star_border_24"
+ app:primaryColor="@color/marked_icon"
+ app:secondaryColor="@color/marked_icon"
+ sparkbutton:iconSize="28dp" />
<com.varunest.sparkbutton.SparkButton
android:id="@+id/action_button_bookmark"
@@ -709,12 +709,12 @@
android:layout_gravity="center"
android:adjustViewBounds="true"
android:contentDescription="@string/bookmark_add"
- app:sparkbutton_activeImage="@drawable/ic_round_bookmark_24"
- app:sparkbutton_animationSpeed="1.5"
- app:sparkbutton_iconSize="24dp"
- app:sparkbutton_inActiveImage="@drawable/ic_round_bookmark_border_24"
- app:sparkbutton_primaryColor="@color/marked_icon"
- app:sparkbutton_secondaryColor="@color/marked_icon" />
+ app:activeImage="@drawable/ic_round_bookmark_24"
+ app:animationSpeed="1.5"
+ app:inactiveImage="@drawable/ic_round_bookmark_border_24"
+ app:primaryColor="@color/marked_icon"
+ app:secondaryColor="@color/marked_icon"
+ sparkbutton:iconSize="28dp" />
<androidx.appcompat.widget.AppCompatImageButton
diff --git a/settings.gradle b/settings.gradle
index eea69bc0f..a2ba1bfb8 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -3,3 +3,4 @@ include ':app'
include ':autoimageslider'
include ':mytransl'
include ':ratethisapp'
+include ':sparkbutton'
diff --git a/sparkbutton/.gitignore b/sparkbutton/.gitignore
new file mode 100644
index 000000000..796b96d1c
--- /dev/null
+++ b/sparkbutton/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/sparkbutton/build.gradle b/sparkbutton/build.gradle
new file mode 100644
index 000000000..54d8db901
--- /dev/null
+++ b/sparkbutton/build.gradle
@@ -0,0 +1,27 @@
+apply plugin: 'com.android.library'
+
+group = 'com.github.tom79'
+
+android {
+ compileSdkVersion 33
+
+ defaultConfig {
+ minSdkVersion 15
+ targetSdkVersion 33
+ versionCode 3
+ versionName "1.0.12"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+ lintOptions {
+ abortOnError false
+ }
+}
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation 'androidx.appcompat:appcompat:1.6.0'
+}
diff --git a/sparkbutton/gradle.properties b/sparkbutton/gradle.properties
new file mode 100644
index 000000000..89a05eff9
--- /dev/null
+++ b/sparkbutton/gradle.properties
@@ -0,0 +1,3 @@
+POM_NAME=SparkButton
+POM_ARTIFACT_ID=sparkbutton
+POM_PACKAGING=aar \ No newline at end of file
diff --git a/sparkbutton/maven-push.gradle b/sparkbutton/maven-push.gradle
new file mode 100644
index 000000000..8ebb6959b
--- /dev/null
+++ b/sparkbutton/maven-push.gradle
@@ -0,0 +1,96 @@
+apply plugin: 'maven'
+apply plugin: 'signing'
+
+def isReleaseBuild() {
+ return VERSION_NAME.contains("SNAPSHOT") == false
+}
+
+def getReleaseRepositoryUrl() {
+ return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
+ : "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
+}
+
+def getSnapshotRepositoryUrl() {
+ return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
+ : "https://oss.sonatype.org/content/repositories/snapshots/"
+}
+
+def getRepositoryUsername() {
+ return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : ""
+}
+
+def getRepositoryPassword() {
+ return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : ""
+}
+
+afterEvaluate { project ->
+ uploadArchives {
+ repositories {
+ mavenDeployer {
+ beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
+
+ pom.groupId = GROUP
+ pom.artifactId = POM_ARTIFACT_ID
+ pom.version = VERSION_NAME
+
+ repository(url: getReleaseRepositoryUrl()) {
+ authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
+ }
+ snapshotRepository(url: getSnapshotRepositoryUrl()) {
+ authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
+ }
+
+ pom.project {
+ name POM_NAME
+ packaging POM_PACKAGING
+ description POM_DESCRIPTION
+ url POM_URL
+
+ scm {
+ url POM_SCM_URL
+ connection POM_SCM_CONNECTION
+ developerConnection POM_SCM_DEV_CONNECTION
+ }
+
+ licenses {
+ license {
+ name POM_LICENCE_NAME
+ url POM_LICENCE_URL
+ distribution POM_LICENCE_DIST
+ }
+ }
+
+ developers {
+ developer {
+ id POM_DEVELOPER_ID
+ name POM_DEVELOPER_NAME
+ }
+ }
+ }
+ }
+ }
+ }
+
+ signing {
+ required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
+ sign configurations.archives
+ }
+
+ //task androidJavadocs(type: Javadoc) {
+ //source = android.sourceSets.main.allJava
+ //}
+
+ //task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
+ //classifier = 'javadoc'
+ //from androidJavadocs.destinationDir
+ //}
+
+ task androidSourcesJar(type: Jar) {
+ classifier = 'sources'
+ from android.sourceSets.main.java.sourceFiles
+ }
+
+ artifacts {
+ archives androidSourcesJar
+ }
+} \ No newline at end of file
diff --git a/sparkbutton/proguard-rules.pro b/sparkbutton/proguard-rules.pro
new file mode 100644
index 000000000..5407790ba
--- /dev/null
+++ b/sparkbutton/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /android-sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/sparkbutton/src/main/AndroidManifest.xml b/sparkbutton/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..1f76ffe6a
--- /dev/null
+++ b/sparkbutton/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<manifest package="com.varunest.sparkbutton">
+
+ <application />
+</manifest>
diff --git a/sparkbutton/src/main/java/com/varunest/sparkbutton/SparkButton.java b/sparkbutton/src/main/java/com/varunest/sparkbutton/SparkButton.java
new file mode 100644
index 000000000..19787c5b8
--- /dev/null
+++ b/sparkbutton/src/main/java/com/varunest/sparkbutton/SparkButton.java
@@ -0,0 +1,313 @@
+package com.varunest.sparkbutton;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.OvershootInterpolator;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.Px;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.core.content.ContextCompat;
+
+import com.varunest.sparkbutton.helpers.SparkAnimationView;
+import com.varunest.sparkbutton.helpers.Utils;
+
+/**
+ * @author varun 7th July 2016
+ */
+public class SparkButton extends FrameLayout implements View.OnClickListener {
+ private static final DecelerateInterpolator DECELERATE_INTERPOLATOR = new DecelerateInterpolator();
+ private static final AccelerateDecelerateInterpolator ACCELERATE_DECELERATE_INTERPOLATOR = new AccelerateDecelerateInterpolator();
+ private static final OvershootInterpolator OVERSHOOT_INTERPOLATOR = new OvershootInterpolator(4);
+
+ private static final int INVALID_RESOURCE_ID = -1;
+ private static final float ANIMATIONVIEW_SIZE_FACTOR = 3;
+ private static final float DOTS_SIZE_FACTOR = .08f;
+ int activeImageTint;
+ int inActiveImageTint;
+ private @DrawableRes
+ int imageResourceIdActive = INVALID_RESOURCE_ID;
+ private @DrawableRes
+ int imageResourceIdInactive = INVALID_RESOURCE_ID;
+ private @Px
+ int imageSize;
+ private @ColorInt
+ int primaryColor;
+ private @ColorInt
+ int secondaryColor;
+ private SparkAnimationView sparkAnimationView;
+ private ImageView imageView;
+ private float animationSpeed = 1;
+ private boolean isChecked = false;
+ private AnimatorSet animatorSet;
+ private SparkEventListener listener;
+
+ SparkButton(Context context) {
+ super(context);
+ }
+
+ public SparkButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initFromXML(attrs);
+ init();
+ }
+
+ public SparkButton(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ initFromXML(attrs);
+ init();
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public SparkButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ initFromXML(attrs);
+ init();
+ }
+
+
+ void init() {
+ int animationViewSize = (int) (imageSize * ANIMATIONVIEW_SIZE_FACTOR);
+
+ sparkAnimationView = new SparkAnimationView(getContext());
+ LayoutParams dotsViewLayoutParams = new LayoutParams(animationViewSize, animationViewSize, Gravity.CENTER);
+ sparkAnimationView.setLayoutParams(dotsViewLayoutParams);
+
+ sparkAnimationView.setColors(secondaryColor, primaryColor);
+ sparkAnimationView.setMaxDotSize((int) (imageSize * DOTS_SIZE_FACTOR));
+
+ addView(sparkAnimationView);
+
+ imageView = new AppCompatImageView(getContext());
+ LayoutParams imageViewLayoutParams = new LayoutParams(imageSize, imageSize, Gravity.CENTER);
+ imageView.setLayoutParams(imageViewLayoutParams);
+
+ addView(imageView);
+
+ if (imageResourceIdInactive != INVALID_RESOURCE_ID) {
+ // should load inactive img first
+ imageView.setImageResource(imageResourceIdInactive);
+ } else if (imageResourceIdActive != INVALID_RESOURCE_ID) {
+ imageView.setImageResource(imageResourceIdActive);
+ } else {
+ throw new IllegalArgumentException("One of Inactive/Active Image Resources is required!");
+ }
+ setOnTouchListener();
+ setOnClickListener(this);
+ }
+
+ /**
+ * Call this function to start spark animation
+ */
+ public void playAnimation() {
+ if (animatorSet != null) {
+ animatorSet.cancel();
+ }
+
+ imageView.animate().cancel();
+ imageView.setScaleX(0);
+ imageView.setScaleY(0);
+ sparkAnimationView.setInnerCircleRadiusProgress(0);
+ sparkAnimationView.setOuterCircleRadiusProgress(0);
+ sparkAnimationView.setCurrentProgress(0);
+
+ animatorSet = new AnimatorSet();
+
+ ObjectAnimator outerCircleAnimator = ObjectAnimator.ofFloat(sparkAnimationView, SparkAnimationView.OUTER_CIRCLE_RADIUS_PROGRESS, 0.1f, 1f);
+ outerCircleAnimator.setDuration((long) (250 / animationSpeed));
+ outerCircleAnimator.setInterpolator(DECELERATE_INTERPOLATOR);
+
+ ObjectAnimator innerCircleAnimator = ObjectAnimator.ofFloat(sparkAnimationView, SparkAnimationView.INNER_CIRCLE_RADIUS_PROGRESS, 0.1f, 1f);
+ innerCircleAnimator.setDuration((long) (200 / animationSpeed));
+ innerCircleAnimator.setStartDelay((long) (200 / animationSpeed));
+ innerCircleAnimator.setInterpolator(DECELERATE_INTERPOLATOR);
+
+ ObjectAnimator starScaleYAnimator = ObjectAnimator.ofFloat(imageView, ImageView.SCALE_Y, 0.2f, 1f);
+ starScaleYAnimator.setDuration((long) (350 / animationSpeed));
+ starScaleYAnimator.setStartDelay((long) (250 / animationSpeed));
+ starScaleYAnimator.setInterpolator(OVERSHOOT_INTERPOLATOR);
+
+ ObjectAnimator starScaleXAnimator = ObjectAnimator.ofFloat(imageView, ImageView.SCALE_X, 0.2f, 1f);
+ starScaleXAnimator.setDuration((long) (350 / animationSpeed));
+ starScaleXAnimator.setStartDelay((long) (250 / animationSpeed));
+ starScaleXAnimator.setInterpolator(OVERSHOOT_INTERPOLATOR);
+
+ ObjectAnimator dotsAnimator = ObjectAnimator.ofFloat(sparkAnimationView, SparkAnimationView.DOTS_PROGRESS, 0, 1f);
+ dotsAnimator.setDuration((long) (900 / animationSpeed));
+ dotsAnimator.setStartDelay((long) (50 / animationSpeed));
+ dotsAnimator.setInterpolator(ACCELERATE_DECELERATE_INTERPOLATOR);
+
+ animatorSet.playTogether(
+ outerCircleAnimator,
+ innerCircleAnimator,
+ starScaleYAnimator,
+ starScaleXAnimator,
+ dotsAnimator
+ );
+
+ animatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ sparkAnimationView.setInnerCircleRadiusProgress(0);
+ sparkAnimationView.setOuterCircleRadiusProgress(0);
+ sparkAnimationView.setCurrentProgress(0);
+ imageView.setScaleX(1);
+ imageView.setScaleY(1);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ }
+ });
+
+ animatorSet.start();
+ }
+
+
+ public @Px
+ int getImageSize() {
+ return imageSize;
+ }
+
+ public void setImageSize(@Px int imageSize) {
+ this.imageSize = imageSize;
+ }
+
+ public @ColorInt
+ int getPrimaryColor() {
+ return primaryColor;
+ }
+
+ public void setPrimaryColor(@ColorInt int primaryColor) {
+ this.primaryColor = primaryColor;
+ }
+
+ public @ColorInt
+ int getSecondaryColor() {
+ return secondaryColor;
+ }
+
+ public void setSecondaryColor(@ColorInt int secondaryColor) {
+ this.secondaryColor = secondaryColor;
+ }
+
+ public void setAnimationSpeed(float animationSpeed) {
+ this.animationSpeed = animationSpeed;
+ }
+
+ /**
+ * @return Returns whether the button is checked (Active) or not.
+ */
+ public boolean isChecked() {
+ return isChecked;
+ }
+
+ /**
+ * Change Button State (Works only if both active and disabled image resource is defined)
+ *
+ * @param flag desired checked state of the button
+ */
+ public void setChecked(boolean flag) {
+ isChecked = flag;
+ imageView.setImageResource(isChecked ? imageResourceIdActive : imageResourceIdInactive);
+ }
+
+ public void setInactiveImage(int inactiveResource) {
+ this.imageResourceIdInactive = inactiveResource;
+ imageView.setImageResource(isChecked ? imageResourceIdActive : imageResourceIdInactive);
+ }
+
+ public void setActiveImage(int activeResource) {
+ this.imageResourceIdActive = activeResource;
+ imageView.setImageResource(isChecked ? imageResourceIdActive : imageResourceIdInactive);
+ }
+
+ @Override
+ public void onClick(View v) {
+ boolean shouldPlayAnimation = listener == null || listener.onEvent(this, isChecked);
+
+ if (shouldPlayAnimation) {
+ if (imageResourceIdInactive != INVALID_RESOURCE_ID) {
+ isChecked = !isChecked;
+
+ imageView.setImageResource(isChecked ? imageResourceIdActive : imageResourceIdInactive);
+
+ if (animatorSet != null) {
+ animatorSet.cancel();
+ }
+ if (isChecked) {
+ sparkAnimationView.setVisibility(VISIBLE);
+ playAnimation();
+ } else {
+ sparkAnimationView.setVisibility(INVISIBLE);
+ }
+ } else {
+ playAnimation();
+ }
+ }
+ }
+
+
+ private void setOnTouchListener() {
+ setOnTouchListener((v, event) -> {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ imageView.animate().scaleX(0.8f).scaleY(0.8f).setDuration(150).setInterpolator(DECELERATE_INTERPOLATOR);
+ setPressed(true);
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ break;
+
+ case MotionEvent.ACTION_UP:
+ imageView.animate().scaleX(1).scaleY(1).setInterpolator(DECELERATE_INTERPOLATOR);
+ if (isPressed()) {
+ performClick();
+ setPressed(false);
+ }
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ imageView.animate().scaleX(1).scaleY(1).setInterpolator(DECELERATE_INTERPOLATOR);
+ break;
+ }
+ return true;
+ });
+ }
+
+ private int getColor(int id) {
+ return ContextCompat.getColor(getContext(), id);
+ }
+
+
+ private void initFromXML(AttributeSet attr) {
+ TypedArray a = getContext().obtainStyledAttributes(attr, R.styleable.SparkButton);
+ imageSize = a.getDimensionPixelOffset(R.styleable.SparkButton_iconSize, Utils.dpToPx(getContext(), 50));
+ imageResourceIdActive = a.getResourceId(R.styleable.SparkButton_activeImage, INVALID_RESOURCE_ID);
+ imageResourceIdInactive = a.getResourceId(R.styleable.SparkButton_inactiveImage, INVALID_RESOURCE_ID);
+ primaryColor = ContextCompat.getColor(getContext(), a.getResourceId(R.styleable.SparkButton_primaryColor, R.color.spark_primary_color));
+ secondaryColor = ContextCompat.getColor(getContext(), a.getResourceId(R.styleable.SparkButton_secondaryColor, R.color.spark_secondary_color));
+ animationSpeed = a.getFloat(R.styleable.SparkButton_animationSpeed, 1);
+ // recycle typedArray
+ a.recycle();
+ }
+}
diff --git a/sparkbutton/src/main/java/com/varunest/sparkbutton/SparkButtonBuilder.java b/sparkbutton/src/main/java/com/varunest/sparkbutton/SparkButtonBuilder.java
new file mode 100644
index 000000000..f79e492e8
--- /dev/null
+++ b/sparkbutton/src/main/java/com/varunest/sparkbutton/SparkButtonBuilder.java
@@ -0,0 +1,61 @@
+package com.varunest.sparkbutton;
+
+import android.content.Context;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.DrawableRes;
+
+import com.varunest.sparkbutton.helpers.Utils;
+
+/**
+ * @author varun on 07/07/16.
+ */
+public class SparkButtonBuilder {
+ private final SparkButton sparkButton;
+ private final Context context;
+
+ public SparkButtonBuilder(Context context) {
+ this.context = context;
+ sparkButton = new SparkButton(context);
+ }
+
+ public SparkButtonBuilder setActiveImage(@DrawableRes int resourceId) {
+ sparkButton.setActiveImage(resourceId);
+ return this;
+ }
+
+ public SparkButtonBuilder setInactiveImage(@DrawableRes int resourceId) {
+ sparkButton.setInactiveImage(resourceId);
+ return this;
+ }
+
+ public SparkButtonBuilder setPrimaryColor(@ColorInt int color) {
+ sparkButton.setPrimaryColor(color);
+ return this;
+ }
+
+ public SparkButtonBuilder setSecondaryColor(int color) {
+ sparkButton.setSecondaryColor(color);
+ return this;
+ }
+
+ public SparkButtonBuilder setImageSizePx(int px) {
+ sparkButton.setImageSize(px);
+ return this;
+ }
+
+ public SparkButtonBuilder setImageSizeDp(int dp) {
+ sparkButton.setImageSize(Utils.dpToPx(context, dp));
+ return this;
+ }
+
+ public SparkButtonBuilder setAnimationSpeed(float speed) {
+ sparkButton.setAnimationSpeed(speed);
+ return this;
+ }
+
+ public SparkButton build() {
+ sparkButton.init();
+ return sparkButton;
+ }
+}
diff --git a/sparkbutton/src/main/java/com/varunest/sparkbutton/SparkEventListener.java b/sparkbutton/src/main/java/com/varunest/sparkbutton/SparkEventListener.java
new file mode 100644
index 000000000..2e02b0891
--- /dev/null
+++ b/sparkbutton/src/main/java/com/varunest/sparkbutton/SparkEventListener.java
@@ -0,0 +1,10 @@
+package com.varunest.sparkbutton;
+
+import androidx.annotation.NonNull;
+
+/**
+ * @author varun on 07/07/16.