diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..c33b7e4
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ xmlns:android
+ ^$
+
+
+
+
+
+
+
+
+ xmlns:.*
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*:id
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ .*:name
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ name
+ ^$
+
+
+
+
+
+
+
+
+ style
+ ^$
+
+
+
+
+
+
+
+
+ .*
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*
+ http://schemas.android.com/apk/res/android
+
+
+ ANDROID_ATTRIBUTE_ORDER
+
+
+
+
+
+
+ .*
+ .*
+
+
+ BY_NAME
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..79ee123
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..66e2f6f
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..7f68460
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 91a0511..3709a89 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,12 +1,13 @@
apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
android {
- compileSdkVersion 25
- buildToolsVersion "25.0.2"
+ compileSdkVersion 29
defaultConfig {
applicationId "com.example.qintong.animatordemo"
- minSdkVersion 16
- targetSdkVersion 25
+ minSdkVersion 19
+ targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -23,11 +24,14 @@ android {
}
dependencies {
- compile fileTree(dir: 'libs', include: ['*.jar'])
- androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
- exclude group: 'com.android.support', module: 'support-annotations'
- })
- compile 'com.android.support:appcompat-v7:25.2.0'
- testCompile 'junit:junit:4.12'
- compile project(path: ':library')
+ implementation project(':library')
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation 'androidx.appcompat:appcompat:1.1.0'
+ implementation 'androidx.core:core-ktx:1.2.0-alpha04'
+ testImplementation 'androidx.test:runner:1.3.0-alpha02'
+ testImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha02'
+}
+repositories {
+ mavenCentral()
}
diff --git a/app/src/androidTest/java/com/example/qintong/animatordemo/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/example/qintong/animatordemo/ExampleInstrumentedTest.java
deleted file mode 100755
index 270e791..0000000
--- a/app/src/androidTest/java/com/example/qintong/animatordemo/ExampleInstrumentedTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.example.qintong.animatordemo;
-
-import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.junit.Assert.*;
-
-/**
- * Instrumentation test, which will execute on an Android device.
- *
- * @see Testing documentation
- */
-@RunWith(AndroidJUnit4.class)
-public class ExampleInstrumentedTest {
- @Test
- public void useAppContext() throws Exception {
- // Context of the app under test.
- Context appContext = InstrumentationRegistry.getTargetContext();
-
- assertEquals("com.example.qintong.animatordemo", appContext.getPackageName());
- }
-}
diff --git a/app/src/androidTest/java/com/example/qintong/animatordemo/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/example/qintong/animatordemo/ExampleInstrumentedTest.kt
new file mode 100755
index 0000000..950846b
--- /dev/null
+++ b/app/src/androidTest/java/com/example/qintong/animatordemo/ExampleInstrumentedTest.kt
@@ -0,0 +1,22 @@
+package com.example.qintong.animatordemo
+
+import androidx.test.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getTargetContext()
+ assertEquals("com.example.qintong.animatordemo", appContext.packageName)
+ }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8084792..15c6fd5 100755
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,6 +1,6 @@
+ package="com.example.qintong.animatordemo">
-
+
-
+
-
diff --git a/app/src/main/java/com/example/qintong/animatordemo/DemoActivity.java b/app/src/main/java/com/example/qintong/animatordemo/DemoActivity.java
deleted file mode 100755
index 1862195..0000000
--- a/app/src/main/java/com/example/qintong/animatordemo/DemoActivity.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.example.qintong.animatordemo;
-
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.view.View;
-import android.widget.Toast;
-import com.qintong.library.InsLoadingView;
-
-import static android.widget.Toast.LENGTH_SHORT;
-
-public class DemoActivity extends AppCompatActivity {
- InsLoadingView mInsLoadingView;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mInsLoadingView = (InsLoadingView) findViewById(R.id.loading_view);
-/* mInsLoadingView.setCircleDuration(2000);
- mInsLoadingView.setRotateDuration(10000);
- mInsLoadingView.setStartColor(Color.YELLOW);
- mInsLoadingView.setEndColor(Color.BLUE);*/
- mInsLoadingView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- switch (mInsLoadingView.getStatus()) {
- case UNCLICKED:
- mInsLoadingView.setStatus(InsLoadingView.Status.LOADING);
- break;
- case LOADING:
- mInsLoadingView.setStatus(InsLoadingView.Status.CLICKED);
- break;
- case CLICKED:
- mInsLoadingView.setStatus(InsLoadingView.Status.UNCLICKED);
- }
- Toast.makeText(DemoActivity.this,"click !", LENGTH_SHORT).show();
- }
- });
- mInsLoadingView.setOnLongClickListener(new View.OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- Toast.makeText(DemoActivity.this,"long click !", LENGTH_SHORT).show();
- return true;
- }
- });
- }
-}
diff --git a/app/src/main/java/com/example/qintong/animatordemo/DemoActivity.kt b/app/src/main/java/com/example/qintong/animatordemo/DemoActivity.kt
new file mode 100755
index 0000000..9e12f1c
--- /dev/null
+++ b/app/src/main/java/com/example/qintong/animatordemo/DemoActivity.kt
@@ -0,0 +1,32 @@
+package com.example.qintong.animatordemo
+
+import android.os.Bundle
+import android.widget.Toast
+import android.widget.Toast.LENGTH_SHORT
+import androidx.appcompat.app.AppCompatActivity
+import com.qintong.library.InsLoadingView
+import kotlinx.android.synthetic.main.activity_main.*
+
+class DemoActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+ /*loading_view?.setCircleDuration(2000)
+ loading_view?.setRotateDuration(10000)
+ loading_view?.setStartColor(Color.YELLOW)
+ loading_view?.setEndColor(Color.BLUE)*/
+ loading_view?.setOnClickListener {
+ when (loading_view?.status) {
+ InsLoadingView.Status.UNCLICKED -> loading_view?.status = InsLoadingView.Status.LOADING
+ InsLoadingView.Status.LOADING -> loading_view?.status = InsLoadingView.Status.CLICKED
+ InsLoadingView.Status.CLICKED -> loading_view?.status = InsLoadingView.Status.UNCLICKED
+ }
+ Toast.makeText(this@DemoActivity, "Click!", LENGTH_SHORT).show()
+ }
+ loading_view?.setOnLongClickListener {
+ Toast.makeText(this@DemoActivity, "Long Click!", LENGTH_SHORT).show()
+ true
+ }
+ }
+}
diff --git a/app/src/main/java/com/example/qintong/animatordemo/TestService.java b/app/src/main/java/com/example/qintong/animatordemo/TestService.java
deleted file mode 100755
index d082033..0000000
--- a/app/src/main/java/com/example/qintong/animatordemo/TestService.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.example.qintong.animatordemo;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.Service;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.IBinder;
-import android.support.annotation.Nullable;
-import android.util.Log;
-
-public class TestService extends Service {
- Handler mHandler;
- @Nullable
- @Override
- public IBinder onBind(Intent intent) {
- Log.d("qintong1", "Service onBind");
- return null;
- }
-
- @Override
- public void onCreate() {
- Log.d("qintong1", "Service onCreate");
- mHandler = new Handler();
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- Log.d("qintong1", "Service onStartCommand: " + (intent == null));
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- Log.d("qintong1", "Service running ");
- Notification.Builder builder = new Notification.Builder(TestService.this);
- builder.setContentText("sbbbbbbb");
- builder.setSmallIcon(R.mipmap.ic_launcher);
- ((NotificationManager)getSystemService(NOTIFICATION_SERVICE)).notify(1,builder.build());
- mHandler.postDelayed(this, 2000);
- }
- }, 2000);
- return START_STICKY;
- }
-
- @Override
- public void onTaskRemoved(Intent rootIntent) {
- Log.d("qintong1", "Service onTaskRemoved");
- }
-}
diff --git a/app/src/main/res/mipmap-mdpi/eric.jpg b/app/src/main/res/drawable/eric.jpg
similarity index 100%
rename from app/src/main/res/mipmap-mdpi/eric.jpg
rename to app/src/main/res/drawable/eric.jpg
diff --git a/app/src/main/res/mipmap-mdpi/pink.jpg b/app/src/main/res/drawable/pink.jpg
similarity index 100%
rename from app/src/main/res/mipmap-mdpi/pink.jpg
rename to app/src/main/res/drawable/pink.jpg
diff --git a/app/src/main/res/mipmap-mdpi/srv.jpg b/app/src/main/res/drawable/srv.jpg
similarity index 100%
rename from app/src/main/res/mipmap-mdpi/srv.jpg
rename to app/src/main/res/drawable/srv.jpg
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 71e7567..8df0d62 100755
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,21 +1,26 @@
-
-
+ android:layout_centerInParent="true"
+ android:scaleType="centerCrop"
+ android:src="@drawable/pink"
+ app:stroke_width="1dp"
+ app:clicked_color="@color/colorGrey"
+ app:corners="round"
+ app:end_color="@color/colorGradientEnd"
+ app:start_color="@color/colorGradientStart"
+ app:status="loading" />
+
+
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 3ab3e9c..fafb8ca 100755
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -3,4 +3,8 @@
#3F51B5
#303F9F
#FF4081
+
+ #FFF700C2
+ #FFFFD900
+ #A0A0A0
diff --git a/app/src/test/java/com/example/qintong/animatordemo/ExampleUnitTest.java b/app/src/test/java/com/example/qintong/animatordemo/ExampleUnitTest.java
deleted file mode 100755
index 98c73de..0000000
--- a/app/src/test/java/com/example/qintong/animatordemo/ExampleUnitTest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.example.qintong.animatordemo;
-
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * @see Testing documentation
- */
-public class ExampleUnitTest {
- @Test
- public void addition_isCorrect() throws Exception {
- assertEquals(4, 2 + 2);
- }
-}
\ No newline at end of file
diff --git a/app/src/test/java/com/example/qintong/animatordemo/ExampleUnitTest.kt b/app/src/test/java/com/example/qintong/animatordemo/ExampleUnitTest.kt
new file mode 100755
index 0000000..59b9ad4
--- /dev/null
+++ b/app/src/test/java/com/example/qintong/animatordemo/ExampleUnitTest.kt
@@ -0,0 +1,16 @@
+package com.example.qintong.animatordemo
+
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index e51f169..7f789ec 100755
--- 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 {
+ ext.kotlin_version = '1.3.50'
repositories {
+ google()
jcenter()
+ mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.2.3'
+ classpath 'com.android.tools.build:gradle:3.5.0'
classpath 'com.novoda:bintray-release:0.5.0'
+ 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,7 +18,9 @@ buildscript {
allprojects {
repositories {
+ google()
jcenter()
+ mavenCentral()
}
}
diff --git a/gradle.properties b/gradle.properties
index aac7c9b..bb8b131 100755
--- a/gradle.properties
+++ b/gradle.properties
@@ -15,3 +15,10 @@ org.gradle.jvmargs=-Xmx1536m
# 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
+
+# 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
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index c8173d9..437552a 100755
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon May 15 20:03:39 CST 2017
+#Wed Sep 11 17:27:53 IST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
diff --git a/library/build.gradle b/library/build.gradle
index e63a433..a6e8347 100755
--- a/library/build.gradle
+++ b/library/build.gradle
@@ -1,19 +1,17 @@
apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.novoda.bintray-release'
-def siteUrl = 'https://github.com/qintong91/InsLoadingAnimation'
+def siteUrl = 'https://github.com/rnkdsh/InsLoadingAnimation'
android {
- compileSdkVersion 25
- buildToolsVersion "25.0.2"
-
+ compileSdkVersion 29
defaultConfig {
- minSdkVersion 15
- targetSdkVersion 25
- versionCode 5
- versionName "1.1.0"
-
+ minSdkVersion 19
+ targetSdkVersion 29
+ versionCode 6
+ versionName "2.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
-
}
buildTypes {
release {
@@ -27,12 +25,12 @@ android {
}
dependencies {
- compile fileTree(dir: 'libs', include: ['*.jar'])
- androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
- exclude group: 'com.android.support', module: 'support-annotations'
- })
- compile 'com.android.support:appcompat-v7:25.2.0'
- testCompile 'junit:junit:4.12'
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation 'androidx.appcompat:appcompat:1.1.0'
+ implementation 'androidx.core:core-ktx:1.2.0-alpha04'
+ testImplementation 'androidx.test:runner:1.3.0-alpha02'
+ testImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha02'
}
publish {
@@ -42,4 +40,4 @@ publish {
publishVersion = '1.1.0'
desc = "Imitation of instagram and weibo loading animation "
website = siteUrl
-}
+}
\ No newline at end of file
diff --git a/library/src/androidTest/java/com/qintong/library/ExampleInstrumentedTest.java b/library/src/androidTest/java/com/qintong/library/ExampleInstrumentedTest.java
deleted file mode 100755
index c1d9c14..0000000
--- a/library/src/androidTest/java/com/qintong/library/ExampleInstrumentedTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.qintong.library;
-
-import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.junit.Assert.*;
-
-/**
- * Instrumentation test, which will execute on an Android device.
- *
- * @see Testing documentation
- */
-@RunWith(AndroidJUnit4.class)
-public class ExampleInstrumentedTest {
- @Test
- public void useAppContext() throws Exception {
- // Context of the app under test.
- Context appContext = InstrumentationRegistry.getTargetContext();
-
- assertEquals("com.example.qintong.library.test", appContext.getPackageName());
- }
-}
diff --git a/library/src/androidTest/java/com/qintong/library/ExampleInstrumentedTest.kt b/library/src/androidTest/java/com/qintong/library/ExampleInstrumentedTest.kt
new file mode 100755
index 0000000..7b4b699
--- /dev/null
+++ b/library/src/androidTest/java/com/qintong/library/ExampleInstrumentedTest.kt
@@ -0,0 +1,22 @@
+package com.qintong.library
+
+import androidx.test.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getTargetContext()
+ assertEquals("com.example.qintong.animatordemo", appContext.packageName)
+ }
+}
diff --git a/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml
index 3d68612..57584be 100755
--- a/library/src/main/AndroidManifest.xml
+++ b/library/src/main/AndroidManifest.xml
@@ -1,10 +1,10 @@
+ package="com.qintong.library">
-
+
diff --git a/library/src/main/java/com/qintong/library/InsLoadingView.java b/library/src/main/java/com/qintong/library/InsLoadingView.java
deleted file mode 100755
index 55bd353..0000000
--- a/library/src/main/java/com/qintong/library/InsLoadingView.java
+++ /dev/null
@@ -1,461 +0,0 @@
-package com.qintong.library;
-
-import android.animation.Animator;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.LinearGradient;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.RectF;
-import android.graphics.Shader;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.LinearInterpolator;
-import android.widget.ImageView;
-
-import static android.graphics.Shader.TileMode.CLAMP;
-
-public class InsLoadingView extends ImageView {
- private static String TAG = "InsLoadingView";
- private static boolean DEBUG = BuildConfig.DEBUG;
- private static final float ARC_WIDTH = 12;
- private static final int MIN_WIDTH = 300;
- private static final float circleDia = 0.9f;
- private static final float strokeWidth = 0.025f;
- private static final float arcChangeAngle = 0.2f;
- private static final int sClickedColor = Color.LTGRAY;
-
- public enum Status {LOADING, CLICKED, UNCLICKED}
-
- private static SparseArray sStatusArray;
-
- static {
- sStatusArray = new SparseArray<>(3);
- sStatusArray.put(0, Status.LOADING);
- sStatusArray.put(1, Status.CLICKED);
- sStatusArray.put(2, Status.UNCLICKED);
- }
-
- private Status mStatus = Status.LOADING;
- private int mRotateDuration = 10000;
- private int mCircleDuration = 2000;
- private float bitmapDia = circleDia - strokeWidth;
- private float degress;
- private float cricleWidth;
- private boolean isFirstCircle = true;
- private ValueAnimator mRotateAnim;
- private ValueAnimator mCircleAnim;
- private ValueAnimator mTouchAnim;
- private int mStartColor = Color.parseColor("#FFF700C2");
- private int mEndColor = Color.parseColor("#FFFFD900");
- private float mScale = 1f;
- private Paint mBitmapPaint;
- private Paint mTrackPaint;
- private RectF mBitmapRectF;
- private RectF mTrackRectF;
-
- public InsLoadingView(Context context) {
- super(context);
- init(context , null);
- }
-
- public InsLoadingView(Context context, AttributeSet attrs) {
- super(context, attrs);
- init(context, attrs);
- }
-
- public InsLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init(context, attrs);
- }
-
- public InsLoadingView setCircleDuration(int circleDuration) {
- this.mCircleDuration = circleDuration;
- mCircleAnim.setDuration(mCircleDuration);
- return this;
- }
-
- public InsLoadingView setRotateDuration(int rotateDuration) {
- this.mRotateDuration = rotateDuration;
- mRotateAnim.setDuration(mRotateDuration);
- return this;
- }
-
- public void setStatus(Status status) {
- this.mStatus = status;
- }
-
- public Status getStatus() {
- return mStatus;
- }
-
- public void setStartColor(int startColor) {
- mStartColor = startColor;
- mTrackPaint = null;
- }
-
- public void setEndColor(int endColor) {
- mEndColor = endColor;
- mTrackPaint = null;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
- final int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
- final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
- final int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
- if (DEBUG) {
- Log.d(TAG, String.format("onMeasure widthMeasureSpec: %s -- %s", widthSpecMode, widthSpecSize));
- Log.d(TAG, String.format("onMeasure heightMeasureSpec: %s -- %s", heightSpecMode, heightSpecSize));
- }
- int width;
- if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) {
- width = Math.min(widthSpecSize, heightSpecSize);
- } else {
- width = Math.min(widthSpecSize, heightSpecSize);
- width = Math.min(width, MIN_WIDTH);
- }
- setMeasuredDimension(width, width);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- initPaints();
- initRectFs();
- canvas.scale(mScale, mScale, centerX(), centerY());
- drawBitmap(canvas);
- switch (mStatus) {
- case LOADING:
- drawTrack(canvas, mTrackPaint);
- break;
- case UNCLICKED:
- drawCircle(canvas, mTrackPaint);
- break;
- case CLICKED:
- drawClickedCircle(canvas);
- break;
- }
- }
-
- @Override
- protected void onVisibilityChanged(View changedView, int visibility) {
- if (DEBUG) {
- Log.d(TAG, "onVisibilityChanged");
- }
- if (visibility == View.VISIBLE) {
- startAnim();
- } else {
- endAnim();
- }
- super.onVisibilityChanged(changedView, visibility);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- boolean result = false;
- if (DEBUG) {
- Log.d(TAG, "onTouchEvent: " + event.getAction());
- }
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN: {
- startDownAnim();
- result = true;
- break;
- }
- case MotionEvent.ACTION_UP: {
- startUpAnim();
- break;
- }
- case MotionEvent.ACTION_CANCEL: {
- startUpAnim();
- break;
- }
- }
- return super.onTouchEvent(event) || result;
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- if (DEBUG) {
- Log.d(TAG, "onSizeChanged");
- }
- mBitmapRectF = null;
- mTrackRectF = null;
- mBitmapPaint = null;
- mTrackPaint = null;
- super.onSizeChanged(w, h, oldw, oldh);
- }
-
- @Override
- public void setImageDrawable(Drawable drawable) {
- if (DEBUG) {
- Log.d(TAG, "setImageDrawable");
- }
- mBitmapPaint = null;
- super.setImageDrawable(drawable);
- }
-
- private void init(Context context, AttributeSet attrs) {
- if (attrs != null) {
- parseAttrs(context, attrs);
- }
- onCreateAnimators();
- }
-
- private void parseAttrs(Context context, AttributeSet attrs) {
- TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.InsLoadingViewAttr);
- int startColor = typedArray.getColor(R.styleable.InsLoadingViewAttr_start_color, mStartColor);
- int endColor = typedArray.getColor(R.styleable.InsLoadingViewAttr_end_color, mEndColor);
- int circleDuration = typedArray.getInt(R.styleable.InsLoadingViewAttr_circle_duration, mCircleDuration);
- int rotateDuration = typedArray.getInt(R.styleable.InsLoadingViewAttr_rotate_duration, mRotateDuration);
- int status = typedArray.getInt(R.styleable.InsLoadingViewAttr_status, 0);
- if (DEBUG) {
- Log.d(TAG, "parseAttrs start_color: " + startColor);
- Log.d(TAG, "parseAttrs end_color: " + endColor);
- Log.d(TAG, "parseAttrs rotate_duration: " + rotateDuration);
- Log.d(TAG, "parseAttrs circle_duration: " + circleDuration);
- Log.d(TAG, "parseAttrs status: " + status);
- }
- typedArray.recycle();
- if (circleDuration != mCircleDuration) {
- setCircleDuration(circleDuration);
- }
- if (rotateDuration != mRotateDuration) {
- setRotateDuration(rotateDuration);
- }
- setStartColor(startColor);
- setEndColor(endColor);
- setStatus(sStatusArray.get(status));
- }
-
- private void initPaints() {
- if (mBitmapPaint == null) {
- mBitmapPaint = getmBitmapPaint();
- }
- if (mTrackPaint == null) {
- mTrackPaint = getTrackPaint();
- }
- }
-
- private void initRectFs() {
- if (mBitmapRectF == null) {
- mBitmapRectF = new RectF(getWidth() * (1 - bitmapDia), getWidth() * (1 - bitmapDia),
- getWidth() * bitmapDia, getHeight() * bitmapDia);
- }
- if (mTrackRectF == null) {
- mTrackRectF = new RectF(getWidth() * (1 - circleDia), getWidth() * (1 - circleDia),
- getWidth() * circleDia, getHeight() * circleDia);
- }
- }
-
- private float centerX() {
- return getWidth() / 2;
- }
-
- private float centerY() {
- return getHeight() / 2;
- }
-
- private void onCreateAnimators() {
- mRotateAnim = ValueAnimator.ofFloat(0, 180, 360);
- mRotateAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- degress = (float) animation.getAnimatedValue();
- postInvalidate();
- }
- });
- mRotateAnim.setInterpolator(new LinearInterpolator());
- mRotateAnim.setDuration(mRotateDuration);
- mRotateAnim.setRepeatCount(-1);
- mCircleAnim = ValueAnimator.ofFloat(0, 360);
- mCircleAnim.setInterpolator(new DecelerateInterpolator());
- mCircleAnim.setDuration(mCircleDuration);
- mCircleAnim.setRepeatCount(-1);
- mCircleAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- if (isFirstCircle) {
- cricleWidth = (float) animation.getAnimatedValue();
- } else {
- cricleWidth = (float) animation.getAnimatedValue() - 360;
- }
- postInvalidate();
- }
- });
- mCircleAnim.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
-
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
-
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
-
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
- isFirstCircle = !isFirstCircle;
- }
- });
- mTouchAnim = new ValueAnimator();
- mTouchAnim.setInterpolator(new DecelerateInterpolator());
- mTouchAnim.setDuration(200);
- mTouchAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mScale = (float) animation.getAnimatedValue();
- postInvalidate();
- }
- });
- startAnim();
- }
-
- private void drawBitmap(Canvas canvas) {
- canvas.drawOval(mBitmapRectF, mBitmapPaint);
- }
-
- private void drawTrack(Canvas canvas, Paint paint) {
- canvas.rotate(degress, centerX(), centerY());
- canvas.rotate(ARC_WIDTH, centerX(), centerY());
-
- if (DEBUG) {
- Log.d(TAG, "cricleWidth:" + cricleWidth);
- }
- if (cricleWidth < 0) {
- //a
- float startArg = cricleWidth + 360;
- canvas.drawArc(mTrackRectF, startArg, 360 - startArg, false, paint);
- float adjustCricleWidth = cricleWidth + 360;
- float width = 8;
- while (adjustCricleWidth > ARC_WIDTH) {
- width = width - arcChangeAngle;
- adjustCricleWidth = adjustCricleWidth - ARC_WIDTH;
- canvas.drawArc(mTrackRectF, adjustCricleWidth, width, false, paint);
- }
- } else {
- //b
- for (int i = 0; i <= 4; i++) {
- if (ARC_WIDTH * i > cricleWidth) {
- break;
- }
- canvas.drawArc(mTrackRectF, cricleWidth - ARC_WIDTH * i, 8 + i, false, paint);
- }
- if (cricleWidth > ARC_WIDTH * 4) {
- canvas.drawArc(mTrackRectF, 0, cricleWidth - ARC_WIDTH * 4, false, paint);
- }
- float adjustCricleWidth = 360;
- float width = 8 * (360 - cricleWidth) / 360;
- if (DEBUG) {
- Log.d(TAG, "width:" + width);
- }
- while (width > 0 && adjustCricleWidth > ARC_WIDTH) {
- width = width - arcChangeAngle;
- adjustCricleWidth = adjustCricleWidth - ARC_WIDTH;
- canvas.drawArc(mTrackRectF, adjustCricleWidth, width, false, paint);
- }
- }
- }
-
- private void drawCircle(Canvas canvas, Paint paint) {
- RectF rectF = new RectF(getWidth() * (1 - circleDia), getWidth() * (1 - circleDia),
- getWidth() * circleDia, getHeight() * circleDia);
- canvas.drawOval(rectF, paint);
- }
-
- private void drawClickedCircle(Canvas canvas) {
- Paint paintClicked = new Paint();
- paintClicked.setColor(sClickedColor);
- setPaintStroke(paintClicked);
- drawCircle(canvas, paintClicked);
- }
-
- private void startDownAnim() {
- mTouchAnim.setFloatValues(mScale, 0.9f);
- mTouchAnim.start();
-
- }
-
- private void startUpAnim() {
- mTouchAnim.setFloatValues(mScale, 1);
- mTouchAnim.start();
- }
-
- private void startAnim() {
- mRotateAnim.start();
- mCircleAnim.start();
- }
-
- private void endAnim() {
- mRotateAnim.end();
- mCircleAnim.end();
- }
-
- private Paint getTrackPaint() {
- Paint paint = new Paint();
- Shader shader = new LinearGradient(0f, 0f, (getWidth() * circleDia * (360 - ARC_WIDTH * 4) / 360),
- getHeight() * strokeWidth, mStartColor, mEndColor, CLAMP);
- paint.setShader(shader);
- setPaintStroke(paint);
- return paint;
- }
-
- private void setPaintStroke(Paint paint) {
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeWidth(getHeight() * strokeWidth);
- }
-
- private Paint getmBitmapPaint() {
- Paint paint = new Paint();
- Drawable drawable = getDrawable();
- Matrix matrix = new Matrix();
- if (null == drawable) {
- return paint;
- }
- Bitmap bitmap = drawableToBitmap(drawable);
- BitmapShader tshader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
- int bSize = Math.min(bitmap.getWidth(), bitmap.getHeight());
- float scale = getWidth() * 1.0f / bSize;
- matrix.setScale(scale, scale);
- if (bitmap.getWidth() > bitmap.getHeight()) {
- matrix.postTranslate(-(bitmap.getWidth() * scale - getWidth()) / 2, 0);
- } else {
- matrix.postTranslate(0, -(bitmap.getHeight() * scale - getHeight()) / 2);
- }
- tshader.setLocalMatrix(matrix);
- paint.setShader(tshader);
- return paint;
- }
-
- private Bitmap drawableToBitmap(Drawable drawable) {
- if (drawable instanceof BitmapDrawable) {
- BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
- return bitmapDrawable.getBitmap();
- }
- int w = drawable.getIntrinsicWidth();
- int h = drawable.getIntrinsicHeight();
- Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- drawable.setBounds(0, 0, w, h);
- drawable.draw(canvas);
- return bitmap;
- }
-}
diff --git a/library/src/main/java/com/qintong/library/InsLoadingView.kt b/library/src/main/java/com/qintong/library/InsLoadingView.kt
new file mode 100755
index 0000000..fe6e4c5
--- /dev/null
+++ b/library/src/main/java/com/qintong/library/InsLoadingView.kt
@@ -0,0 +1,442 @@
+package com.qintong.library
+
+import android.animation.Animator
+import android.animation.ValueAnimator
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.*
+import android.graphics.Shader.TileMode.CLAMP
+import android.graphics.drawable.BitmapDrawable
+import android.graphics.drawable.Drawable
+import android.util.AttributeSet
+import android.util.Log
+import android.util.SparseArray
+import android.view.MotionEvent
+import android.view.View
+import android.view.animation.DecelerateInterpolator
+import android.view.animation.LinearInterpolator
+import android.widget.ImageView
+
+class InsLoadingView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
+) : ImageView(context, attrs, defStyleAttr) {
+
+ var status = Status.LOADING
+ private var mRotateDuration = 10000
+ private var mCircleDuration = 2000
+ private var mRotateDegree: Float = 0.toFloat()
+ private var mCircleWidth: Float = 0.toFloat()
+ private var mStrokeWidth: Float = STROKE_WIDTH / 100
+ private var bitmapDia = CIRCLE_DIA - mStrokeWidth
+ private var mIsFirstCircle = true
+ private var mRotateAnim: ValueAnimator? = null
+ private var mCircleAnim: ValueAnimator? = null
+ private var mTouchAnim: ValueAnimator? = null
+ private var mStartColor = Color.TRANSPARENT
+ private var mEndColor = Color.TRANSPARENT
+ private var mClickedColor = CLICKED_COLOR
+ private var mScale = 1f
+ private var mBitmapPaint: Paint? = null
+ private var mTrackPaint: Paint? = null
+ private var mBitmapRectF: RectF? = null
+ private var mTrackRectF: RectF? = null
+ private var cap: Paint.Cap = Paint.Cap.ROUND
+ private var join: Paint.Join = Paint.Join.ROUND
+
+ private val trackPaint: Paint
+ get() {
+ val paint = Paint()
+ paint.isAntiAlias = true
+ val shader = LinearGradient(
+ 0f, 0f, width.toFloat() * CIRCLE_DIA * (360 - ARC_WIDTH * 4) / 360,
+ height * mStrokeWidth, mStartColor, mEndColor, CLAMP
+ )
+ paint.shader = shader
+ setPaintStroke(paint)
+ return paint
+ }
+
+ private val bitmapPaint: Paint
+ get() {
+ val paint = Paint()
+ paint.isAntiAlias = true
+ val drawable = drawable
+ val matrix = Matrix()
+ if (null == drawable) {
+ return paint
+ }
+ val bitmap = drawableToBitmap(drawable)
+ val shader = BitmapShader(bitmap, CLAMP, CLAMP)
+ val size = Math.min(bitmap.width, bitmap.height)
+ val scale = width * 1.0f / size
+ matrix.setScale(scale, scale)
+ if (bitmap.width > bitmap.height) {
+ matrix.postTranslate(-(bitmap.width * scale - width) / 2, 0f)
+ } else {
+ matrix.postTranslate(0f, -(bitmap.height * scale - height) / 2)
+ }
+ shader.setLocalMatrix(matrix)
+ paint.shader = shader
+ return paint
+ }
+
+ enum class Status {
+ LOADING, CLICKED, UNCLICKED
+ }
+
+ init {
+ if (attrs != null) {
+ parseAttrs(context, attrs)
+ }
+ onCreateAnimators()
+ }
+
+ fun setCircleDuration(circleDuration: Int): InsLoadingView {
+ this.mCircleDuration = circleDuration
+ mCircleAnim!!.duration = mCircleDuration.toLong()
+ return this
+ }
+
+ fun setRotateDuration(rotateDuration: Int): InsLoadingView {
+ this.mRotateDuration = rotateDuration
+ mRotateAnim!!.duration = mRotateDuration.toLong()
+ return this
+ }
+
+ fun setStartColor(startColor: Int) {
+ mStartColor = startColor
+ mTrackPaint = null
+ }
+
+ fun setEndColor(endColor: Int) {
+ mEndColor = endColor
+ mTrackPaint = null
+ }
+
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ val widthSpecMode = MeasureSpec.getMode(widthMeasureSpec)
+ val widthSpecSize = MeasureSpec.getSize(widthMeasureSpec)
+ val heightSpecMode = MeasureSpec.getMode(heightMeasureSpec)
+ val heightSpecSize = MeasureSpec.getSize(heightMeasureSpec)
+ if (DEBUG) {
+ Log.d(TAG, String.format("onMeasure widthMeasureSpec: %s -- %s", widthSpecMode, widthSpecSize))
+ Log.d(TAG, String.format("onMeasure heightMeasureSpec: %s -- %s", heightSpecMode, heightSpecSize))
+ }
+ var width: Int
+ if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) {
+ width = Math.min(widthSpecSize, heightSpecSize)
+ } else {
+ width = Math.min(widthSpecSize, heightSpecSize)
+ width = Math.min(width, MIN_WIDTH)
+ }
+ setMeasuredDimension(width, width)
+ }
+
+ override fun onDraw(canvas: Canvas) {
+ initPaints()
+ initRectFs()
+ canvas.scale(mScale, mScale, centerX(), centerY())
+ drawBitmap(canvas)
+ when (status) {
+ Status.LOADING -> drawTrack(canvas, mTrackPaint)
+ Status.UNCLICKED -> drawCircle(canvas, mTrackPaint)
+ Status.CLICKED -> drawClickedCircle(canvas)
+ }
+ }
+
+ override fun onVisibilityChanged(changedView: View, visibility: Int) {
+ if (DEBUG) {
+ Log.d(TAG, "onVisibilityChanged")
+ }
+ if (visibility == View.VISIBLE) {
+ startAnim()
+ } else {
+ endAnim()
+ }
+ super.onVisibilityChanged(changedView, visibility)
+ }
+
+ @SuppressLint("ClickableViewAccessibility")
+ override fun onTouchEvent(event: MotionEvent): Boolean {
+ var result = false
+ if (DEBUG) {
+ Log.d(TAG, "onTouchEvent: " + event.action)
+ }
+ when (event.action) {
+ MotionEvent.ACTION_DOWN -> {
+ startDownAnim()
+ result = true
+ }
+ MotionEvent.ACTION_UP -> {
+ startUpAnim()
+ }
+ MotionEvent.ACTION_CANCEL -> {
+ startUpAnim()
+ }
+ }
+ return super.onTouchEvent(event) || result
+ }
+
+ override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
+ if (DEBUG) {
+ Log.d(TAG, "onSizeChanged")
+ }
+ mBitmapRectF = null
+ mTrackRectF = null
+ mBitmapPaint = null
+ mTrackPaint = null
+ super.onSizeChanged(w, h, oldw, oldh)
+ }
+
+ override fun setImageDrawable(drawable: Drawable?) {
+ if (DEBUG) {
+ Log.d(TAG, "setImageDrawable")
+ }
+ mBitmapPaint = null
+ super.setImageDrawable(drawable)
+ }
+
+ @SuppressLint("CustomViewStyleable")
+ private fun parseAttrs(context: Context, attrs: AttributeSet) {
+ val typedArray = context.obtainStyledAttributes(attrs, R.styleable.InsLoadingViewAttr)
+ val startColor = typedArray.getColor(R.styleable.InsLoadingViewAttr_start_color, mStartColor)
+ val endColor = typedArray.getColor(R.styleable.InsLoadingViewAttr_end_color, mEndColor)
+ val clickedColor = typedArray.getColor(R.styleable.InsLoadingViewAttr_clicked_color, mClickedColor)
+ val circleDuration = typedArray.getInt(R.styleable.InsLoadingViewAttr_circle_duration, mCircleDuration)
+ val rotateDuration = typedArray.getInt(R.styleable.InsLoadingViewAttr_rotate_duration, mRotateDuration)
+ val strokeWidth = typedArray.getDimension(R.styleable.InsLoadingViewAttr_stroke_width, mStrokeWidth)
+ val status1 = typedArray.getInt(R.styleable.InsLoadingViewAttr_status, 0)
+ val corners = typedArray.getInt(R.styleable.InsLoadingViewAttr_corners, 0)
+ if (corners == 0) {
+ cap = Paint.Cap.ROUND
+ join = Paint.Join.ROUND
+ } else {
+ cap = Paint.Cap.SQUARE
+ join = Paint.Join.MITER
+ }
+ if (DEBUG) {
+ Log.d(TAG, "parseAttrs start_color: $startColor")
+ Log.d(TAG, "parseAttrs end_color: $endColor")
+ Log.d(TAG, "parseAttrs rotate_duration: $rotateDuration")
+ Log.d(TAG, "parseAttrs circle_duration: $circleDuration")
+ Log.d(TAG, "parseAttrs status: $status")
+ }
+ typedArray.recycle()
+ if (circleDuration != mCircleDuration) {
+ setCircleDuration(circleDuration)
+ }
+ if (rotateDuration != mRotateDuration) {
+ setRotateDuration(rotateDuration)
+ }
+ setStartColor(startColor)
+ setEndColor(endColor)
+ status = sStatusArray!!.get(status1)
+ mClickedColor = clickedColor
+ mStrokeWidth = strokeWidth / 100
+ bitmapDia = CIRCLE_DIA - mStrokeWidth
+ }
+
+ private fun initPaints() {
+ if (mBitmapPaint == null) {
+ mBitmapPaint = bitmapPaint
+ }
+ if (mTrackPaint == null) {
+ mTrackPaint = trackPaint
+ }
+ }
+
+ private fun initRectFs() {
+ if (mBitmapRectF == null) {
+ mBitmapRectF = RectF(
+ width * (1 - bitmapDia), width * (1 - bitmapDia),
+ width * bitmapDia, height * bitmapDia
+ )
+ }
+ if (mTrackRectF == null) {
+ mTrackRectF = RectF(
+ width * (1 - CIRCLE_DIA), width * (1 - CIRCLE_DIA),
+ width * CIRCLE_DIA, height * CIRCLE_DIA
+ )
+ }
+ }
+
+ private fun centerX(): Float {
+ return (width / 2).toFloat()
+ }
+
+ private fun centerY(): Float {
+ return (height / 2).toFloat()
+ }
+
+ private fun onCreateAnimators() {
+ mRotateAnim = ValueAnimator.ofFloat(0f, 180f, 360f)
+ mRotateAnim!!.addUpdateListener { animation ->
+ mRotateDegree = animation.animatedValue as Float
+ postInvalidate()
+ }
+ mRotateAnim!!.interpolator = LinearInterpolator()
+ mRotateAnim!!.duration = mRotateDuration.toLong()
+ mRotateAnim!!.repeatCount = -1
+ mCircleAnim = ValueAnimator.ofFloat(0f, 360f)
+ mCircleAnim!!.interpolator = DecelerateInterpolator()
+ mCircleAnim!!.duration = mCircleDuration.toLong()
+ mCircleAnim!!.repeatCount = -1
+ mCircleAnim!!.addUpdateListener { animation ->
+ mCircleWidth = if (mIsFirstCircle) {
+ animation.animatedValue as Float
+ } else {
+ animation.animatedValue as Float - 360
+ }
+ postInvalidate()
+ }
+ mCircleAnim!!.addListener(object : Animator.AnimatorListener {
+ override fun onAnimationStart(animation: Animator) {
+
+ }
+
+ override fun onAnimationEnd(animation: Animator) {
+
+ }
+
+ override fun onAnimationCancel(animation: Animator) {
+
+ }
+
+ override fun onAnimationRepeat(animation: Animator) {
+ mIsFirstCircle = !mIsFirstCircle
+ }
+ })
+ mTouchAnim = ValueAnimator()
+ mTouchAnim!!.interpolator = DecelerateInterpolator()
+ mTouchAnim!!.duration = 200
+ mTouchAnim!!.addUpdateListener { animation ->
+ mScale = animation.animatedValue as Float
+ postInvalidate()
+ }
+ startAnim()
+ }
+
+ private fun drawBitmap(canvas: Canvas) {
+ canvas.drawOval(mBitmapRectF!!, mBitmapPaint!!)
+ }
+
+ private fun drawTrack(canvas: Canvas, paint: Paint?) {
+ canvas.rotate(mRotateDegree, centerX(), centerY())
+ canvas.rotate(ARC_WIDTH, centerX(), centerY())
+
+ if (DEBUG) {
+ Log.d(TAG, "circleWidth:$mCircleWidth")
+ }
+ if (mCircleWidth < 0) {
+ //a
+ val startArg = mCircleWidth + 360
+ canvas.drawArc(mTrackRectF!!, startArg, 360 - startArg, false, paint!!)
+ var adjustCircleWidth = mCircleWidth + 360
+ var width = 8f
+ while (adjustCircleWidth > ARC_WIDTH) {
+ width -= ARC_CHANGE_ANGLE
+ adjustCircleWidth -= ARC_WIDTH
+ canvas.drawArc(mTrackRectF!!, adjustCircleWidth, width, false, paint)
+ }
+ } else {
+ //b
+ for (i in 0..4) {
+ if (ARC_WIDTH * i > mCircleWidth) {
+ break
+ }
+ canvas.drawArc(mTrackRectF!!, mCircleWidth - ARC_WIDTH * i, (8 + i).toFloat(), false, paint!!)
+ }
+ if (mCircleWidth > ARC_WIDTH * 4) {
+ canvas.drawArc(mTrackRectF!!, 0f, mCircleWidth - ARC_WIDTH * 4, false, paint!!)
+ }
+ var adjustCircleWidth = 360f
+ var width = 8 * (360 - mCircleWidth) / 360
+ if (DEBUG) {
+ Log.d(TAG, "width:$width")
+ }
+ while (width > 0 && adjustCircleWidth > ARC_WIDTH) {
+ width -= ARC_CHANGE_ANGLE
+ adjustCircleWidth -= ARC_WIDTH
+ canvas.drawArc(mTrackRectF!!, adjustCircleWidth, width, false, paint!!)
+ }
+ }
+ }
+
+ private fun drawCircle(canvas: Canvas, paint: Paint?) {
+ val rectF = RectF(
+ width * (1 - CIRCLE_DIA), width * (1 - CIRCLE_DIA),
+ width * CIRCLE_DIA, height * CIRCLE_DIA
+ )
+ canvas.drawOval(rectF, paint!!)
+ }
+
+ private fun drawClickedCircle(canvas: Canvas) {
+ val paintClicked = Paint()
+ paintClicked.isAntiAlias = true
+ paintClicked.color = mClickedColor
+ setPaintStroke(paintClicked)
+ drawCircle(canvas, paintClicked)
+ }
+
+ private fun startDownAnim() {
+ mTouchAnim?.setFloatValues(mScale, 0.9f)
+ mTouchAnim?.start()
+ }
+
+ private fun startUpAnim() {
+ mTouchAnim?.setFloatValues(mScale, 1f)
+ mTouchAnim?.start()
+ }
+
+ private fun startAnim() {
+ mRotateAnim?.start()
+ mCircleAnim?.start()
+ }
+
+ private fun endAnim() {
+ mRotateAnim?.end()
+ mCircleAnim?.end()
+ }
+
+ private fun setPaintStroke(paint: Paint) {
+ paint.style = Paint.Style.STROKE
+ paint.strokeWidth = height * mStrokeWidth
+ paint.strokeCap = cap
+ paint.strokeJoin = join
+ }
+
+ private fun drawableToBitmap(drawable: Drawable): Bitmap {
+ if (drawable is BitmapDrawable) {
+ return drawable.bitmap
+ }
+ val w = drawable.intrinsicWidth
+ val h = drawable.intrinsicHeight
+ val bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
+ val canvas = Canvas(bitmap)
+ drawable.setBounds(0, 0, w, h)
+ drawable.draw(canvas)
+ return bitmap
+ }
+
+ companion object {
+ private val DEBUG = BuildConfig.DEBUG
+ private const val TAG = "InsLoadingView"
+ private const val ARC_WIDTH = 12f
+ private const val MIN_WIDTH = 300
+ private const val CIRCLE_DIA = 0.9f
+ private const val STROKE_WIDTH = 1f
+ private const val ARC_CHANGE_ANGLE = 0.2f
+ private const val CLICKED_COLOR = Color.LTGRAY
+
+ private var sStatusArray: SparseArray? = null
+
+ init {
+ sStatusArray = SparseArray(3)
+ sStatusArray?.put(0, Status.LOADING)
+ sStatusArray?.put(1, Status.CLICKED)
+ sStatusArray?.put(2, Status.UNCLICKED)
+ }
+ }
+}
diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml
index ba458aa..3fa519d 100644
--- a/library/src/main/res/values/attrs.xml
+++ b/library/src/main/res/values/attrs.xml
@@ -3,12 +3,18 @@
+
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/library/src/test/java/com/example/qintong/library/ExampleUnitTest.java b/library/src/test/java/com/example/qintong/library/ExampleUnitTest.java
deleted file mode 100755
index d96c82b..0000000
--- a/library/src/test/java/com/example/qintong/library/ExampleUnitTest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.example.qintong.library;
-
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * @see Testing documentation
- */
-public class ExampleUnitTest {
- @Test
- public void addition_isCorrect() throws Exception {
- assertEquals(4, 2 + 2);
- }
-}
\ No newline at end of file
diff --git a/library/src/test/java/com/example/qintong/library/ExampleUnitTest.kt b/library/src/test/java/com/example/qintong/library/ExampleUnitTest.kt
new file mode 100755
index 0000000..d6aa39f
--- /dev/null
+++ b/library/src/test/java/com/example/qintong/library/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.example.qintong.library
+
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see [Testing documentation](http://d.android.com/tools/testing)
+ */
+class ExampleUnitTest {
+ @Test
+ @Throws(Exception::class)
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file