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