diff --git a/app/build.gradle b/app/build.gradle index a2eb020..7c5440f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,26 +1,70 @@ apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-kapt' android { - compileSdkVersion 22 - buildToolsVersion '25.0.0' + compileSdkVersion 30 + buildToolsVersion "29.0.3" defaultConfig { applicationId "com.github.jlmd.animatedcircleloadingview.sample" minSdkVersion 15 - targetSdkVersion 22 + targetSdkVersion 30 versionCode 1 versionName "1.0" } + buildTypes { release { + shrinkResources false minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } + + + packagingOptions { + exclude 'META-INF/atomicfu.kotlin_module' + } + + + // You can change the value to override the default behavior. + buildFeatures { + // Determines whether to support View Binding. + // Note that the viewBinding.enabled property is now deprecated. + viewBinding = true + // Determines whether to support Data Binding. + // Note that the dataBinding.enabled property is now deprecated. + dataBinding = true + + + } } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:22.2.0' - compile project(':library') + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'androidx.constraintlayout:constraintlayout:2.0.2' + def archLifecycleVersion = '2.2.0' + // Lifecycle components + implementation "androidx.lifecycle:lifecycle-extensions:$archLifecycleVersion" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$archLifecycleVersion" + + + implementation project(':library') + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + + +} +repositories { + mavenCentral() } \ No newline at end of file diff --git a/app/src/main/java/com/github/jlmd/animatedcircleloadingview/sample/MainActivity.java b/app/src/main/java/com/github/jlmd/animatedcircleloadingview/sample/MainActivity.java deleted file mode 100644 index 7f70728..0000000 --- a/app/src/main/java/com/github/jlmd/animatedcircleloadingview/sample/MainActivity.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.github.jlmd.animatedcircleloadingview.sample; - -import android.app.Activity; -import android.os.Bundle; -import android.util.Log; -import com.github.jlmd.animatedcircleloadingview.AnimatedCircleLoadingView; - -public class MainActivity extends Activity { - - private AnimatedCircleLoadingView animatedCircleLoadingView; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - animatedCircleLoadingView = (AnimatedCircleLoadingView) findViewById(R.id.circle_loading_view); - startLoading(); - startPercentMockThread(); - } - - private void startLoading() { - animatedCircleLoadingView.startDeterminate(); - } - - private void startPercentMockThread() { - Runnable runnable = new Runnable() { - @Override - public void run() { - try { - Thread.sleep(1500); - for (int i = 0; i <= 100; i++) { - Thread.sleep(65); - changePercent(i); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }; - new Thread(runnable).start(); - } - - private void changePercent(final int percent) { - runOnUiThread(new Runnable() { - @Override - public void run() { - animatedCircleLoadingView.setPercent(percent); - } - }); - } - - public void resetLoading() { - runOnUiThread(new Runnable() { - @Override - public void run() { - animatedCircleLoadingView.resetLoading(); - } - }); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/github/jlmd/animatedcircleloadingview/sample/MainActivity.kt b/app/src/main/java/com/github/jlmd/animatedcircleloadingview/sample/MainActivity.kt new file mode 100644 index 0000000..432ff78 --- /dev/null +++ b/app/src/main/java/com/github/jlmd/animatedcircleloadingview/sample/MainActivity.kt @@ -0,0 +1,43 @@ +package com.github.jlmd.animatedcircleloadingview.sample + +import android.app.Activity +import android.os.Bundle +import com.github.jlmd.animatedcircleloadingview.AnimatedCircleLoadingView +import kotlinx.android.synthetic.main.activity_main.* +import kotlinx.coroutines.* + +class MainActivity : Activity() { + private var animatedCircleLoadingView: AnimatedCircleLoadingView? = null + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + animatedCircleLoadingView = circle_loading_view + startLoading() + startPercentMockThread() + + } + + private fun startLoading() { + animatedCircleLoadingView!!.startDeterminate() + } + + private fun startPercentMockThread() { + CoroutineScope(Dispatchers.IO).launch { + delay(1000) + for (i in 0..100) { + delay(100) + withContext(Dispatchers.Main) { + changePercent(i) + } + } + } + } + + private fun changePercent(percent: Int) { + animatedCircleLoadingView!!.setPercent(percent) + } + + fun resetLoading() { + animatedCircleLoadingView!!.resetLoading() + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 77ddc9b..db8c690 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,18 +1,22 @@ - - + - + diff --git a/build.gradle b/build.gradle index 5cf0d31..7b81157 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,16 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - repositories { + ext.kotlin_version = '1.4.10' + ext.gradle_version = '3.0.1' + repositories { jcenter() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.2' - // NOTE: Do not place your application dependencies here; they belong + classpath 'com.android.tools.build:gradle:4.0.2' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } @@ -14,5 +18,6 @@ buildscript { allprojects { repositories { jcenter() + google() } } diff --git a/gradle.properties b/gradle.properties index 1d3591c..4d15d01 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,18 +1,21 @@ # Project-wide Gradle settings. - # IDE (e.g. Android Studio) users: # Gradle settings configured through the IDE *will override* # any settings specified in this file. - # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html - # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 - +org.gradle.jvmargs=-Xmx2048m # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 59bb0be..0039de7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Jul 08 22:01:22 CEST 2017 +#Fri Oct 02 08:50:45 IST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/library/build.gradle b/library/build.gradle index f5034f4..8411e6c 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -1,12 +1,13 @@ apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' android { - compileSdkVersion 22 - buildToolsVersion '25.0.0' + compileSdkVersion 30 + buildToolsVersion "29.0.3" defaultConfig { minSdkVersion 14 - targetSdkVersion 22 + targetSdkVersion 30 versionCode 116 versionName "1.1.6" } @@ -19,6 +20,11 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:22.2.0' + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation "androidx.core:core-ktx:1.3.2" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} +repositories { + mavenCentral() } diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/AnimatedCircleLoadingView.java b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/AnimatedCircleLoadingView.java deleted file mode 100644 index 530f810..0000000 --- a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/AnimatedCircleLoadingView.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.github.jlmd.animatedcircleloadingview; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Color; -import android.util.AttributeSet; -import android.widget.FrameLayout; -import com.github.jlmd.animatedcircleloadingview.animator.ViewAnimator; -import com.github.jlmd.animatedcircleloadingview.component.InitialCenterCircleView; -import com.github.jlmd.animatedcircleloadingview.component.MainCircleView; -import com.github.jlmd.animatedcircleloadingview.component.PercentIndicatorView; -import com.github.jlmd.animatedcircleloadingview.component.RightCircleView; -import com.github.jlmd.animatedcircleloadingview.component.SideArcsView; -import com.github.jlmd.animatedcircleloadingview.component.TopCircleBorderView; -import com.github.jlmd.animatedcircleloadingview.component.finish.FinishedFailureView; -import com.github.jlmd.animatedcircleloadingview.component.finish.FinishedOkView; - -/** - * @author jlmd - */ -public class AnimatedCircleLoadingView extends FrameLayout { - - private static final String DEFAULT_HEX_MAIN_COLOR = "#FF9A00"; - private static final String DEFAULT_HEX_SECONDARY_COLOR = "#BDBDBD"; - private static final String DEFAULT_HEX_TINT_COLOR = "#FFFFFF"; - private static final String DEFAULT_HEX_TEXT_COLOR = "#FFFFFF"; - private final Context context; - private InitialCenterCircleView initialCenterCircleView; - private MainCircleView mainCircleView; - private RightCircleView rightCircleView; - private SideArcsView sideArcsView; - private TopCircleBorderView topCircleBorderView; - private FinishedOkView finishedOkView; - private FinishedFailureView finishedFailureView; - private PercentIndicatorView percentIndicatorView; - private ViewAnimator viewAnimator; - private AnimationListener animationListener; - private boolean startAnimationIndeterminate; - private boolean startAnimationDeterminate; - private boolean stopAnimationOk; - private boolean stopAnimationFailure; - private int mainColor; - private int secondaryColor; - private int checkMarkTintColor; - private int failureMarkTintColor; - private int textColor; - - public AnimatedCircleLoadingView(Context context) { - super(context); - this.context = context; - } - - public AnimatedCircleLoadingView(Context context, AttributeSet attrs) { - super(context, attrs); - this.context = context; - initAttributes(attrs); - } - - public AnimatedCircleLoadingView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - this.context = context; - initAttributes(attrs); - } - - private void initAttributes(AttributeSet attrs) { - TypedArray attributes = - getContext().obtainStyledAttributes(attrs, R.styleable.AnimatedCircleLoadingView); - mainColor = attributes.getColor(R.styleable.AnimatedCircleLoadingView_animCircleLoadingView_mainColor, - Color.parseColor(DEFAULT_HEX_MAIN_COLOR)); - secondaryColor = attributes.getColor(R.styleable.AnimatedCircleLoadingView_animCircleLoadingView_secondaryColor, - Color.parseColor(DEFAULT_HEX_SECONDARY_COLOR)); - checkMarkTintColor = - attributes.getColor(R.styleable.AnimatedCircleLoadingView_animCircleLoadingView_checkMarkTintColor, - Color.parseColor(DEFAULT_HEX_TINT_COLOR)); - failureMarkTintColor = - attributes.getColor(R.styleable.AnimatedCircleLoadingView_animCircleLoadingView_failureMarkTintColor, - Color.parseColor(DEFAULT_HEX_TINT_COLOR)); - textColor = attributes.getColor(R.styleable.AnimatedCircleLoadingView_animCircleLoadingView_textColor, - Color.parseColor(DEFAULT_HEX_TEXT_COLOR)); - attributes.recycle(); - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); - init(); - startAnimation(); - } - - private void startAnimation() { - if (getWidth() != 0 && getHeight() != 0) { - if (startAnimationIndeterminate) { - viewAnimator.startAnimator(); - startAnimationIndeterminate = false; - } - if (startAnimationDeterminate) { - addView(percentIndicatorView); - viewAnimator.startAnimator(); - startAnimationDeterminate = false; - } - if (stopAnimationOk) { - stopOk(); - } - if (stopAnimationFailure) { - stopFailure(); - } - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - // Force view to be a square - super.onMeasure(widthMeasureSpec, widthMeasureSpec); - } - - private void init() { - initComponents(); - addComponentsViews(); - initAnimatorHelper(); - } - - private void initComponents() { - int width = getWidth(); - initialCenterCircleView = - new InitialCenterCircleView(context, width, mainColor, secondaryColor); - rightCircleView = new RightCircleView(context, width, mainColor, secondaryColor); - sideArcsView = new SideArcsView(context, width, mainColor, secondaryColor); - topCircleBorderView = new TopCircleBorderView(context, width, mainColor, secondaryColor); - mainCircleView = new MainCircleView(context, width, mainColor, secondaryColor); - finishedOkView = - new FinishedOkView(context, width, mainColor, secondaryColor, checkMarkTintColor); - finishedFailureView = - new FinishedFailureView(context, width, mainColor, secondaryColor, failureMarkTintColor); - percentIndicatorView = new PercentIndicatorView(context, width, textColor); - } - - private void addComponentsViews() { - addView(initialCenterCircleView); - addView(rightCircleView); - addView(sideArcsView); - addView(topCircleBorderView); - addView(mainCircleView); - addView(finishedOkView); - addView(finishedFailureView); - } - - private void initAnimatorHelper() { - viewAnimator = new ViewAnimator(); - viewAnimator.setAnimationListener(animationListener); - viewAnimator.setComponentViewAnimations(initialCenterCircleView, rightCircleView, sideArcsView, - topCircleBorderView, mainCircleView, finishedOkView, finishedFailureView, - percentIndicatorView); - } - - public void startIndeterminate() { - startAnimationIndeterminate = true; - startAnimation(); - } - - public void startDeterminate() { - startAnimationDeterminate = true; - startAnimation(); - } - - public void setPercent(int percent) { - if (percentIndicatorView != null) { - percentIndicatorView.setPercent(percent); - if (percent == 100) { - viewAnimator.finishOk(); - } - } - } - - public void stopOk() { - if (viewAnimator == null) { - stopAnimationOk = true; - } else { - viewAnimator.finishOk(); - } - } - - public void stopFailure() { - if (viewAnimator == null) { - stopAnimationFailure = true; - } else { - viewAnimator.finishFailure(); - } - } - - public void resetLoading() { - if (viewAnimator != null) { - viewAnimator.resetAnimator(); - } - setPercent(0); - } - - public void setAnimationListener(AnimationListener animationListener) { - this.animationListener = animationListener; - } - - public interface AnimationListener { - - void onAnimationEnd(boolean success); - } -} diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/AnimatedCircleLoadingView.kt b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/AnimatedCircleLoadingView.kt new file mode 100644 index 0000000..6f26810 --- /dev/null +++ b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/AnimatedCircleLoadingView.kt @@ -0,0 +1,207 @@ +package com.github.jlmd.animatedcircleloadingview + +import android.content.Context +import android.graphics.Color +import android.util.AttributeSet +import android.widget.FrameLayout +import com.github.jlmd.animatedcircleloadingview.animator.ViewAnimator +import com.github.jlmd.animatedcircleloadingview.component.* +import com.github.jlmd.animatedcircleloadingview.component.finish.FinishedFailureView +import com.github.jlmd.animatedcircleloadingview.component.finish.FinishedOkView + +/** + * @author jlmd + */ +class AnimatedCircleLoadingView : FrameLayout { + + private var initialCenterCircleView: InitialCenterCircleView? = null + private var mainCircleView: MainCircleView? = null + private var rightCircleView: RightCircleView? = null + private var sideArcsView: SideArcsView? = null + private var topCircleBorderView: TopCircleBorderView? = null + private var finishedOkView: FinishedOkView? = null + private var finishedFailureView: FinishedFailureView? = null + private var percentIndicatorView: PercentIndicatorView? = null + private var viewAnimator: ViewAnimator? = null + private var animationListener: AnimationListener? = null + private var startAnimationIndeterminate = false + private var startAnimationDeterminate = false + private var stopAnimationOk = false + private var stopAnimationFailure = false + private var mainColor = 0 + private var secondaryColor = 0 + private var checkMarkTintColor = 0 + private var failureMarkTintColor = 0 + private var textColor = 0 + + constructor(context: Context) : super(context) + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + initAttributes(attrs) + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) { + + initAttributes(attrs) + } + + private fun initAttributes(attrs: AttributeSet?) { + val attributes = + context.obtainStyledAttributes(attrs, R.styleable.AnimatedCircleLoadingView) + mainColor = attributes.getColor( + R.styleable.AnimatedCircleLoadingView_animCircleLoadingView_mainColor, + Color.parseColor(DEFAULT_HEX_MAIN_COLOR) + ) + secondaryColor = attributes.getColor( + R.styleable.AnimatedCircleLoadingView_animCircleLoadingView_secondaryColor, + Color.parseColor(DEFAULT_HEX_SECONDARY_COLOR) + ) + checkMarkTintColor = attributes.getColor( + R.styleable.AnimatedCircleLoadingView_animCircleLoadingView_checkMarkTintColor, + Color.parseColor(DEFAULT_HEX_TINT_COLOR) + ) + failureMarkTintColor = attributes.getColor( + R.styleable.AnimatedCircleLoadingView_animCircleLoadingView_failureMarkTintColor, + Color.parseColor(DEFAULT_HEX_TINT_COLOR) + ) + textColor = attributes.getColor( + R.styleable.AnimatedCircleLoadingView_animCircleLoadingView_textColor, + Color.parseColor(DEFAULT_HEX_TEXT_COLOR) + ) + attributes.recycle() + } + + override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { + super.onSizeChanged(w, h, oldw, oldh) + init() + startAnimation() + } + + private fun startAnimation() { + if (width != 0 && height != 0) { + if (startAnimationIndeterminate) { + viewAnimator!!.startAnimator() + startAnimationIndeterminate = false + } + if (startAnimationDeterminate) { + addView(percentIndicatorView) + viewAnimator!!.startAnimator() + startAnimationDeterminate = false + } + if (stopAnimationOk) { + stopOk() + } + if (stopAnimationFailure) { + stopFailure() + } + } + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + // Force view to be a square + super.onMeasure(widthMeasureSpec, widthMeasureSpec) + } + + private fun init() { + initComponents() + addComponentsViews() + initAnimatorHelper() + } + + private fun initComponents() { + val width = width + initialCenterCircleView = InitialCenterCircleView(context, width, mainColor, secondaryColor) + rightCircleView = RightCircleView(context, width, mainColor, secondaryColor) + sideArcsView = SideArcsView(context, width, mainColor, secondaryColor) + topCircleBorderView = TopCircleBorderView(context, width, mainColor, secondaryColor) + mainCircleView = MainCircleView(context, width, mainColor, secondaryColor) + finishedOkView = + FinishedOkView(context, width, mainColor, secondaryColor, checkMarkTintColor) + finishedFailureView = + FinishedFailureView(context, width, mainColor, secondaryColor, failureMarkTintColor) + percentIndicatorView = PercentIndicatorView(context, width, textColor) + } + + private fun addComponentsViews() { + addView(initialCenterCircleView) + addView(rightCircleView) + addView(sideArcsView) + addView(topCircleBorderView) + addView(mainCircleView) + addView(finishedOkView) + addView(finishedFailureView) + } + + private fun initAnimatorHelper() { + viewAnimator = ViewAnimator() + viewAnimator!!.setAnimationListener(animationListener) + viewAnimator!!.setComponentViewAnimations( + initialCenterCircleView, rightCircleView, sideArcsView, + topCircleBorderView, mainCircleView, finishedOkView, finishedFailureView, + percentIndicatorView + ) + } + + fun startIndeterminate() { + startAnimationIndeterminate = true + startAnimation() + } + + fun startDeterminate() { + startAnimationDeterminate = true + startAnimation() + } + + fun setPercent(percent: Int) { + if (percentIndicatorView != null) { + percentIndicatorView!!.setPercent(percent) + if (percent == 100) { + viewAnimator!!.finishOk() + } + } + } + + fun stopOk() { + if (viewAnimator == null) { + stopAnimationOk = true + } else { + viewAnimator!!.finishOk() + percentIndicatorView = null + } + } + + fun stopFailure() { + if (viewAnimator == null) { + stopAnimationFailure = true + } else { + viewAnimator!!.finishFailure() + percentIndicatorView = null + } + } + + fun resetLoading() { + if (viewAnimator != null) { + viewAnimator!!.resetAnimator() + } + setPercent(0) + } + + fun setAnimationListener(animationListener: AnimationListener?) { + this.animationListener = animationListener + } + + interface AnimationListener { + fun onAnimationEnd(success: Boolean) + } + + companion object { + private const val DEFAULT_HEX_MAIN_COLOR = "#FF9A00" + private const val DEFAULT_HEX_SECONDARY_COLOR = "#BDBDBD" + private const val DEFAULT_HEX_TINT_COLOR = "#FFFFFF" + private const val DEFAULT_HEX_TEXT_COLOR = "#FFFFFF" + } +} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/animator/AnimationState.java b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/animator/AnimationState.java deleted file mode 100644 index 7e36890..0000000 --- a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/animator/AnimationState.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.github.jlmd.animatedcircleloadingview.animator; - -/** - * @author jlmd - */ -public enum AnimationState { - - MAIN_CIRCLE_TRANSLATED_TOP, MAIN_CIRCLE_SCALED_DISAPPEAR, MAIN_CIRCLE_FILLED_TOP, - MAIN_CIRCLE_DRAWN_TOP, MAIN_CIRCLE_TRANSLATED_CENTER, SECONDARY_CIRCLE_FINISHED, - SIDE_ARCS_RESIZED_TOP, FINISHED_OK, FINISHED_FAILURE, ANIMATION_END -} diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/animator/AnimationState.kt b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/animator/AnimationState.kt new file mode 100644 index 0000000..3711acb --- /dev/null +++ b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/animator/AnimationState.kt @@ -0,0 +1,8 @@ +package com.github.jlmd.animatedcircleloadingview.animator + +/** + * @author jlmd + */ +enum class AnimationState { + MAIN_CIRCLE_TRANSLATED_TOP, MAIN_CIRCLE_SCALED_DISAPPEAR, MAIN_CIRCLE_FILLED_TOP, MAIN_CIRCLE_DRAWN_TOP, MAIN_CIRCLE_TRANSLATED_CENTER, SECONDARY_CIRCLE_FINISHED, SIDE_ARCS_RESIZED_TOP, FINISHED_OK, FINISHED_FAILURE, ANIMATION_END +} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/animator/ViewAnimator.java b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/animator/ViewAnimator.java deleted file mode 100644 index 232b73c..0000000 --- a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/animator/ViewAnimator.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.github.jlmd.animatedcircleloadingview.animator; - -import com.github.jlmd.animatedcircleloadingview.AnimatedCircleLoadingView; -import com.github.jlmd.animatedcircleloadingview.component.ComponentViewAnimation; -import com.github.jlmd.animatedcircleloadingview.component.InitialCenterCircleView; -import com.github.jlmd.animatedcircleloadingview.component.MainCircleView; -import com.github.jlmd.animatedcircleloadingview.component.PercentIndicatorView; -import com.github.jlmd.animatedcircleloadingview.component.RightCircleView; -import com.github.jlmd.animatedcircleloadingview.component.SideArcsView; -import com.github.jlmd.animatedcircleloadingview.component.TopCircleBorderView; -import com.github.jlmd.animatedcircleloadingview.component.finish.FinishedFailureView; -import com.github.jlmd.animatedcircleloadingview.component.finish.FinishedOkView; - -/** - * @author jlmd - */ -public class ViewAnimator implements ComponentViewAnimation.StateListener { - - private InitialCenterCircleView initialCenterCircleView; - private RightCircleView rightCircleView; - private SideArcsView sideArcsView; - private TopCircleBorderView topCircleBorderView; - private MainCircleView mainCircleView; - private FinishedOkView finishedOkView; - private FinishedFailureView finishedFailureView; - private PercentIndicatorView percentIndicatorView; - private AnimationState finishedState; - private boolean resetAnimator; - private AnimatedCircleLoadingView.AnimationListener animationListener; - - public void setComponentViewAnimations(InitialCenterCircleView initialCenterCircleView, - RightCircleView rightCircleView, SideArcsView sideArcsView, - TopCircleBorderView topCircleBorderView, MainCircleView mainCircleView, - FinishedOkView finishedOkCircleView, FinishedFailureView finishedFailureView, - PercentIndicatorView percentIndicatorView) { - this.initialCenterCircleView = initialCenterCircleView; - this.rightCircleView = rightCircleView; - this.sideArcsView = sideArcsView; - this.topCircleBorderView = topCircleBorderView; - this.mainCircleView = mainCircleView; - this.finishedOkView = finishedOkCircleView; - this.finishedFailureView = finishedFailureView; - this.percentIndicatorView = percentIndicatorView; - initListeners(); - } - - private void initListeners() { - initialCenterCircleView.setStateListener(this); - rightCircleView.setStateListener(this); - sideArcsView.setStateListener(this); - topCircleBorderView.setStateListener(this); - mainCircleView.setStateListener(this); - finishedOkView.setStateListener(this); - finishedFailureView.setStateListener(this); - } - - public void startAnimator() { - finishedState = null; - initialCenterCircleView.showView(); - initialCenterCircleView.startTranslateTopAnimation(); - initialCenterCircleView.startScaleAnimation(); - rightCircleView.showView(); - rightCircleView.startSecondaryCircleAnimation(); - } - - public void resetAnimator() { - initialCenterCircleView.hideView(); - rightCircleView.hideView(); - sideArcsView.hideView(); - topCircleBorderView.hideView(); - mainCircleView.hideView(); - finishedOkView.hideView(); - finishedFailureView.hideView(); - resetAnimator = true; - startAnimator(); - } - - public void finishOk() { - finishedState = AnimationState.FINISHED_OK; - } - - public void finishFailure() { - finishedState = AnimationState.FINISHED_FAILURE; - } - - public void setAnimationListener(AnimatedCircleLoadingView.AnimationListener animationListener) { - this.animationListener = animationListener; - } - - @Override - public void onStateChanged(AnimationState state) { - if (resetAnimator) { - resetAnimator = false; - } else { - switch (state) { - case MAIN_CIRCLE_TRANSLATED_TOP: - onMainCircleTranslatedTop(); - break; - case MAIN_CIRCLE_SCALED_DISAPPEAR: - onMainCircleScaledDisappear(); - break; - case MAIN_CIRCLE_FILLED_TOP: - onMainCircleFilledTop(); - break; - case SIDE_ARCS_RESIZED_TOP: - onSideArcsResizedTop(); - break; - case MAIN_CIRCLE_DRAWN_TOP: - onMainCircleDrawnTop(); - break; - case FINISHED_OK: - onFinished(state); - break; - case FINISHED_FAILURE: - onFinished(state); - break; - case MAIN_CIRCLE_TRANSLATED_CENTER: - onMainCircleTranslatedCenter(); - break; - case ANIMATION_END: - onAnimationEnd(); - break; - default: - break; - } - } - } - - private void onMainCircleTranslatedTop() { - initialCenterCircleView.startTranslateBottomAnimation(); - initialCenterCircleView.startScaleDisappear(); - } - - private void onMainCircleScaledDisappear() { - initialCenterCircleView.hideView(); - sideArcsView.showView(); - sideArcsView.startRotateAnimation(); - sideArcsView.startResizeDownAnimation(); - } - - private void onSideArcsResizedTop() { - topCircleBorderView.showView(); - topCircleBorderView.startDrawCircleAnimation(); - sideArcsView.hideView(); - } - - private void onMainCircleDrawnTop() { - mainCircleView.showView(); - mainCircleView.startFillCircleAnimation(); - } - - private void onMainCircleFilledTop() { - if (isAnimationFinished()) { - onStateChanged(finishedState); - percentIndicatorView.startAlphaAnimation(); - } else { - topCircleBorderView.hideView(); - mainCircleView.hideView(); - initialCenterCircleView.showView(); - initialCenterCircleView.startTranslateBottomAnimation(); - initialCenterCircleView.startScaleDisappear(); - } - } - - private boolean isAnimationFinished() { - return finishedState != null; - } - - private void onFinished(AnimationState state) { - topCircleBorderView.hideView(); - mainCircleView.hideView(); - finishedState = state; - initialCenterCircleView.showView(); - initialCenterCircleView.startTranslateCenterAnimation(); - } - - private void onMainCircleTranslatedCenter() { - if (finishedState == AnimationState.FINISHED_OK) { - finishedOkView.showView(); - finishedOkView.startScaleAnimation(); - } else { - finishedFailureView.showView(); - finishedFailureView.startScaleAnimation(); - } - initialCenterCircleView.hideView(); - } - - private void onAnimationEnd() { - if (animationListener != null) { - boolean success = finishedState == AnimationState.FINISHED_OK; - animationListener.onAnimationEnd(success); - } - } -} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/animator/ViewAnimator.kt b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/animator/ViewAnimator.kt new file mode 100644 index 0000000..1c8712d --- /dev/null +++ b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/animator/ViewAnimator.kt @@ -0,0 +1,169 @@ +package com.github.jlmd.animatedcircleloadingview.animator + +import com.github.jlmd.animatedcircleloadingview.AnimatedCircleLoadingView +import com.github.jlmd.animatedcircleloadingview.component.* +import com.github.jlmd.animatedcircleloadingview.component.ComponentViewAnimation.StateListener +import com.github.jlmd.animatedcircleloadingview.component.finish.FinishedFailureView +import com.github.jlmd.animatedcircleloadingview.component.finish.FinishedOkView + +/** + * @author jlmd + */ +class ViewAnimator : StateListener { + private var initialCenterCircleView: InitialCenterCircleView? = null + private var rightCircleView: RightCircleView? = null + private var sideArcsView: SideArcsView? = null + private var topCircleBorderView: TopCircleBorderView? = null + private var mainCircleView: MainCircleView? = null + private var finishedOkView: FinishedOkView? = null + private var finishedFailureView: FinishedFailureView? = null + private var percentIndicatorView: PercentIndicatorView? = null + private var finishedState: AnimationState? = null + private var resetAnimator = false + private var animationListener: AnimatedCircleLoadingView.AnimationListener? = null + fun setComponentViewAnimations( + initialCenterCircleView: InitialCenterCircleView?, + rightCircleView: RightCircleView?, sideArcsView: SideArcsView?, + topCircleBorderView: TopCircleBorderView?, mainCircleView: MainCircleView?, + finishedOkCircleView: FinishedOkView?, finishedFailureView: FinishedFailureView?, + percentIndicatorView: PercentIndicatorView? + ) { + this.initialCenterCircleView = initialCenterCircleView + this.rightCircleView = rightCircleView + this.sideArcsView = sideArcsView + this.topCircleBorderView = topCircleBorderView + this.mainCircleView = mainCircleView + finishedOkView = finishedOkCircleView + this.finishedFailureView = finishedFailureView + this.percentIndicatorView = percentIndicatorView + initListeners() + } + + private fun initListeners() { + initialCenterCircleView!!.setStateListener(this) + rightCircleView!!.setStateListener(this) + sideArcsView!!.setStateListener(this) + topCircleBorderView!!.setStateListener(this) + mainCircleView!!.setStateListener(this) + finishedOkView!!.setStateListener(this) + finishedFailureView!!.setStateListener(this) + } + + fun startAnimator() { + finishedState = null + initialCenterCircleView!!.showView() + initialCenterCircleView!!.startTranslateTopAnimation() + initialCenterCircleView!!.startScaleAnimation() + rightCircleView!!.showView() + rightCircleView!!.startSecondaryCircleAnimation() + } + + fun resetAnimator() { + initialCenterCircleView!!.hideView() + rightCircleView!!.hideView() + sideArcsView!!.hideView() + topCircleBorderView!!.hideView() + mainCircleView!!.hideView() + finishedOkView!!.hideView() + finishedFailureView!!.hideView() + resetAnimator = true + startAnimator() + } + + fun finishOk() { + finishedState = AnimationState.FINISHED_OK + } + + fun finishFailure() { + finishedState = AnimationState.FINISHED_FAILURE + } + + fun setAnimationListener(animationListener: AnimatedCircleLoadingView.AnimationListener?) { + this.animationListener = animationListener + } + + override fun onStateChanged(state: AnimationState?) { + if (resetAnimator) { + resetAnimator = false + } else { + when (state) { + AnimationState.MAIN_CIRCLE_TRANSLATED_TOP -> onMainCircleTranslatedTop() + AnimationState.MAIN_CIRCLE_SCALED_DISAPPEAR -> onMainCircleScaledDisappear() + AnimationState.MAIN_CIRCLE_FILLED_TOP -> onMainCircleFilledTop() + AnimationState.SIDE_ARCS_RESIZED_TOP -> onSideArcsResizedTop() + AnimationState.MAIN_CIRCLE_DRAWN_TOP -> onMainCircleDrawnTop() + AnimationState.FINISHED_OK -> onFinished(state) + AnimationState.FINISHED_FAILURE -> onFinished(state) + AnimationState.MAIN_CIRCLE_TRANSLATED_CENTER -> onMainCircleTranslatedCenter() + AnimationState.ANIMATION_END -> onAnimationEnd() + else -> { + } + } + } + } + + private fun onMainCircleTranslatedTop() { + initialCenterCircleView!!.startTranslateBottomAnimation() + initialCenterCircleView!!.startScaleDisappear() + } + + private fun onMainCircleScaledDisappear() { + initialCenterCircleView!!.hideView() + sideArcsView!!.showView() + sideArcsView!!.startRotateAnimation() + sideArcsView!!.startResizeDownAnimation() + } + + private fun onSideArcsResizedTop() { + topCircleBorderView!!.showView() + topCircleBorderView!!.startDrawCircleAnimation() + sideArcsView!!.hideView() + } + + private fun onMainCircleDrawnTop() { + mainCircleView!!.showView() + mainCircleView!!.startFillCircleAnimation() + } + + private fun onMainCircleFilledTop() { + if (isAnimationFinished) { + onStateChanged(finishedState) + percentIndicatorView!!.startAlphaAnimation() + } else { + topCircleBorderView!!.hideView() + mainCircleView!!.hideView() + initialCenterCircleView!!.showView() + initialCenterCircleView!!.startTranslateBottomAnimation() + initialCenterCircleView!!.startScaleDisappear() + } + } + + private val isAnimationFinished: Boolean + get() = finishedState != null + + private fun onFinished(state: AnimationState) { + topCircleBorderView!!.hideView() + mainCircleView!!.hideView() + finishedState = state + initialCenterCircleView!!.showView() + initialCenterCircleView!!.startTranslateCenterAnimation() + } + + private fun onMainCircleTranslatedCenter() { + if (finishedState === AnimationState.FINISHED_OK) { + finishedOkView!!.showView() + finishedOkView!!.startScaleAnimation() + } else { + finishedFailureView!!.showView() + finishedFailureView!!.startScaleAnimation() + } + initialCenterCircleView!!.hideView() + } + + private fun onAnimationEnd() { + if (animationListener != null) { + val success = finishedState === AnimationState.FINISHED_OK + animationListener!!.onAnimationEnd(success) + } + } +} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/ComponentViewAnimation.java b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/ComponentViewAnimation.java deleted file mode 100644 index e0bbade..0000000 --- a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/ComponentViewAnimation.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.github.jlmd.animatedcircleloadingview.component; - -import android.content.Context; -import android.view.View; -import com.github.jlmd.animatedcircleloadingview.animator.AnimationState; -import com.github.jlmd.animatedcircleloadingview.exception.NullStateListenerException; - -/** - * @author jlmd - */ -public abstract class ComponentViewAnimation extends View { - - protected final int parentWidth; - protected final int mainColor; - protected final int secondaryColor; - - protected float parentCenter; - protected float circleRadius; - protected int strokeWidth; - private StateListener stateListener; - - public ComponentViewAnimation(Context context, int parentWidth, int mainColor, - int secondaryColor) { - super(context); - this.parentWidth = parentWidth; - this.mainColor = mainColor; - this.secondaryColor = secondaryColor; - init(); - } - - private void init() { - hideView(); - circleRadius = parentWidth / 10; - parentCenter = parentWidth / 2; - strokeWidth = (12 * parentWidth) / 700; - } - - public void hideView() { - setVisibility(View.GONE); - } - - public void showView() { - setVisibility(View.VISIBLE); - } - - public void setState(AnimationState state) { - if (stateListener != null) { - stateListener.onStateChanged(state); - } else { - throw new NullStateListenerException(); - } - } - - public void setStateListener(StateListener stateListener) { - this.stateListener = stateListener; - } - - public interface StateListener { - - void onStateChanged(AnimationState state); - } -} diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/ComponentViewAnimation.kt b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/ComponentViewAnimation.kt new file mode 100644 index 0000000..dca3f30 --- /dev/null +++ b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/ComponentViewAnimation.kt @@ -0,0 +1,56 @@ +package com.github.jlmd.animatedcircleloadingview.component + +import android.content.Context +import android.view.View +import com.github.jlmd.animatedcircleloadingview.animator.AnimationState +import com.github.jlmd.animatedcircleloadingview.exception.NullStateListenerException + +/** + * @author jlmd + */ +abstract class ComponentViewAnimation( + context: Context?, protected val parentWidth: Int, protected val mainColor: Int, + protected val secondaryColor: Int +) : View(context) { + @JvmField + protected var parentCenter = 0f + @JvmField + protected var circleRadius = 0f + @JvmField + protected var strokeWidth = 0 + private var stateListener: StateListener? = null + private fun init() { + hideView() + circleRadius = parentWidth / 10.toFloat() + parentCenter = parentWidth / 2.toFloat() + strokeWidth = 12 * parentWidth / 700 + } + + fun hideView() { + visibility = GONE + } + + fun showView() { + visibility = VISIBLE + } + + fun setState(state: AnimationState?) { + if (stateListener != null) { + stateListener!!.onStateChanged(state) + } else { + throw NullStateListenerException() + } + } + + fun setStateListener(stateListener: StateListener?) { + this.stateListener = stateListener + } + + interface StateListener { + fun onStateChanged(state: AnimationState?) + } + + init { + init() + } +} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/InitialCenterCircleView.java b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/InitialCenterCircleView.java deleted file mode 100644 index b94e06d..0000000 --- a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/InitialCenterCircleView.java +++ /dev/null @@ -1,190 +0,0 @@ -package com.github.jlmd.animatedcircleloadingview.component; - -import android.animation.Animator; -import android.animation.ObjectAnimator; -import android.animation.ValueAnimator; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.RectF; -import com.github.jlmd.animatedcircleloadingview.animator.AnimationState; - -/** - * @author jlmd - */ -public class InitialCenterCircleView extends ComponentViewAnimation { - - private Paint paint; - private RectF oval; - private float minRadius; - private float currentCircleWidth; - private float currentCircleHeight; - - public InitialCenterCircleView(Context context, int parentWidth, int mainColor, - int secondaryColor) { - super(context, parentWidth, mainColor, secondaryColor); - init(); - } - - private void init() { - initOval(); - initPaint(); - } - - private void initPaint() { - paint = new Paint(); - paint.setStyle(Paint.Style.FILL_AND_STROKE); - paint.setColor(mainColor); - paint.setAntiAlias(true); - } - - private void initOval() { - oval = new RectF(); - minRadius = (15 * parentWidth) / 700; - currentCircleWidth = minRadius; - currentCircleHeight = minRadius; - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - drawCircle(canvas); - } - - public void drawCircle(Canvas canvas) { - - RectF oval = new RectF(); - oval.set(parentCenter - currentCircleWidth, parentCenter - currentCircleHeight, - parentCenter + currentCircleWidth, parentCenter + currentCircleHeight); - canvas.drawOval(oval, paint); - } - - public void startTranslateTopAnimation() { - float translationYTo = -(255 * parentWidth) / 700; - ObjectAnimator translationY = ObjectAnimator.ofFloat(this, "translationY", 0, translationYTo); - translationY.setDuration(1100); - translationY.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - // Empty - } - - @Override - public void onAnimationEnd(Animator animation) { - setState(AnimationState.MAIN_CIRCLE_TRANSLATED_TOP); - } - - @Override - public void onAnimationCancel(Animator animation) { - // Empty - } - - @Override - public void onAnimationRepeat(Animator animation) { - // Empty - } - }); - translationY.start(); - } - - public void startScaleAnimation() { - ValueAnimator valueAnimator = ValueAnimator.ofFloat(minRadius, circleRadius); - valueAnimator.setDuration(1400); - valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - currentCircleWidth = (float) animation.getAnimatedValue(); - currentCircleHeight = (float) animation.getAnimatedValue(); - invalidate(); - } - }); - valueAnimator.start(); - } - - public void startTranslateBottomAnimation() { - float translationYFrom = -(260 * parentWidth) / 700; - float translationYTo = (360 * parentWidth) / 700; - ObjectAnimator translationY = - ObjectAnimator.ofFloat(this, "translationY", translationYFrom, translationYTo); - translationY.setDuration(650); - translationY.start(); - } - - public void startScaleDisappear() { - float maxScaleSize = (250 * parentWidth) / 700; - ValueAnimator valueScaleWidthAnimator = ValueAnimator.ofFloat(circleRadius, maxScaleSize); - valueScaleWidthAnimator.setDuration(260); - valueScaleWidthAnimator.setStartDelay(430); - valueScaleWidthAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - currentCircleWidth = (float) animation.getAnimatedValue(); - invalidate(); - } - }); - valueScaleWidthAnimator.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - // Empty - } - - @Override - public void onAnimationEnd(Animator animation) { - setState(AnimationState.MAIN_CIRCLE_SCALED_DISAPPEAR); - currentCircleWidth = circleRadius + (strokeWidth / 2); - currentCircleHeight = circleRadius + (strokeWidth / 2); - } - - @Override - public void onAnimationCancel(Animator animation) { - // Empty - } - - @Override - public void onAnimationRepeat(Animator animation) { - // Empty - } - }); - valueScaleWidthAnimator.start(); - - ValueAnimator valueScaleHeightAnimator = ValueAnimator.ofFloat(circleRadius, circleRadius / 2); - valueScaleHeightAnimator.setDuration(260); - valueScaleHeightAnimator.setStartDelay(430); - valueScaleHeightAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - currentCircleHeight = (float) animation.getAnimatedValue(); - invalidate(); - } - }); - valueScaleHeightAnimator.start(); - } - - public void startTranslateCenterAnimation() { - float translationYFrom = -(260 * parentWidth) / 700; - ObjectAnimator translationY = ObjectAnimator.ofFloat(this, "translationY", translationYFrom, 0); - translationY.setDuration(650); - translationY.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - // Empty - } - - @Override - public void onAnimationEnd(Animator animation) { - setState(AnimationState.MAIN_CIRCLE_TRANSLATED_CENTER); - } - - @Override - public void onAnimationCancel(Animator animation) { - // Empty - } - - @Override - public void onAnimationRepeat(Animator animation) { - // Empty - } - }); - translationY.start(); - } -} diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/InitialCenterCircleView.kt b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/InitialCenterCircleView.kt new file mode 100644 index 0000000..4ec92e9 --- /dev/null +++ b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/InitialCenterCircleView.kt @@ -0,0 +1,166 @@ +package com.github.jlmd.animatedcircleloadingview.component + +import android.animation.Animator +import android.animation.Animator.AnimatorListener +import android.animation.ObjectAnimator +import android.animation.ValueAnimator +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.RectF +import com.github.jlmd.animatedcircleloadingview.animator.AnimationState + +/** + * @author jlmd + */ +class InitialCenterCircleView( + context: Context?, parentWidth: Int, mainColor: Int, + secondaryColor: Int +) : ComponentViewAnimation(context, parentWidth, mainColor, secondaryColor) { + private var paint: Paint? = null + private var oval: RectF? = null + private var minRadius = 0f + private var currentCircleWidth = 0f + private var currentCircleHeight = 0f + private fun init() { + initOval() + initPaint() + } + + private fun initPaint() { + paint = Paint() + paint!!.style = Paint.Style.FILL_AND_STROKE + paint!!.color = mainColor + paint!!.isAntiAlias = true + } + + private fun initOval() { + oval = RectF() + minRadius = 15 * parentWidth / 700.toFloat() + currentCircleWidth = minRadius + currentCircleHeight = minRadius + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + drawCircle(canvas) + } + + fun drawCircle(canvas: Canvas) { + val oval = RectF() + oval[parentCenter - currentCircleWidth, parentCenter - currentCircleHeight, parentCenter + currentCircleWidth] = + parentCenter + currentCircleHeight + canvas.drawOval(oval, paint!!) + } + + fun startTranslateTopAnimation() { + val translationYTo = -(255 * parentWidth) / 700.toFloat() + val translationY = ObjectAnimator.ofFloat(this, "translationY", 0f, translationYTo) + translationY.duration = 1100 + translationY.addListener(object : AnimatorListener { + override fun onAnimationStart(animation: Animator) { + // Empty + } + + override fun onAnimationEnd(animation: Animator) { + setState(AnimationState.MAIN_CIRCLE_TRANSLATED_TOP) + } + + override fun onAnimationCancel(animation: Animator) { + // Empty + } + + override fun onAnimationRepeat(animation: Animator) { + // Empty + } + }) + translationY.start() + } + + fun startScaleAnimation() { + val valueAnimator = ValueAnimator.ofFloat(minRadius, circleRadius) + valueAnimator.duration = 1400 + valueAnimator.addUpdateListener { animation -> + currentCircleWidth = animation.animatedValue as Float + currentCircleHeight = animation.animatedValue as Float + invalidate() + } + valueAnimator.start() + } + + fun startTranslateBottomAnimation() { + val translationYFrom = -(260 * parentWidth) / 700.toFloat() + val translationYTo = 360 * parentWidth / 700.toFloat() + val translationY = + ObjectAnimator.ofFloat(this, "translationY", translationYFrom, translationYTo) + translationY.duration = 650 + translationY.start() + } + + fun startScaleDisappear() { + val maxScaleSize = 250 * parentWidth / 700.toFloat() + val valueScaleWidthAnimator = ValueAnimator.ofFloat(circleRadius, maxScaleSize) + valueScaleWidthAnimator.duration = 260 + valueScaleWidthAnimator.startDelay = 430 + valueScaleWidthAnimator.addUpdateListener { animation -> + currentCircleWidth = animation.animatedValue as Float + invalidate() + } + valueScaleWidthAnimator.addListener(object : AnimatorListener { + override fun onAnimationStart(animation: Animator) { + // Empty + } + + override fun onAnimationEnd(animation: Animator) { + setState(AnimationState.MAIN_CIRCLE_SCALED_DISAPPEAR) + currentCircleWidth = circleRadius + strokeWidth / 2 + currentCircleHeight = circleRadius + strokeWidth / 2 + } + + override fun onAnimationCancel(animation: Animator) { + // Empty + } + + override fun onAnimationRepeat(animation: Animator) { + // Empty + } + }) + valueScaleWidthAnimator.start() + val valueScaleHeightAnimator = ValueAnimator.ofFloat(circleRadius, circleRadius / 2) + valueScaleHeightAnimator.duration = 260 + valueScaleHeightAnimator.startDelay = 430 + valueScaleHeightAnimator.addUpdateListener { animation -> + currentCircleHeight = animation.animatedValue as Float + invalidate() + } + valueScaleHeightAnimator.start() + } + + fun startTranslateCenterAnimation() { + val translationYFrom = -(260 * parentWidth) / 700.toFloat() + val translationY = ObjectAnimator.ofFloat(this, "translationY", translationYFrom, 0f) + translationY.duration = 650 + translationY.addListener(object : AnimatorListener { + override fun onAnimationStart(animation: Animator) { + // Empty + } + + override fun onAnimationEnd(animation: Animator) { + setState(AnimationState.MAIN_CIRCLE_TRANSLATED_CENTER) + } + + override fun onAnimationCancel(animation: Animator) { + // Empty + } + + override fun onAnimationRepeat(animation: Animator) { + // Empty + } + }) + translationY.start() + } + + init { + init() + } +} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/MainCircleView.java b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/MainCircleView.java deleted file mode 100644 index 8aabf4f..0000000 --- a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/MainCircleView.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.github.jlmd.animatedcircleloadingview.component; - -import android.animation.Animator; -import android.animation.ValueAnimator; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.RectF; -import com.github.jlmd.animatedcircleloadingview.animator.AnimationState; - -/** - * @author jlmd - */ -public class MainCircleView extends ComponentViewAnimation { - - private Paint paint; - private RectF oval; - private int arcFillAngle = 0; - private int arcStartAngle = 0; - - public MainCircleView(Context context, int parentWidth, int mainColor, int secondaryColor) { - super(context, parentWidth, mainColor, secondaryColor); - init(); - } - - private void init() { - initPaint(); - initOval(); - } - - private void initPaint() { - paint = new Paint(); - paint.setColor(mainColor); - paint.setStrokeWidth(strokeWidth); - paint.setStyle(Paint.Style.FILL_AND_STROKE); - paint.setAntiAlias(true); - } - - private void initOval() { - float padding = paint.getStrokeWidth() / 2; - oval = new RectF(); - oval.set(parentCenter - circleRadius, padding, parentCenter + circleRadius, circleRadius * 2); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - drawArcs(canvas); - } - - private void drawArcs(Canvas canvas) { - canvas.drawArc(oval, arcStartAngle, arcFillAngle, false, paint); - } - - public void startFillCircleAnimation() { - ValueAnimator valueAnimator = ValueAnimator.ofInt(90, 360); - valueAnimator.setDuration(800); - valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - arcStartAngle = (int) animation.getAnimatedValue(); - arcFillAngle = (90 - arcStartAngle) * 2; - invalidate(); - } - }); - valueAnimator.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - // Empty - } - - @Override - public void onAnimationEnd(Animator animation) { - setState(AnimationState.MAIN_CIRCLE_FILLED_TOP); - } - - @Override - public void onAnimationCancel(Animator animation) { - // Empty - } - - @Override - public void onAnimationRepeat(Animator animation) { - // Empty - } - }); - valueAnimator.start(); - } -} diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/MainCircleView.kt b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/MainCircleView.kt new file mode 100644 index 0000000..f0a9492 --- /dev/null +++ b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/MainCircleView.kt @@ -0,0 +1,80 @@ +package com.github.jlmd.animatedcircleloadingview.component + +import android.animation.Animator +import android.animation.Animator.AnimatorListener +import android.animation.ValueAnimator +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.RectF +import com.github.jlmd.animatedcircleloadingview.animator.AnimationState + +/** + * @author jlmd + */ +class MainCircleView(context: Context?, parentWidth: Int, mainColor: Int, secondaryColor: Int) : + ComponentViewAnimation(context, parentWidth, mainColor, secondaryColor) { + private var paint: Paint? = null + private var oval: RectF? = null + private var arcFillAngle = 0 + private var arcStartAngle = 0 + private fun init() { + initPaint() + initOval() + } + + private fun initPaint() { + paint = Paint() + paint!!.color = mainColor + paint!!.strokeWidth = strokeWidth.toFloat() + paint!!.style = Paint.Style.FILL_AND_STROKE + paint!!.isAntiAlias = true + } + + private fun initOval() { + val padding = paint!!.strokeWidth / 2 + oval = RectF() + oval!![parentCenter - circleRadius, padding, parentCenter + circleRadius] = circleRadius * 2 + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + drawArcs(canvas) + } + + private fun drawArcs(canvas: Canvas) { + canvas.drawArc(oval!!, arcStartAngle.toFloat(), arcFillAngle.toFloat(), false, paint!!) + } + + fun startFillCircleAnimation() { + val valueAnimator = ValueAnimator.ofInt(90, 360) + valueAnimator.duration = 800 + valueAnimator.addUpdateListener { animation -> + arcStartAngle = animation.animatedValue as Int + arcFillAngle = (90 - arcStartAngle) * 2 + invalidate() + } + valueAnimator.addListener(object : AnimatorListener { + override fun onAnimationStart(animation: Animator) { + // Empty + } + + override fun onAnimationEnd(animation: Animator) { + setState(AnimationState.MAIN_CIRCLE_FILLED_TOP) + } + + override fun onAnimationCancel(animation: Animator) { + // Empty + } + + override fun onAnimationRepeat(animation: Animator) { + // Empty + } + }) + valueAnimator.start() + } + + init { + init() + } +} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/PercentIndicatorView.java b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/PercentIndicatorView.java deleted file mode 100644 index da7cefc..0000000 --- a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/PercentIndicatorView.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.github.jlmd.animatedcircleloadingview.component; - -import android.content.Context; -import android.graphics.Color; -import android.view.Gravity; -import android.view.animation.AlphaAnimation; -import android.widget.TextView; - -/** - * @author jlmd - */ -public class PercentIndicatorView extends TextView { - - private final int parentWidth; - private int textColor = Color.WHITE; - - public PercentIndicatorView(Context context, int parentWidth, int textColor) { - super(context); - this.parentWidth = parentWidth; - this.textColor = textColor; - init(); - } - - private void init() { - int textSize = (35 * parentWidth) / 700; - setTextSize(textSize); - setTextColor(this.textColor); - setGravity(Gravity.CENTER); - setAlpha(0.8f); - } - - public void setPercent(int percent) { - setText(percent + "%"); - } - - public void startAlphaAnimation() { - AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); - alphaAnimation.setDuration(700); - alphaAnimation.setFillAfter(true); - startAnimation(alphaAnimation); - } -} diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/PercentIndicatorView.kt b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/PercentIndicatorView.kt new file mode 100644 index 0000000..70d0bbb --- /dev/null +++ b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/PercentIndicatorView.kt @@ -0,0 +1,40 @@ +package com.github.jlmd.animatedcircleloadingview.component + +import android.content.Context +import android.graphics.Color +import android.view.Gravity +import android.view.animation.AlphaAnimation +import androidx.appcompat.widget.AppCompatTextView + +/** + * @author jlmd + */ +class PercentIndicatorView(context: Context?, private val parentWidth: Int, textColor: Int) : + AppCompatTextView( + context!! + ) { + private var textColor: Int? = null + private fun init() { + val textSize = 35 * parentWidth / 700 + setTextSize(textSize.toFloat()) + setTextColor(textColor!!) + gravity = Gravity.CENTER + alpha = 0.8f + } + + fun setPercent(percent: Int) { + text = "$percent%" + } + + fun startAlphaAnimation() { + val alphaAnimation = AlphaAnimation(1f, 0f) + alphaAnimation.duration = 700 + alphaAnimation.fillAfter = true + startAnimation(alphaAnimation) + } + + init { + this.textColor = textColor + init() + } +} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/RightCircleView.java b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/RightCircleView.java deleted file mode 100644 index 63a3cab..0000000 --- a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/RightCircleView.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.github.jlmd.animatedcircleloadingview.component; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.view.animation.AlphaAnimation; -import android.view.animation.Animation; -import android.view.animation.AnimationSet; -import android.view.animation.TranslateAnimation; -import com.github.jlmd.animatedcircleloadingview.animator.AnimationState; - -/** - * @author jlmd - */ -public class RightCircleView extends ComponentViewAnimation { - - private int rightMargin; - private int bottomMargin; - private Paint paint; - - public RightCircleView(Context context, int parentWidth, int mainColor, int secondaryColor) { - super(context, parentWidth, mainColor, secondaryColor); - init(); - } - - private void init() { - rightMargin = (150 * parentWidth / 700); - bottomMargin = (50 * parentWidth / 700); - initPaint(); - } - - private void initPaint() { - paint = new Paint(); - paint.setStyle(Paint.Style.FILL); - paint.setColor(secondaryColor); - paint.setAntiAlias(true); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - drawCircle(canvas); - } - - public void drawCircle(Canvas canvas) { - canvas.drawCircle(getWidth() - rightMargin, parentCenter - bottomMargin, circleRadius, paint); - } - - public void startSecondaryCircleAnimation() { - int bottomMovementAddition = (260 * parentWidth) / 700; - TranslateAnimation translateAnimation = - new TranslateAnimation(getX(), getX(), getY(), getY() + bottomMovementAddition); - translateAnimation.setStartOffset(200); - translateAnimation.setDuration(1000); - - AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); - alphaAnimation.setStartOffset(1300); - alphaAnimation.setDuration(200); - - AnimationSet animationSet = new AnimationSet(true); - animationSet.addAnimation(translateAnimation); - animationSet.addAnimation(alphaAnimation); - animationSet.setFillAfter(true); - animationSet.setAnimationListener(new Animation.AnimationListener() { - @Override - public void onAnimationStart(Animation animation) { - // Empty - } - - @Override - public void onAnimationEnd(Animation animation) { - setState(AnimationState.SECONDARY_CIRCLE_FINISHED); - } - - @Override - public void onAnimationRepeat(Animation animation) { - // Empty - } - }); - - startAnimation(animationSet); - } -} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/RightCircleView.kt b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/RightCircleView.kt new file mode 100644 index 0000000..f2f9837 --- /dev/null +++ b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/RightCircleView.kt @@ -0,0 +1,81 @@ +package com.github.jlmd.animatedcircleloadingview.component + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.view.animation.AlphaAnimation +import android.view.animation.Animation +import android.view.animation.AnimationSet +import android.view.animation.TranslateAnimation +import com.github.jlmd.animatedcircleloadingview.animator.AnimationState + +/** + * @author jlmd + */ +class RightCircleView(context: Context?, parentWidth: Int, mainColor: Int, secondaryColor: Int) : + ComponentViewAnimation(context, parentWidth, mainColor, secondaryColor) { + private var rightMargin = 0 + private var bottomMargin = 0 + private var paint: Paint? = null + + private fun init() { + rightMargin = 150 * parentWidth / 700 + bottomMargin = 50 * parentWidth / 700 + initPaint() + } + + private fun initPaint() { + paint = Paint() + paint!!.style = Paint.Style.FILL + paint!!.color = secondaryColor + paint!!.isAntiAlias = true + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + drawCircle(canvas) + } + + fun drawCircle(canvas: Canvas) { + canvas.drawCircle( + width - rightMargin.toFloat(), + parentCenter - bottomMargin, + circleRadius, + paint!! + ) + } + + fun startSecondaryCircleAnimation() { + val bottomMovementAddition = 260 * parentWidth / 700 + val translateAnimation = TranslateAnimation(x, x, y, y + bottomMovementAddition) + translateAnimation.startOffset = 200 + translateAnimation.duration = 1000 + + val alphaAnimation = AlphaAnimation(1f, 0f) + alphaAnimation.startOffset = (1300).toLong() + alphaAnimation.duration = (200).toLong() + + val animationSet = AnimationSet(true) + animationSet.addAnimation(translateAnimation) + animationSet.addAnimation(alphaAnimation) + animationSet.fillAfter = true + animationSet.setAnimationListener(object : Animation.AnimationListener { + override fun onAnimationStart(animation: Animation) { + // Empty + } + + override fun onAnimationEnd(animation: Animation) { + setState(AnimationState.SECONDARY_CIRCLE_FINISHED) + } + + override fun onAnimationRepeat(animation: Animation) { + // Empty + } + }) + startAnimation(animationSet) + } + + init { + init() + } +} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/SideArcsView.java b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/SideArcsView.java deleted file mode 100644 index b0b5ec7..0000000 --- a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/SideArcsView.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.github.jlmd.animatedcircleloadingview.component; - -import android.animation.Animator; -import android.animation.ValueAnimator; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.RectF; -import android.view.animation.DecelerateInterpolator; -import com.github.jlmd.animatedcircleloadingview.animator.AnimationState; - -/** - * @author jlmd - */ -public class SideArcsView extends ComponentViewAnimation { - - private static final int MIN_RESIZE_ANGLE = 8; - private static final int MAX_RESIZE_ANGLE = 45; - private static final int INITIAL_LEFT_ARC_START_ANGLE = 100; - private static final int INITIAL_RIGHT_ARC_START_ANGLE = 80; - private static final int MIN_START_ANGLE = 0; - private static final int MAX_START_ANGLE = 165; - private int startLeftArcAngle = INITIAL_LEFT_ARC_START_ANGLE; - private int startRightArcAngle = INITIAL_RIGHT_ARC_START_ANGLE; - private Paint paint; - private RectF oval; - private int arcAngle; - - public SideArcsView(Context context, int parentWidth, int mainColor, int secondaryColor) { - super(context, parentWidth, mainColor, secondaryColor); - init(); - } - - private void init() { - initPaint(); - arcAngle = MAX_RESIZE_ANGLE; - initOval(); - } - - private void initPaint() { - paint = new Paint(); - paint.setColor(mainColor); - paint.setStrokeWidth(strokeWidth); - paint.setStyle(Paint.Style.STROKE); - paint.setAntiAlias(true); - } - - private void initOval() { - float padding = paint.getStrokeWidth() / 2; - oval = new RectF(); - oval.set(padding, padding, parentWidth - padding, parentWidth - padding); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - drawArcs(canvas); - } - - private void drawArcs(Canvas canvas) { - canvas.drawArc(oval, startLeftArcAngle, arcAngle, false, paint); - canvas.drawArc(oval, startRightArcAngle, -arcAngle, false, paint); - } - - public void startRotateAnimation() { - ValueAnimator valueAnimator = ValueAnimator.ofInt(MIN_START_ANGLE, MAX_START_ANGLE); - valueAnimator.setInterpolator(new DecelerateInterpolator()); - valueAnimator.setDuration(550); - valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - startLeftArcAngle = INITIAL_LEFT_ARC_START_ANGLE + (int) animation.getAnimatedValue(); - startRightArcAngle = INITIAL_RIGHT_ARC_START_ANGLE - ((int) animation.getAnimatedValue()); - invalidate(); - } - }); - valueAnimator.start(); - } - - public void startResizeDownAnimation() { - ValueAnimator valueAnimator = ValueAnimator.ofInt(MAX_RESIZE_ANGLE, MIN_RESIZE_ANGLE); - valueAnimator.setInterpolator(new DecelerateInterpolator()); - valueAnimator.setDuration(620); - valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - arcAngle = (int) animation.getAnimatedValue(); - invalidate(); - } - }); - valueAnimator.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - // Empty - } - - @Override - public void onAnimationEnd(Animator animation) { - setState(AnimationState.SIDE_ARCS_RESIZED_TOP); - } - - @Override - public void onAnimationCancel(Animator animation) { - // Empty - } - - @Override - public void onAnimationRepeat(Animator animation) { - // Empty - } - }); - valueAnimator.start(); - } -} diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/SideArcsView.kt b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/SideArcsView.kt new file mode 100644 index 0000000..5c17fab --- /dev/null +++ b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/SideArcsView.kt @@ -0,0 +1,106 @@ +package com.github.jlmd.animatedcircleloadingview.component + +import android.animation.Animator +import android.animation.Animator.AnimatorListener +import android.animation.ValueAnimator +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.RectF +import android.view.animation.DecelerateInterpolator +import com.github.jlmd.animatedcircleloadingview.animator.AnimationState + +/** + * @author jlmd + */ +class SideArcsView(context: Context?, parentWidth: Int, mainColor: Int, secondaryColor: Int) : + ComponentViewAnimation(context, parentWidth, mainColor, secondaryColor) { + private var startLeftArcAngle = INITIAL_LEFT_ARC_START_ANGLE + private var startRightArcAngle = INITIAL_RIGHT_ARC_START_ANGLE + private var paint: Paint? = null + private var oval: RectF? = null + private var arcAngle = 0 + private val addedTime = 0 + private fun init() { + initPaint() + arcAngle = MAX_RESIZE_ANGLE + initOval() + } + + private fun initPaint() { + paint = Paint() + paint!!.color = mainColor + paint!!.strokeWidth = strokeWidth.toFloat() + paint!!.style = Paint.Style.STROKE + paint!!.isAntiAlias = true + } + + private fun initOval() { + val padding = paint!!.strokeWidth / 2 + oval = RectF() + oval!![padding, padding, parentWidth - padding] = parentWidth - padding + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + drawArcs(canvas) + } + + private fun drawArcs(canvas: Canvas) { + canvas.drawArc(oval!!, startLeftArcAngle.toFloat(), arcAngle.toFloat(), false, paint!!) + canvas.drawArc(oval!!, startRightArcAngle.toFloat(), -arcAngle.toFloat(), false, paint!!) + } + + fun startRotateAnimation() { + val valueAnimator = ValueAnimator.ofInt(MIN_START_ANGLE, MAX_START_ANGLE) + valueAnimator.interpolator = DecelerateInterpolator() + valueAnimator.duration = 550 + addedTime.toLong() + valueAnimator.addUpdateListener { animation -> + startLeftArcAngle = INITIAL_LEFT_ARC_START_ANGLE + animation.animatedValue as Int + startRightArcAngle = INITIAL_RIGHT_ARC_START_ANGLE - animation.animatedValue as Int + invalidate() + } + valueAnimator.start() + } + + fun startResizeDownAnimation() { + val valueAnimator = ValueAnimator.ofInt(MAX_RESIZE_ANGLE, MIN_RESIZE_ANGLE) + valueAnimator.interpolator = DecelerateInterpolator() + valueAnimator.duration = 620 + addedTime.toLong() + valueAnimator.addUpdateListener { animation -> + arcAngle = animation.animatedValue as Int + invalidate() + } + valueAnimator.addListener(object : AnimatorListener { + override fun onAnimationStart(animation: Animator) { + // Empty + } + + override fun onAnimationEnd(animation: Animator) { + setState(AnimationState.SIDE_ARCS_RESIZED_TOP) + } + + override fun onAnimationCancel(animation: Animator) { + // Empty + } + + override fun onAnimationRepeat(animation: Animator) { + // Empty + } + }) + valueAnimator.start() + } + + companion object { + private const val MIN_RESIZE_ANGLE = 8 + private const val MAX_RESIZE_ANGLE = 45 + private const val INITIAL_LEFT_ARC_START_ANGLE = 100 + private const val INITIAL_RIGHT_ARC_START_ANGLE = 80 + private const val MIN_START_ANGLE = 0 + private const val MAX_START_ANGLE = 165 + } + + init { + init() + } +} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/TopCircleBorderView.java b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/TopCircleBorderView.java deleted file mode 100644 index 2211d1a..0000000 --- a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/TopCircleBorderView.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.github.jlmd.animatedcircleloadingview.component; - -import android.animation.Animator; -import android.animation.ValueAnimator; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.RectF; -import android.view.animation.DecelerateInterpolator; -import com.github.jlmd.animatedcircleloadingview.animator.AnimationState; - -/** - * @author jlmd - */ -public class TopCircleBorderView extends ComponentViewAnimation { - - private static final int MIN_ANGLE = 25; - private static final int MAX_ANGLE = 180; - private Paint paint; - private RectF oval; - private int arcAngle; - - public TopCircleBorderView(Context context, int parentWidth, int mainColor, int secondaryColor) { - super(context, parentWidth, mainColor, secondaryColor); - init(); - } - - private void init() { - initPaint(); - initOval(); - arcAngle = MIN_ANGLE; - } - - private void initPaint() { - paint = new Paint(); - paint.setColor(mainColor); - paint.setStrokeWidth(strokeWidth); - paint.setStyle(Paint.Style.STROKE); - paint.setAntiAlias(true); - } - - private void initOval() { - float padding = paint.getStrokeWidth() / 2; - oval = new RectF(); - oval.set(parentCenter - circleRadius, padding, parentCenter + circleRadius, circleRadius * 2); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - drawArcs(canvas); - } - - private void drawArcs(Canvas canvas) { - canvas.drawArc(oval, 270, arcAngle, false, paint); - canvas.drawArc(oval, 270, -arcAngle, false, paint); - } - - public void startDrawCircleAnimation() { - ValueAnimator valueAnimator = ValueAnimator.ofInt(MIN_ANGLE, MAX_ANGLE); - valueAnimator.setInterpolator(new DecelerateInterpolator()); - valueAnimator.setDuration(400); - valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - arcAngle = (int) animation.getAnimatedValue(); - invalidate(); - } - }); - valueAnimator.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - // Empty - } - - @Override - public void onAnimationEnd(Animator animation) { - setState(AnimationState.MAIN_CIRCLE_DRAWN_TOP); - } - - @Override - public void onAnimationCancel(Animator animation) { - // Empty - } - - @Override - public void onAnimationRepeat(Animator animation) { - // Empty - } - }); - valueAnimator.start(); - } -} diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/TopCircleBorderView.kt b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/TopCircleBorderView.kt new file mode 100644 index 0000000..5c0d6d6 --- /dev/null +++ b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/TopCircleBorderView.kt @@ -0,0 +1,91 @@ +package com.github.jlmd.animatedcircleloadingview.component + +import android.animation.Animator +import android.animation.Animator.AnimatorListener +import android.animation.ValueAnimator +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.RectF +import android.view.animation.DecelerateInterpolator +import com.github.jlmd.animatedcircleloadingview.animator.AnimationState + +/** + * @author jlmd + */ +class TopCircleBorderView( + context: Context?, + parentWidth: Int, + mainColor: Int, + secondaryColor: Int +) : ComponentViewAnimation(context, parentWidth, mainColor, secondaryColor) { + private var paint: Paint? = null + private var oval: RectF? = null + private var arcAngle = 0 + private fun init() { + initPaint() + initOval() + arcAngle = MIN_ANGLE + } + + private fun initPaint() { + paint = Paint() + paint!!.color = mainColor + paint!!.strokeWidth = strokeWidth.toFloat() + paint!!.style = Paint.Style.STROKE + paint!!.isAntiAlias = true + } + + private fun initOval() { + val padding = paint!!.strokeWidth / 2 + oval = RectF() + oval!![parentCenter - circleRadius, padding, parentCenter + circleRadius] = circleRadius * 2 + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + drawArcs(canvas) + } + + private fun drawArcs(canvas: Canvas) { + canvas.drawArc(oval!!, 270f, arcAngle.toFloat(), false, paint!!) + canvas.drawArc(oval!!, 270f, -arcAngle.toFloat(), false, paint!!) + } + + fun startDrawCircleAnimation() { + val valueAnimator = ValueAnimator.ofInt(MIN_ANGLE, MAX_ANGLE) + valueAnimator.interpolator = DecelerateInterpolator() + valueAnimator.duration = 400 + valueAnimator.addUpdateListener { animation -> + arcAngle = animation.animatedValue as Int + invalidate() + } + valueAnimator.addListener(object : AnimatorListener { + override fun onAnimationStart(animation: Animator) { + // Empty + } + + override fun onAnimationEnd(animation: Animator) { + setState(AnimationState.MAIN_CIRCLE_DRAWN_TOP) + } + + override fun onAnimationCancel(animation: Animator) { + // Empty + } + + override fun onAnimationRepeat(animation: Animator) { + // Empty + } + }) + valueAnimator.start() + } + + companion object { + private const val MIN_ANGLE = 25 + private const val MAX_ANGLE = 180 + } + + init { + init() + } +} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedFailureView.java b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedFailureView.java deleted file mode 100644 index acb0526..0000000 --- a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedFailureView.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.github.jlmd.animatedcircleloadingview.component.finish; - -import android.content.Context; -import com.github.jlmd.animatedcircleloadingview.R; - -/** - * @author jlmd - */ -public class FinishedFailureView extends FinishedView { - - public FinishedFailureView(Context context, int parentWidth, int mainColor, int secondaryColor, - int tintColor) { - super(context, parentWidth, mainColor, secondaryColor, tintColor); - } - - @Override - protected int getDrawable() { - return R.drawable.ic_failure_mark; - } - - @Override - protected int getDrawableTintColor() { - return tintColor; - } - - @Override - protected int getCircleColor() { - return secondaryColor; - } -} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedFailureView.kt b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedFailureView.kt new file mode 100644 index 0000000..d103f2c --- /dev/null +++ b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedFailureView.kt @@ -0,0 +1,19 @@ +package com.github.jlmd.animatedcircleloadingview.component.finish + +import android.content.Context +import com.github.jlmd.animatedcircleloadingview.R + +/** + * @author jlmd + */ +open class FinishedFailureView( + context: Context?, parentWidth: Int, mainColor: Int, secondaryColor: Int, + tintColor: Int +) : FinishedView(context, parentWidth, mainColor, secondaryColor, tintColor) { + override val drawable: Int + get() = R.drawable.ic_failure_mark + override val drawableTintColor: Int + get() = tintColor + override val circleColor: Int + get() = secondaryColor +} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedOkView.java b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedOkView.java deleted file mode 100644 index 9451cda..0000000 --- a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedOkView.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.github.jlmd.animatedcircleloadingview.component.finish; - -import android.content.Context; -import com.github.jlmd.animatedcircleloadingview.R; - -/** - * @author jlmd - */ -public class FinishedOkView extends FinishedView { - - public FinishedOkView(Context context, int parentWidth, int mainColor, int secondaryColor, - int tintColor) { - super(context, parentWidth, mainColor, secondaryColor, tintColor); - } - - @Override - protected int getDrawable() { - return R.drawable.ic_checked_mark; - } - - @Override - protected int getDrawableTintColor() { - return tintColor; - } - - @Override - protected int getCircleColor() { - return mainColor; - } -} diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedOkView.kt b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedOkView.kt new file mode 100644 index 0000000..a24d533 --- /dev/null +++ b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedOkView.kt @@ -0,0 +1,19 @@ +package com.github.jlmd.animatedcircleloadingview.component.finish + +import android.content.Context +import com.github.jlmd.animatedcircleloadingview.R + +/** + * @author jlmd + */ +open class FinishedOkView( + context: Context?, parentWidth: Int, mainColor: Int, secondaryColor: Int, + tintColor: Int +) : FinishedView(context, parentWidth, mainColor, secondaryColor, tintColor) { + override val drawable: Int + get() = R.drawable.ic_checked_mark + override val drawableTintColor: Int + get() = tintColor + override val circleColor: Int + get() = mainColor +} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedView.java b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedView.java deleted file mode 100644 index bbb0eb9..0000000 --- a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedView.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.github.jlmd.animatedcircleloadingview.component.finish; - -import android.animation.Animator; -import android.animation.ValueAnimator; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.LightingColorFilter; -import android.graphics.Paint; -import android.util.Log; -import com.github.jlmd.animatedcircleloadingview.animator.AnimationState; -import com.github.jlmd.animatedcircleloadingview.component.ComponentViewAnimation; - -/** - * @author jlmd - */ -public abstract class FinishedView extends ComponentViewAnimation { - - private static final int MIN_IMAGE_SIZE = 1; - protected final int tintColor; - private int maxImageSize; - private int circleMaxRadius; - private Bitmap originalFinishedBitmap; - private float currentCircleRadius; - private int imageSize; - - public FinishedView(Context context, int parentWidth, int mainColor, int secondaryColor, - int tintColor) { - super(context, parentWidth, mainColor, secondaryColor); - this.tintColor = tintColor; - init(); - } - - private void init() { - maxImageSize = (140 * parentWidth) / 700; - circleMaxRadius = (140 * parentWidth) / 700; - currentCircleRadius = circleRadius; - imageSize = MIN_IMAGE_SIZE; - originalFinishedBitmap = BitmapFactory.decodeResource(getResources(), getDrawable()); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - drawCircle(canvas); - drawCheckedMark(canvas); - } - - private void drawCheckedMark(Canvas canvas) { - Paint paint = new Paint(); - paint.setColorFilter(new LightingColorFilter(getDrawableTintColor(), 0)); - - Bitmap bitmap = Bitmap.createScaledBitmap(originalFinishedBitmap, imageSize, imageSize, true); - canvas.drawBitmap(bitmap, parentCenter - bitmap.getWidth() / 2, - parentCenter - bitmap.getHeight() / 2, paint); - } - - public void drawCircle(Canvas canvas) { - Paint paint = new Paint(); - paint.setStyle(Paint.Style.FILL_AND_STROKE); - paint.setColor(getCircleColor()); - paint.setAntiAlias(true); - canvas.drawCircle(parentCenter, parentCenter, currentCircleRadius, paint); - } - - public void startScaleAnimation() { - startScaleCircleAnimation(); - startScaleImageAnimation(); - } - - private void startScaleCircleAnimation() { - ValueAnimator valueCircleAnimator = - ValueAnimator.ofFloat(circleRadius + strokeWidth / 2, circleMaxRadius); - valueCircleAnimator.setDuration(1000); - valueCircleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - currentCircleRadius = (float) animation.getAnimatedValue(); - invalidate(); - } - }); - valueCircleAnimator.start(); - } - - private void startScaleImageAnimation() { - ValueAnimator valueImageAnimator = ValueAnimator.ofInt(MIN_IMAGE_SIZE, maxImageSize); - valueImageAnimator.setDuration(1000); - valueImageAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - imageSize = (int) animation.getAnimatedValue(); - invalidate(); - } - }); - valueImageAnimator.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - // Empty - } - - @Override - public void onAnimationEnd(Animator animation) { - setState(AnimationState.ANIMATION_END); - } - - @Override - public void onAnimationCancel(Animator animation) { - // Empty - } - - @Override - public void onAnimationRepeat(Animator animation) { - // Empty - } - }); - valueImageAnimator.start(); - } - - protected abstract int getDrawable(); - - protected abstract int getDrawableTintColor(); - - protected abstract int getCircleColor(); -} diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedView.kt b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedView.kt new file mode 100644 index 0000000..2b30d9d --- /dev/null +++ b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/component/finish/FinishedView.kt @@ -0,0 +1,109 @@ +package com.github.jlmd.animatedcircleloadingview.component.finish + +import android.animation.Animator +import android.animation.Animator.AnimatorListener +import android.animation.ValueAnimator +import android.content.Context +import android.graphics.* +import com.github.jlmd.animatedcircleloadingview.animator.AnimationState +import com.github.jlmd.animatedcircleloadingview.component.ComponentViewAnimation + +/** + * @author jlmd + */ +abstract class FinishedView( + context: Context?, parentWidth: Int, mainColor: Int, secondaryColor: Int, + protected val tintColor: Int +) : ComponentViewAnimation(context, parentWidth, mainColor, secondaryColor) { + private var maxImageSize = 0 + private var circleMaxRadius = 0 + private var originalFinishedBitmap: Bitmap? = null + private var currentCircleRadius = 0f + private var imageSize = 0 + private fun init() { + maxImageSize = 140 * parentWidth / 700 + circleMaxRadius = 140 * parentWidth / 700 + currentCircleRadius = circleRadius + imageSize = MIN_IMAGE_SIZE + originalFinishedBitmap = BitmapFactory.decodeResource(resources, drawable) + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + drawCircle(canvas) + drawCheckedMark(canvas) + } + + private fun drawCheckedMark(canvas: Canvas) { + val paint = Paint() + paint.colorFilter = LightingColorFilter(drawableTintColor, 0) + val bitmap = Bitmap.createScaledBitmap(originalFinishedBitmap!!, imageSize, imageSize, true) + canvas.drawBitmap( + bitmap, parentCenter - bitmap.width / 2, + parentCenter - bitmap.height / 2, paint + ) + } + + fun drawCircle(canvas: Canvas) { + val paint = Paint() + paint.style = Paint.Style.FILL_AND_STROKE + paint.color = circleColor + paint.isAntiAlias = true + canvas.drawCircle(parentCenter, parentCenter, currentCircleRadius, paint) + } + + fun startScaleAnimation() { + startScaleCircleAnimation() + startScaleImageAnimation() + } + + private fun startScaleCircleAnimation() { + val valueCircleAnimator = + ValueAnimator.ofFloat(circleRadius + strokeWidth / 2, circleMaxRadius.toFloat()) + valueCircleAnimator.duration = 1000 + valueCircleAnimator.addUpdateListener { animation -> + currentCircleRadius = animation.animatedValue as Float + invalidate() + } + valueCircleAnimator.start() + } + + private fun startScaleImageAnimation() { + val valueImageAnimator = ValueAnimator.ofInt(MIN_IMAGE_SIZE, maxImageSize) + valueImageAnimator.duration = 1000 + valueImageAnimator.addUpdateListener { animation -> + imageSize = animation.animatedValue as Int + invalidate() + } + valueImageAnimator.addListener(object : AnimatorListener { + override fun onAnimationStart(animation: Animator) { + // Empty + } + + override fun onAnimationEnd(animation: Animator) { + setState(AnimationState.ANIMATION_END) + } + + override fun onAnimationCancel(animation: Animator) { + // Empty + } + + override fun onAnimationRepeat(animation: Animator) { + // Empty + } + }) + valueImageAnimator.start() + } + + protected abstract val drawable: Int + protected abstract val drawableTintColor: Int + protected abstract val circleColor: Int + + companion object { + private const val MIN_IMAGE_SIZE = 1 + } + + init { + init() + } +} \ No newline at end of file diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/exception/NullStateListenerException.java b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/exception/NullStateListenerException.java deleted file mode 100644 index 1695768..0000000 --- a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/exception/NullStateListenerException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.github.jlmd.animatedcircleloadingview.exception; - -/** - * @author jlmd - */ -public class NullStateListenerException extends RuntimeException { - // Empty -} diff --git a/library/src/main/java/com/github/jlmd/animatedcircleloadingview/exception/NullStateListenerException.kt b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/exception/NullStateListenerException.kt new file mode 100644 index 0000000..272efe4 --- /dev/null +++ b/library/src/main/java/com/github/jlmd/animatedcircleloadingview/exception/NullStateListenerException.kt @@ -0,0 +1,7 @@ +package com.github.jlmd.animatedcircleloadingview.exception + +/** + * @author jlmd + */ +class NullStateListenerException : RuntimeException() { // Empty +} \ No newline at end of file