diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..0f6e935
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,28 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 27
+ defaultConfig {
+ applicationId "com.example.varun.theglowingloader"
+ minSdkVersion 21
+ targetSdkVersion 27
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation 'com.android.support:appcompat-v7:27.1.1'
+ implementation 'com.android.support.constraint:constraint-layout:1.1.2'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'com.android.support.test:runner:1.0.2'
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/app/src/androidTest/java/com/example/varun/loader/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/example/varun/loader/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..ab3017d
--- /dev/null
+++ b/app/src/androidTest/java/com/example/varun/loader/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.example.varun.loader;
+
+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.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("com.example.varun.theglowingloader", appContext.getPackageName());
+ }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..e9948b1
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/example/varun/MainActivity.java b/app/src/main/java/com/example/varun/MainActivity.java
new file mode 100644
index 0000000..44589cd
--- /dev/null
+++ b/app/src/main/java/com/example/varun/MainActivity.java
@@ -0,0 +1,15 @@
+package com.example.varun;
+
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+
+import com.example.varun.loader.R;
+
+public class MainActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ }
+}
diff --git a/app/src/main/java/com/example/varun/loader/GlowingLoader.java b/app/src/main/java/com/example/varun/loader/GlowingLoader.java
new file mode 100644
index 0000000..791a5b0
--- /dev/null
+++ b/app/src/main/java/com/example/varun/loader/GlowingLoader.java
@@ -0,0 +1,218 @@
+package com.example.varun.loader;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+
+import java.util.logging.Handler;
+
+public class GlowingLoader extends View {
+ private Paint rp;
+ private Paint wp;
+ private float x1, x2, x3, x4, y1, y2, y3, y4;
+ private float xa11, xa12, ya11, ya12, xa21, ya21, xa22, ya22, xa31, ya31, xa32, ya32;
+ private ValueAnimator w11, w12, w21, w22, w31, w32;
+
+ public GlowingLoader(Context context) {
+ super(context);
+ init();
+ }
+
+ public GlowingLoader(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public GlowingLoader(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init();
+ }
+
+ public GlowingLoader(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init();
+ }
+
+ private void init() {
+ rp = new Paint(Paint.ANTI_ALIAS_FLAG);
+ rp.setColor(Color.parseColor("#EF5350"));
+ rp.setStrokeWidth(25);
+ rp.setStrokeCap(Paint.Cap.ROUND);
+
+ wp = new Paint(Paint.ANTI_ALIAS_FLAG);
+ wp.setColor(Color.WHITE);
+ wp.setStrokeWidth(25);
+ wp.setStrokeCap(Paint.Cap.ROUND);
+ }
+
+ private void startAnimation() {
+ Log.d("TAG", String.valueOf(x1));
+ Log.d("TAG", String.valueOf(x2));
+
+ PropertyValuesHolder px1 = PropertyValuesHolder.ofFloat("X", x1, x2);
+ PropertyValuesHolder py1 = PropertyValuesHolder.ofFloat("Y", y1, y2);
+ PropertyValuesHolder px2 = PropertyValuesHolder.ofFloat("X", x2, x3);
+ PropertyValuesHolder py2 = PropertyValuesHolder.ofFloat("Y", y2, y3);
+ PropertyValuesHolder px3 = PropertyValuesHolder.ofFloat("X", x3, x4);
+ PropertyValuesHolder py3 = PropertyValuesHolder.ofFloat("Y", y3, y4);
+
+ w11 = ValueAnimator.ofPropertyValuesHolder(px1, py1);
+ w11.setInterpolator(new AccelerateInterpolator(1.8f));
+ w11.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ xa12 = (float) valueAnimator.getAnimatedValue("X");
+ ya12 = (float) valueAnimator.getAnimatedValue("Y");
+ invalidate();
+ }
+ });
+
+ w12 = ValueAnimator.ofPropertyValuesHolder(px1, py1);
+ w12.setInterpolator(new AccelerateInterpolator(1.8f));
+ w12.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ xa11 = (float) valueAnimator.getAnimatedValue("X");
+ ya11 = (float) valueAnimator.getAnimatedValue("Y");
+ invalidate();
+ }
+ });
+
+ w21 = ValueAnimator.ofPropertyValuesHolder(px2, py2);
+ w21.setInterpolator(new AccelerateInterpolator(1.8f));
+ w21.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ xa22 = (float) valueAnimator.getAnimatedValue("X");
+ ya22 = (float) valueAnimator.getAnimatedValue("Y");
+ invalidate();
+ }
+ });
+
+ w22 = ValueAnimator.ofPropertyValuesHolder(px2, py2);
+ w22.setInterpolator(new AccelerateInterpolator(1.8f));
+ w22.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ xa21 = (float) valueAnimator.getAnimatedValue("X");
+ ya21 = (float) valueAnimator.getAnimatedValue("Y");
+ invalidate();
+ }
+ });
+
+ w31 = ValueAnimator.ofPropertyValuesHolder(px3, py3);
+ w31.setInterpolator(new DecelerateInterpolator(1.8f));
+ w31.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ xa32 = (float) valueAnimator.getAnimatedValue("X");
+ ya32 = (float) valueAnimator.getAnimatedValue("Y");
+ invalidate();
+ }
+ });
+
+ w32 = ValueAnimator.ofPropertyValuesHolder(px3, py3);
+ w32.setInterpolator(new DecelerateInterpolator(1.8f));
+ w32.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ xa31 = (float) valueAnimator.getAnimatedValue("X");
+ ya31 = (float) valueAnimator.getAnimatedValue("Y");
+ invalidate();
+ }
+ });
+
+ int tw11 = 416;
+ int tw21 = 133;
+ int tw31 = 500;
+ w11.setDuration(tw11);
+ w21.setDuration(tw21);
+ w31.setDuration(tw31);
+
+ w21.setStartDelay(tw11);
+ w31.setStartDelay(tw11 + tw21);
+
+ int tw12 = 450;
+ int tw22 = 150;
+ int tw32 = 433;
+ w12.setDuration(tw12);
+ w22.setDuration(tw22);
+ w32.setDuration(tw32);
+
+
+ w22.setStartDelay(tw21);
+ w32.setStartDelay(tw21 + tw22);
+
+ w11.start();
+ w12.start();
+ w21.start();
+ w22.start();
+ w31.start();
+ w32.start();
+
+ w32.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ Runnable r = new Runnable() {
+ @Override
+ public void run() {
+ initCoordinates();
+ startAnimation();
+ }
+ };
+ GlowingLoader.this.postDelayed(r, 1000);
+ }
+ });
+
+ }
+
+ private void initCoordinates() {
+ xa11 = xa12 = x1;
+ xa21 = xa22 = x2;
+ ya11 = ya12 = y1;
+ ya21 = ya22 = y2;
+ xa31 = xa32 = x3;
+ ya31 = ya32 = y3;
+ }
+
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ if (w < h) {
+ x1 = .1f * w;
+ y1 = h / 2 + .15f * w;
+ x2 = .30f * w;
+ y2 = h / 2 + -.15f * w;
+ x3 = .70f * w;
+ y3 = h / 2 + .30f * w;
+ x4 = .9f * w;
+ y4 = h / 2 - .03f * w;
+ } else {
+
+ }
+
+ initCoordinates();
+ startAnimation();
+ super.onSizeChanged(w, h, oldw, oldh);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ canvas.drawLine(xa11, ya11, xa12, ya12, wp);
+ canvas.drawLine(xa21, ya21, xa22, ya22, wp);
+ canvas.drawLine(xa31, ya31, xa32, ya32, wp);
+ }
+}
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..c7bd21d
--- /dev/null
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..d5fccc5
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..da6103b
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a2f5908
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..1b52399
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..ff10afd
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..115a4c7
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..dcd3cd8
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..459ca60
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..8ca12fe
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..8e19b41
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b824ebd
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..4c19a13
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..3ab3e9c
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..961e3aa
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ The Glowing Loader
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..5885930
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/app/src/test/java/com/example/varun/loader/ExampleUnitTest.java b/app/src/test/java/com/example/varun/loader/ExampleUnitTest.java
new file mode 100644
index 0000000..62eb624
--- /dev/null
+++ b/app/src/test/java/com/example/varun/loader/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.example.varun.loader;
+
+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() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..1a3d812
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,27 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.1.2'
+
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..743d692
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,13 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true