diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5edb4ee
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+*.iml
+.gradle
+/local.properties
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..97626ba
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..206b933
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..99202cc
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
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..99f7877
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,32 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+
+android {
+ compileSdkVersion 27
+ defaultConfig {
+ applicationId "bg.devlabs.twinklelibrary"
+ minSdkVersion 19
+ 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"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
+ 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'
+ implementation project(path: ':twinkle')
+}
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/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..f260dfa
--- /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/bg/devlabs/twinklelibrary/TwinkleActivity.kt b/app/src/main/java/bg/devlabs/twinklelibrary/TwinkleActivity.kt
new file mode 100644
index 0000000..de150d8
--- /dev/null
+++ b/app/src/main/java/bg/devlabs/twinklelibrary/TwinkleActivity.kt
@@ -0,0 +1,35 @@
+package bg.devlabs.twinklelibrary
+
+import android.support.v7.app.AppCompatActivity
+import android.os.Bundle
+import android.os.Handler
+import android.util.Log
+import bg.devlabs.twinkle.Twinkle
+import bg.devlabs.twinkle.twinkle
+import kotlinx.android.synthetic.main.activity_twinkle.*
+
+class TwinkleActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_twinkle)
+
+ val t: Twinkle = twinkle_text.twinkle()
+ delay(1000) {
+ t.stop()
+ }
+ }
+
+
+
+ private fun delay(delay: Long, func: () -> Unit) {
+ val handler = Handler()
+ handler.postDelayed({
+ try {
+ func()
+ } catch (e: Exception) {
+ Log.d("Twinkle error", e.localizedMessage)
+ }
+ }, delay)
+ }
+}
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..c3903ed
--- /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..5713f34
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_twinkle.xml b/app/src/main/res/layout/activity_twinkle.xml
new file mode 100644
index 0000000..93ffa84
--- /dev/null
+++ b/app/src/main/res/layout/activity_twinkle.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
\ 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..bbd3e02
--- /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..bbd3e02
--- /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..61cc9a4
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ twinklelibrary
+
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/build.gradle b/build.gradle
new file mode 100644
index 0000000..6b25030
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,32 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ ext.kotlin_version = '1.2.51'
+ ext.dokka_version = '0.9.15'
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.1.3'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+
+ classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
+ classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
+ classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:${dokka_version}"
+
+ // 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
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..7a3265e
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..428eeeb
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jul 20 14:54:08 EEST 2018
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..47e590f
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+include ':app', ':twinkle'
diff --git a/twinkle/.gitignore b/twinkle/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/twinkle/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/twinkle/build.gradle b/twinkle/build.gradle
new file mode 100644
index 0000000..8d54c7b
--- /dev/null
+++ b/twinkle/build.gradle
@@ -0,0 +1,48 @@
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+apply plugin: 'com.jfrog.bintray'
+apply plugin: 'org.jetbrains.dokka-android'
+apply plugin: 'maven-publish'
+
+android {
+ compileSdkVersion 27
+
+
+
+ defaultConfig {
+ minSdkVersion 19
+ 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'
+ }
+ }
+
+}
+
+dokka {
+ outputFormat = 'html'
+ outputDirectory = "$buildDir/javadoc"
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+ implementation 'com.android.support:appcompat-v7:27.1.1'
+ 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'
+ compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
+repositories {
+ mavenCentral()
+}
+apply from: 'deploy.gradle'
\ No newline at end of file
diff --git a/twinkle/deploy.gradle b/twinkle/deploy.gradle
new file mode 100644
index 0000000..07874df
--- /dev/null
+++ b/twinkle/deploy.gradle
@@ -0,0 +1,79 @@
+apply plugin: 'com.github.dcendents.android-maven'
+apply plugin: 'com.jfrog.bintray'
+apply from: 'keystore.gradle'//the file, containing the bintray API key
+ext {
+ // This configuration will result in:
+ // compile '::'
+ groupId = 'bg.devlabs.twinkle' // package name of the project
+ artifactId = "twinkle" // module name of the library
+ libVersion = "1.0"
+}
+version = libVersion
+group = groupId
+//take a look at https://github.com/bintray/gradle-bintray-plugin#buildgradle
+bintray {
+ user = 'radoslav' // Your bintray User
+ key = bintray_key // Defined in keystore.gradle file
+ configurations = ['archives']
+ publish = true //[Default: false] Whether version should be auto published after an upload
+ override = false //[Default: false] Whether to override version artifacts already published
+ // Package configuration. The plugin will use the repo and name properties to check if the
+ // package already exists. In that case, there's no need to configure the other package
+ // properties (like userOrg, desc, etc).
+ pkg {
+ repo = "maven" //bintray repo
+ name = "twinkle" //bintray package
+ version {
+ name = libVersion
+ }
+ }
+}
+install {
+ repositories.mavenInstaller {
+ pom.project {
+ packaging 'aar'
+ groupId groupId
+ artifactId artifactId
+ version libVersion
+ name artifactId // pom.project.name must be same as bintray.pkg.name
+ }
+ }
+}
+
+//just copy paste the lines below
+if (project.hasProperty("kotlin")) { //Kotlin libraries
+ task sourcesJar(type: Jar) {
+ classifier = 'sources'
+ from android.sourceSets.main.java.srcDirs
+ }
+
+ task javadoc(type: Javadoc, dependsOn: dokka) {
+
+ }
+} else if (project.hasProperty("android")) {
+ task sourcesJar(type: Jar) {
+ classifier = 'sources'
+ from android.sourceSets.main.java.srcDirs
+ }
+
+ task javadoc(type: Javadoc) {
+ source = android.sourceSets.main.java.srcDirs
+ classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
+ }
+} else { // Java libraries
+ task sourcesJar(type: Jar, dependsOn: classes) {
+ classifier = 'sources'
+ from sourceSets.main.allSource
+ }
+}
+
+task javadocJar(type: Jar, dependsOn: javadoc) {
+ classifier = 'javadoc'
+ from javadoc.destinationDir
+ // options.encoding = 'UTF-8'
+}
+
+artifacts {
+ archives javadocJar
+ archives sourcesJar
+}
\ No newline at end of file
diff --git a/twinkle/keystore.gradle b/twinkle/keystore.gradle
new file mode 100644
index 0000000..dab7831
--- /dev/null
+++ b/twinkle/keystore.gradle
@@ -0,0 +1,3 @@
+ext{
+ bintray_key = '-'
+}
\ No newline at end of file
diff --git a/twinkle/proguard-rules.pro b/twinkle/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/twinkle/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/twinkle/src/main/AndroidManifest.xml b/twinkle/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..b692265
--- /dev/null
+++ b/twinkle/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
diff --git a/twinkle/src/main/java/bg/devlabs/twinkle/Twinkle.kt b/twinkle/src/main/java/bg/devlabs/twinkle/Twinkle.kt
new file mode 100644
index 0000000..be13f87
--- /dev/null
+++ b/twinkle/src/main/java/bg/devlabs/twinkle/Twinkle.kt
@@ -0,0 +1,124 @@
+package bg.devlabs.twinkle
+
+import android.app.Activity
+import android.os.Handler
+import android.util.Log
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import java.util.*
+
+/**
+ * Created by Radoslav Yankov on 20.07.2018
+ * Dev Labs
+ * radoslavyankov@gmail.com
+ */
+
+/**
+ * @param drawableRes The drawable resource for the twinkle effect. Star by default
+ * @param duration The duration of each particle animation. 600ms by default
+ * @param sparsity The period between particle generation. Larger number -> less particles.
+ * @param size The size of each particle in pixels. 80 pixels by default
+ */
+fun View.twinkle(drawableRes: Int = R.drawable.twinkle, duration: Int = 600, sparsity: Int = 120, size: Int = 80): Twinkle {
+ return Twinkle(this, drawableRes, duration, sparsity, size)
+}
+
+/**
+ * Main Twinkle class
+ */
+class Twinkle(var view: View, var drawableRes: Int, var duration: Int, private var sparsity: Int, var size: Int) {
+ private var isRunning = true
+
+ init {
+ start()
+ }
+
+ fun start() {
+ isRunning = true
+ val rInt = Random()
+ loop(rInt.nextInt(sparsity * 2) + (sparsity / 2L)) {
+ //creating the ImageView. Not the most optimal way of showing graphics, but it's easy
+ var image: ImageView? = ImageView(view.context)
+ image?.apply {
+ layoutParams = ViewGroup.LayoutParams(size, size)
+ setBackgroundResource(drawableRes)
+ try {
+ x = (rInt.nextInt((view.width / 1.1).toInt()) + view.x + view.width * 0.1f) - (layoutParams.width / 2)
+ y = (rInt.nextInt((view.height / 1.1).toInt()) + view.y + view.height * 0.1f) - (layoutParams.height / 2)
+ } catch (e: Exception) {
+ return@apply
+ }
+ (view.context as? Activity)?.window?.decorView?.findViewById(android.R.id.content)?.addView(this)
+ alpha = 0f
+ scaleX = 0.7f
+ scaleY = 0.7f
+ animate().alpha(0.5f).duration = duration / 3L
+ animate().scaleX(1f).duration = duration / 3L
+ animate().scaleY(1f).duration = duration / 3L
+ loop(150) {
+ // alpha = 0.5f
+ animate().alpha(0.5f).duration = 70
+ delay(80) {
+ animate().alpha(0.4f).duration = 30
+// alpha = 0.4f
+ }
+ }
+ //animation
+ delay(duration / 3L) {
+ animate().rotation(-10f).duration = duration / 6L
+ delay(duration / 6L) {
+ animate().rotation(10f).duration = duration / 6L * 2
+ delay(duration / 6L * 2) {
+ animate().rotation(0f).duration = duration / 6L
+ }
+ }
+ delay(duration / 3L) {
+ animate().alpha(0f).duration = duration / 3L
+ animate().scaleX(0.7f).duration = duration / 3L
+ animate().scaleY(0.7f).duration = duration / 3L
+ }
+ }
+ }
+ delay(duration.toLong()) {
+ (view.context as? Activity)?.window?.decorView?.findViewById(android.R.id.content)?.removeView(image)
+ image = null
+ }
+ }
+ }
+
+
+ fun stop(){
+ isRunning = false
+ }
+
+ private fun loop(delay: Long, f: () -> Unit) {
+ f()
+ var handler: Handler? = Handler()
+ val runnable = object : Runnable {
+ override fun run() {
+ if (!isRunning){
+ handler = null
+ return
+ }
+ try {
+ f()
+ } catch (e: Exception) {
+ Log.d("Twinkle error", e.localizedMessage)
+ }; handler?.postDelayed(this, delay)
+ }
+ }; handler?.postDelayed(runnable, delay)
+ }
+
+ private fun delay(delay: Long, func: () -> Unit) {
+ val handler = Handler()
+ handler.postDelayed({
+ try {
+ func()
+ } catch (e: Exception) {
+ Log.d("Twinkle error", e.localizedMessage)
+ }
+ }, delay)
+ }
+
+}
\ No newline at end of file
diff --git a/twinkle/src/main/res/drawable/twinkle.png b/twinkle/src/main/res/drawable/twinkle.png
new file mode 100644
index 0000000..883157c
Binary files /dev/null and b/twinkle/src/main/res/drawable/twinkle.png differ
diff --git a/twinkle/src/main/res/values/strings.xml b/twinkle/src/main/res/values/strings.xml
new file mode 100644
index 0000000..d1d4c5d
--- /dev/null
+++ b/twinkle/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ twinkle
+