├── .gitignore
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── sofakingforever
│ │ └── animatedstarsview
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── sofakingforever
│ │ │ └── animatedstarsview
│ │ │ └── MainActivity.kt
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── gradient_night_sky.xml
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── arrays.xml
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── sofakingforever
│ └── animatedstarsview
│ └── ExampleUnitTest.kt
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshot.png
├── settings.gradle
└── stars
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
├── androidTest
└── java
│ └── com
│ └── sofakingforever
│ └── stars
│ └── ExampleInstrumentedTest.java
├── main
├── AndroidManifest.xml
├── java
│ └── com
│ │ └── sofakingforever
│ │ └── stars
│ │ ├── AnimatedStarsView.kt
│ │ └── entities
│ │ ├── InterstellarFactory.kt
│ │ ├── Star.kt
│ │ ├── StarConstraints.kt
│ │ ├── meteor
│ │ └── Meteorite.kt
│ │ └── stars
│ │ ├── BaseStar.kt
│ │ ├── RoundyStar.kt
│ │ ├── ShinyStar.kt
│ │ └── TinyStar.kt
└── res
│ └── values
│ ├── attrs_stars.xml
│ └── strings.xml
└── test
└── java
└── com
└── sofakingforever
└── stars
└── ExampleUnitTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Gradle files
16 | .gradle/
17 | build/
18 |
19 | # Local configuration file (sdk path, etc)
20 | local.properties
21 |
22 | # Proguard folder generated by Eclipse
23 | proguard/
24 |
25 | # Log Files
26 | *.log
27 |
28 | # Android Studio Navigation editor temp files
29 | .navigation/
30 |
31 | # Android Studio captures folder
32 | captures/
33 |
34 | \.idea/
35 |
36 | *.iml
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | []( https://android-arsenal.com/details/1/7202 )
2 |
3 | # AnimatedStarsView for Android
4 |
5 | Kotlin Android view that draws animated stars on a canvas
6 |
7 |
8 | ### Preview (Click for video)
9 | [](http://www.youtube.com/watch?v=mpwT7fZcn10)
10 |
11 |
12 | ## Quick Start Guide
13 |
14 | ### Step 1
15 | Add library to your gradle module
16 |
17 | ```gradle
18 | repositories {
19 | maven { url "http://dl.bintray.com/sofakingforever/libraries" }
20 | }
21 |
22 | dependencies {
23 | implementation 'com.sofakingforever.libraries:animated-stars-android:1.1.4@aar'
24 |
25 | // Don't forget to add kotlin if you're in a pure-java project (thanks to moisoni97)
26 | implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.2.71
27 | }
28 | ```
29 |
30 | ### Step 2
31 | Insert View via XML (or code)
32 |
33 | ```xml
34 |
35 |
47 | ```
48 |
49 | ### Step 3
50 | Add the color array
51 | ```xml
52 |
53 |
54 | - @color/star_color_1
55 | - @color/star_color_1
56 | - @color/star_color_1
57 | - @color/star_color_1
58 | - @color/star_color_2
59 | - @color/star_color_3
60 |
61 |
62 |
63 |
64 |
65 | - @color/star_color_2
66 | - @color/star_color_4
67 | - @color/star_color_3
68 |
69 |
70 | ```
71 |
72 | ### Step 4
73 | Kotlin Implementation Example - Call `onStart` and `onStop`
74 | ```kotlin
75 |
76 | override fun onStart() {
77 | super.onStart()
78 | stars.onStart()
79 | }
80 |
81 | override fun onStop() {
82 | stars.onStop()
83 | super.onStop()
84 | }
85 | ```
86 | ### DONE!
87 |
88 | ### Originally developed for [Wakey - Beautiful Alarm Clock](https://wakey.app/?ref=github)
89 |
90 | Wakey is a simple & beautiful animated alarm clock, featuring a spectacular design and an immersive experience - guaranteed to wake you up with a smile everyday!
91 |
92 | With our smiling sunrise, and grumpy lunar animations, this is the most unique alarm clock in our solar system.
93 |
94 | 
95 |
96 | License
97 | -------
98 |
99 | Licensed under the Apache License, Version 2.0 (the "License");
100 | you may not use this file except in compliance with the License.
101 | You may obtain a copy of the License at
102 |
103 | http://www.apache.org/licenses/LICENSE-2.0
104 |
105 | Unless required by applicable law or agreed to in writing, software
106 | distributed under the License is distributed on an "AS IS" BASIS,
107 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
108 | See the License for the specific language governing permissions and
109 | limitations under the License.
110 |
111 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | apply plugin: 'kotlin-android'
4 |
5 | apply plugin: 'kotlin-android-extensions'
6 |
7 | android {
8 | compileSdkVersion 28
9 | defaultConfig {
10 | applicationId "com.sofakingforever.animatedstarsview"
11 | minSdkVersion 21
12 | targetSdkVersion 28
13 | versionCode 1
14 | versionName "1.0"
15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | implementation fileTree(include: ['*.jar'], dir: 'libs')
27 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
28 | implementation 'com.android.support:appcompat-v7:28.0.0'
29 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
30 | testImplementation 'junit:junit:4.12'
31 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
32 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
33 | implementation project(':stars')
34 | }
35 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/sofakingforever/animatedstarsview/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.sofakingforever.animatedstarsview
2 |
3 | import android.support.test.InstrumentationRegistry
4 | import android.support.test.runner.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getTargetContext()
22 | assertEquals("com.sofakingforever.animatedstarsview", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/sofakingforever/animatedstarsview/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.sofakingforever.animatedstarsview
2 |
3 | import android.support.v7.app.AppCompatActivity
4 | import android.os.Bundle
5 | import kotlinx.android.synthetic.main.activity_main.*
6 |
7 | class MainActivity : AppCompatActivity() {
8 |
9 | override fun onCreate(savedInstanceState: Bundle?) {
10 | super.onCreate(savedInstanceState)
11 | setContentView(R.layout.activity_main)
12 |
13 |
14 | }
15 |
16 | override fun onStart() {
17 | super.onStart()
18 |
19 | stars_white.onStart()
20 | stars.onStart()
21 | }
22 |
23 | override fun onStop() {
24 |
25 | stars_white.onStop()
26 | stars.onStop()
27 |
28 | super.onStop()
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gradient_night_sky.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
22 |
23 |
24 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sofakingforever/animated-stars-android/d85bf1fd8b2e0b5f2384fc1b94e83f97752ff9d4/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sofakingforever/animated-stars-android/d85bf1fd8b2e0b5f2384fc1b94e83f97752ff9d4/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sofakingforever/animated-stars-android/d85bf1fd8b2e0b5f2384fc1b94e83f97752ff9d4/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sofakingforever/animated-stars-android/d85bf1fd8b2e0b5f2384fc1b94e83f97752ff9d4/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sofakingforever/animated-stars-android/d85bf1fd8b2e0b5f2384fc1b94e83f97752ff9d4/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sofakingforever/animated-stars-android/d85bf1fd8b2e0b5f2384fc1b94e83f97752ff9d4/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sofakingforever/animated-stars-android/d85bf1fd8b2e0b5f2384fc1b94e83f97752ff9d4/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sofakingforever/animated-stars-android/d85bf1fd8b2e0b5f2384fc1b94e83f97752ff9d4/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sofakingforever/animated-stars-android/d85bf1fd8b2e0b5f2384fc1b94e83f97752ff9d4/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sofakingforever/animated-stars-android/d85bf1fd8b2e0b5f2384fc1b94e83f97752ff9d4/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | - @color/star_color_1
10 | - @color/star_color_1
11 | - @color/star_color_1
12 | - @color/star_color_1
13 | - @color/star_color_2
14 | - @color/star_color_3
15 |
16 |
17 |
18 |
19 |
20 |
21 | - @color/star_color_2
22 | - @color/star_color_4
23 | - @color/star_color_3
24 |
25 |
26 |
27 | - @color/star_color_1
28 | - @color/star_color_2
29 | - @color/star_color_1
30 | - @color/star_color_1
31 | - @color/star_color_1
32 | - @color/star_color_3
33 | - @color/star_color_1
34 | - @color/star_color_1
35 | - @color/star_color_4
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
8 |
9 | #ffffff
10 | #25ADFF
11 | #FFC100
12 | #FF3800
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Animated Stars Example
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/test/java/com/sofakingforever/animatedstarsview/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.sofakingforever.animatedstarsview
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.3.10'
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.2.1'
11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
12 |
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | jcenter()
22 | }
23 | }
24 |
25 | task clean(type: Delete) {
26 | delete rootProject.buildDir
27 | }
28 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sofakingforever/animated-stars-android/d85bf1fd8b2e0b5f2384fc1b94e83f97752ff9d4/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Oct 14 03:02:00 IDT 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sofakingforever/animated-stars-android/d85bf1fd8b2e0b5f2384fc1b94e83f97752ff9d4/screenshot.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':stars'
2 |
--------------------------------------------------------------------------------
/stars/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/stars/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'com.github.dcendents.android-maven'
4 | apply plugin: 'com.jfrog.bintray'
5 |
6 | buildscript {
7 | repositories {
8 | jcenter()
9 | }
10 | dependencies {
11 |
12 |
13 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
14 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
15 |
16 | }
17 | }
18 |
19 | def versionNameStr = "1.1.4"
20 |
21 | android {
22 | compileSdkVersion 28
23 |
24 |
25 |
26 | defaultConfig {
27 | minSdkVersion 21
28 | targetSdkVersion 28
29 | versionCode 113
30 | versionName versionNameStr
31 |
32 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
33 |
34 | }
35 |
36 | buildTypes {
37 | release {
38 | minifyEnabled false
39 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
40 | }
41 | }
42 |
43 | }
44 |
45 | dependencies {
46 | implementation fileTree(dir: 'libs', include: ['*.jar'])
47 |
48 | implementation 'com.android.support:appcompat-v7:28.0.0'
49 | testImplementation 'junit:junit:4.12'
50 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
51 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
52 | compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
53 | }
54 | repositories {
55 | mavenCentral()
56 | }
57 |
58 | ext {
59 | bintrayRepo = 'libraries'
60 | bintrayName = 'animated-stars-android'
61 |
62 | publishedGroupId = 'com.sofakingforever.libraries'
63 | artifact = 'animated-stars-android'
64 | libraryName = 'stars'
65 | libraryVersion = versionNameStr
66 |
67 | libraryDescription = 'This is a SOLID Kotlin Analytics Interface for Android.'
68 |
69 | siteUrl = 'https://github.com/sofakingforever/animated-stars-android'
70 | gitUrl = 'https://github.com/sofakingforever/animated-stars-android.git'
71 |
72 |
73 | developerId = 'sofakingforever'
74 | developerName = 'sofakingforever'
75 | developerEmail = 'sofakingforever@gmail.com'
76 |
77 | licenseName = 'The Apache Software License, Version 2.0'
78 | licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
79 | allLicenses = ["Apache-2.0"]
80 | }
81 | group = publishedGroupId
82 | version = libraryVersion
83 |
84 | install {
85 | repositories.mavenInstaller {
86 | pom.project {
87 | packaging 'aar'
88 | groupId publishedGroupId
89 | artifactId artifact
90 |
91 | name libraryName
92 | description libraryDescription
93 | url siteUrl
94 |
95 | licenses {
96 | license {
97 | name licenseName
98 | url licenseUrl
99 | }
100 | }
101 | developers {
102 | developer {
103 | id developerId
104 | name developerName
105 | email developerEmail
106 | }
107 | }
108 | scm {
109 | connection gitUrl
110 | developerConnection gitUrl
111 | url siteUrl
112 | }
113 | }
114 | }
115 | }
116 |
117 | // Todo - Re-enable Javadocs and understand why it's causing trouble when compiling
118 | tasks.withType(Javadoc).all {
119 | enabled = false
120 | }
121 | task sourcesJar(type: Jar) {
122 | classifier = 'sources'
123 | from android.sourceSets.main.java.srcDirs
124 | }
125 |
126 | task javadoc(type: Javadoc) {
127 | source = android.sourceSets.main.java.srcDirs
128 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
129 | }
130 |
131 | task javadocJar(type: Jar, dependsOn: javadoc) {
132 | classifier = 'javadoc'
133 | from javadoc.destinationDir
134 | }
135 |
136 | artifacts {
137 | archives javadocJar
138 | archives sourcesJar
139 | }
140 |
141 | Properties properties = new Properties()
142 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
143 |
144 | bintray {
145 | user = properties.getProperty("bintray.user")
146 | key = properties.getProperty("bintray.apikey")
147 |
148 | configurations = ['archives']
149 | pkg {
150 | repo = bintrayRepo
151 | name = bintrayName
152 | desc = libraryDescription
153 | websiteUrl = siteUrl
154 | vcsUrl = gitUrl
155 | licenses = allLicenses
156 | dryRun = false
157 | publish = true
158 | override = false
159 | publicDownloadNumbers = true
160 | version {
161 | desc = libraryDescription
162 | }
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/stars/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/stars/src/androidTest/java/com/sofakingforever/stars/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.sofakingforever.stars;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.sofakingforever.stars.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/stars/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/stars/src/main/java/com/sofakingforever/stars/AnimatedStarsView.kt:
--------------------------------------------------------------------------------
1 | package com.sofakingforever.stars
2 |
3 | import android.content.Context
4 | import android.graphics.Canvas
5 | import android.util.AttributeSet
6 | import android.view.View
7 | import com.sofakingforever.stars.entities.InterstellarFactory
8 | import com.sofakingforever.stars.entities.Star
9 | import com.sofakingforever.stars.entities.StarConstraints
10 | import com.sofakingforever.stars.entities.stars.BaseStar
11 | import com.sofakingforever.stars.entities.meteor.Meteorite
12 | import java.util.*
13 | import java.util.concurrent.Executors
14 | import kotlin.concurrent.timerTask
15 |
16 |
17 | /**
18 | * Kotlin Android view that draws animated stars on a canvas
19 | *
20 | * Used in Wakey - Cute & Gentle Alarm Clock for Android: http://bit.ly/2uI8pgL
21 | * Check out the article on Medium: http://bit.ly/2NlFJBW
22 | * Or see what it looks like on YouTube: https://www.youtube.com/watch?v=v1-228CkoQc
23 | *
24 | * Crafted with ❤️ by sofakingforever
25 | */
26 | class AnimatedStarsView
27 | @kotlin.jvm.JvmOverloads
28 | constructor(
29 | context: Context,
30 | attrs: AttributeSet? = null,
31 | defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {
32 |
33 | private val fps: Long = 1000 / 60
34 | private val defaultStarCount: Int = 25
35 | private val threadExecutor = Executors.newSingleThreadExecutor()
36 |
37 | private var starCount: Int
38 | private var starColors: IntArray
39 | private var meteoritesColors: IntArray
40 | private var bigStarThreshold: Int
41 | private var minStarSize: Int
42 | private var maxStarSize: Int
43 |
44 | private var starsCalculatedFlag: Boolean = false
45 | private var viewWidth: Int = 0
46 | private var viewHeight: Int = 0
47 | private var starConstraints: StarConstraints
48 |
49 | private var stars: MutableList = mutableListOf()
50 | private var meteorite: Meteorite? = null
51 |
52 | private lateinit var starsIterator: MutableIterator
53 | private lateinit var timer: Timer
54 | private lateinit var task: TimerTask
55 |
56 | private val random: Random = Random()
57 | private var initiated: Boolean = false
58 | private var started: Boolean = false
59 |
60 | private lateinit var meteoriteListener: Meteorite.MeteoriteCompleteListener
61 | private var meteoritesEnabled: Boolean
62 | private var meteoritesInterval: Int
63 |
64 | private var calculateRunnable: Runnable? = null
65 |
66 | /**
67 | * init view's attributes
68 | */
69 | init {
70 |
71 | val array = context.obtainStyledAttributes(attrs, R.styleable.AnimatedStarsView, defStyleAttr, 0)
72 |
73 | starColors = intArrayOf()
74 | starCount = array.getInt(R.styleable.AnimatedStarsView_starsView_starCount, defaultStarCount)
75 | minStarSize = array.getDimensionPixelSize(R.styleable.AnimatedStarsView_starsView_minStarSize, 4)
76 | maxStarSize = array.getDimensionPixelSize(R.styleable.AnimatedStarsView_starsView_maxStarSize, 24)
77 | bigStarThreshold = array.getDimensionPixelSize(R.styleable.AnimatedStarsView_starsView_bigStarThreshold, Integer.MAX_VALUE)
78 | starConstraints = StarConstraints(minStarSize, maxStarSize, bigStarThreshold)
79 |
80 | meteoritesColors = intArrayOf()
81 | meteoritesEnabled = array.getBoolean(R.styleable.AnimatedStarsView_starsView_meteoritesEnabled, false)
82 | meteoritesInterval = array.getInt(R.styleable.AnimatedStarsView_starsView_meteoritesInterval, 5000)
83 |
84 | val starColorsArrayId = array.getResourceId(R.styleable.AnimatedStarsView_starsView_starColors, 0)
85 | val meteoritesColorsArrayId = array.getResourceId(R.styleable.AnimatedStarsView_starsView_meteoritesColors, 0)
86 |
87 | if (starColorsArrayId != 0) {
88 | starColors = context.resources.getIntArray(starColorsArrayId)
89 | }
90 |
91 | if (meteoritesColorsArrayId != 0) {
92 | meteoritesColors = context.resources.getIntArray(meteoritesColorsArrayId)
93 |
94 | }
95 |
96 | array.recycle()
97 |
98 | }
99 |
100 |
101 | /**
102 | * Must call this in Activity's onStart
103 | */
104 | fun onStart() {
105 |
106 | if (!started) {
107 | timer = Timer()
108 | task = timerTask {
109 | invalidateStars()
110 | }
111 |
112 | timer.scheduleAtFixedRate(task, 0, fps)
113 |
114 | started = true
115 | }
116 | }
117 |
118 |
119 | /**
120 | * Must call this in Activity's onStop
121 | */
122 | fun onStop() {
123 |
124 | if (started) {
125 | task.cancel()
126 | timer.cancel()
127 |
128 | started = false
129 |
130 | }
131 | }
132 |
133 | /**
134 | * get view's size and init stars every time the size of the view has changed
135 | */
136 | override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
137 | super.onSizeChanged(w, h, oldw, oldh)
138 | viewWidth = w
139 | viewHeight = h
140 |
141 | if (viewWidth > 0 && viewHeight > 0) {
142 | if (!initiated || stars.isEmpty()) {
143 | initStars()
144 | }
145 | }
146 | }
147 |
148 |
149 | /**
150 | * Draw stars on view's canvas
151 | */
152 | override fun onDraw(canvas: Canvas?) {
153 |
154 | if (!initiated && !started) return
155 |
156 | // create a variable canvas object
157 | var newCanvas = canvas
158 |
159 |
160 | synchronized(stars) {
161 | if (stars.isNotEmpty()) {
162 | // onDraw each star on the canvas
163 | starsIterator = stars.iterator()
164 | starsIterator.forEach { newCanvas = it.onDraw(newCanvas) }
165 |
166 | newCanvas = meteorite?.onDraw(newCanvas)
167 |
168 | // reset flag
169 | starsCalculatedFlag = false
170 | }
171 | }
172 | // finish drawing view
173 | super.onDraw(newCanvas)
174 |
175 | }
176 |
177 |
178 | /**
179 | * create x stars with a random point location and alphaDouble
180 | */
181 | private fun initStars() {
182 |
183 | if (!started) return
184 | // val generateColor = { starColors[random.nextInt(starColors.size)] }
185 |
186 | meteoriteListener = object : Meteorite.MeteoriteCompleteListener {
187 | override fun onMeteoriteComplete() {
188 | if (meteoritesEnabled) {
189 | postDelayed({
190 |
191 | meteorite = Meteorite(
192 | smallestWidth = Math.min(viewWidth, viewHeight),
193 | x = viewWidth,
194 | y = Math.round(Math.random() * (viewHeight * 2 / 3)).toInt(),
195 | color = meteoritesColors[random.nextInt(meteoritesColors.size)],
196 | starSize = starConstraints.getRandomStarSize().toInt(),
197 | listener = meteoriteListener
198 | )
199 |
200 | }, meteoritesInterval.toLong())
201 | }
202 | }
203 |
204 | }
205 |
206 | synchronized(stars) {
207 | stars = MutableList(starCount) {
208 |
209 | val starCompleteListener = object : BaseStar.StarCompleteListener {
210 | override fun onStarAnimationComplete() {
211 | stars[it] = createStar(it, this)
212 | }
213 |
214 | }
215 | createStar(it, starCompleteListener)
216 |
217 | }
218 | }
219 |
220 | meteoriteListener.onMeteoriteComplete()
221 |
222 | // so we know lateinit var was initiated
223 | initiated = true
224 |
225 | }
226 |
227 | private fun createStar(it: Int, starCompleteListener: BaseStar.StarCompleteListener): Star {
228 | return InterstellarFactory.create(starConstraints = starConstraints,
229 | x = Math.round(Math.random() * viewWidth).toInt(),
230 | y = Math.round(Math.random() * viewHeight).toInt(),
231 | color = starColors[it % starColors.size],
232 | listener = starCompleteListener)
233 | }
234 |
235 |
236 | /**
237 | * calculate and invalidate all stars for the next frame
238 | */
239 | private fun invalidateStars() {
240 |
241 | // not initiated
242 | if (!initiated) return
243 |
244 | // not finised drawing
245 | if (starsCalculatedFlag) return
246 |
247 | if (calculateRunnable == null) {
248 | calculateRunnable = Runnable {
249 |
250 | synchronized(stars) {
251 | // recalculate stars position and alphaInt on a background thread
252 | starsIterator = stars.iterator()
253 | starsIterator.forEach { it.calculateFrame() }
254 | }
255 | meteorite?.calculateFrame(viewWidth, viewHeight)
256 | starsCalculatedFlag = true
257 |
258 | // then post to ui thread
259 | postInvalidate()
260 | }
261 | }
262 |
263 |
264 | // new background thread
265 | threadExecutor.execute(calculateRunnable)
266 |
267 | }
268 | }
269 |
270 |
271 |
--------------------------------------------------------------------------------
/stars/src/main/java/com/sofakingforever/stars/entities/InterstellarFactory.kt:
--------------------------------------------------------------------------------
1 | package com.sofakingforever.stars.entities
2 |
3 | import com.sofakingforever.stars.entities.stars.BaseStar
4 | import com.sofakingforever.stars.entities.stars.RoundyStar
5 | import com.sofakingforever.stars.entities.stars.ShinyStar
6 | import com.sofakingforever.stars.entities.stars.TinyStar
7 |
8 | object InterstellarFactory {
9 |
10 | fun create(starConstraints: StarConstraints, x: Int, y: Int, color: Int, listener: BaseStar.StarCompleteListener): Star {
11 | val starSize = starConstraints.getRandomStarSize()
12 |
13 | return if (starSize >= starConstraints.bigStarThreshold) {
14 |
15 | // big star ones randomly be Shiny or Round
16 | if (Math.random() < 0.7) {
17 | ShinyStar(starConstraints, x, y, color, listener)
18 | } else {
19 | RoundyStar(starConstraints, x, y, color, listener)
20 | }
21 | } else {
22 | // others will ne tiny
23 | TinyStar(starConstraints, x, y, color, listener)
24 | }
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/stars/src/main/java/com/sofakingforever/stars/entities/Star.kt:
--------------------------------------------------------------------------------
1 | package com.sofakingforever.stars.entities
2 |
3 | import android.graphics.Canvas
4 |
5 | interface Star {
6 |
7 | var x: Int
8 | var y: Int
9 | val color: Int
10 |
11 | var alphaDouble: Double
12 |
13 | var multiplierFactor: Int
14 | var incrementFactor: Double
15 | val starSize : Double
16 |
17 |
18 |
19 | fun onDraw(canvas: Canvas?): Canvas?
20 |
21 | fun calculateFrame()
22 |
23 | }
--------------------------------------------------------------------------------
/stars/src/main/java/com/sofakingforever/stars/entities/StarConstraints.kt:
--------------------------------------------------------------------------------
1 | package com.sofakingforever.stars.entities
2 |
3 | class StarConstraints(private val minStarSize: Int, private val maxStarSize: Int, val bigStarThreshold: Int) {
4 |
5 | fun getRandomStarSize(): Double {
6 | val maxRandom = maxStarSize - minStarSize
7 | return (minStarSize + Math.random() * maxRandom)
8 | }
9 |
10 | }
--------------------------------------------------------------------------------
/stars/src/main/java/com/sofakingforever/stars/entities/meteor/Meteorite.kt:
--------------------------------------------------------------------------------
1 | package com.sofakingforever.stars.entities.meteor
2 |
3 | import android.graphics.*
4 | import android.support.v4.graphics.ColorUtils
5 |
6 |
7 | internal class Meteorite(val smallestWidth: Int, var x: Int, var y: Int, val starSize: Int, var color: Int, val listener: Meteorite.MeteoriteCompleteListener) {
8 |
9 | private fun getTrailAlpha(): Int {
10 | // val randomFactor = Math.random() * 255
11 | // return randomFactor.toInt()
12 | return 200 + (Math.random() * 55).toInt()
13 |
14 |
15 |
16 | }
17 |
18 | private val trailLength = (200 + (Math.random() * (smallestWidth / 4))).toFloat()
19 | private val trailColor: Int = ColorUtils.setAlphaComponent(color, getTrailAlpha())
20 | private var finished = false
21 | private val factor = starSize * (Math.random() * 1.9f)
22 |
23 |
24 | private val starPaint = Paint(Paint.ANTI_ALIAS_FLAG).also {
25 | it.color = color
26 | }
27 |
28 | private val trailPaint = Paint(Paint.ANTI_ALIAS_FLAG).also {
29 | it.strokeWidth =
30 | starSize.toFloat()
31 | }
32 |
33 |
34 | fun calculateFrame(viewWidth: Int, viewHeight: Int) {
35 |
36 | if (finished) {
37 | return
38 | }
39 |
40 | // go left
41 | x -= factor.toInt()
42 |
43 | // go down
44 | y += factor.toInt()
45 |
46 |
47 |
48 | trailPaint.shader = LinearGradient(
49 | x.toFloat(),
50 | y.toFloat(),
51 | x.toFloat() + trailLength,
52 | y.toFloat() - trailLength,
53 | trailColor,
54 | Color.TRANSPARENT,
55 | Shader.TileMode.CLAMP)
56 |
57 |
58 | if (x < (viewWidth * -0.5)) {
59 | listener.onMeteoriteComplete()
60 | finished = true
61 | }
62 | }
63 |
64 | fun onDraw(canvas: Canvas?): Canvas? {
65 |
66 | canvas?.drawLine(x.toFloat(), y.toFloat(), x.toFloat() + trailLength, y.toFloat() - trailLength, trailPaint)
67 | canvas?.drawCircle(x.toFloat(), y.toFloat(), starSize.toFloat() / 2f, starPaint)
68 | return canvas
69 | }
70 |
71 |
72 | interface MeteoriteCompleteListener {
73 | fun onMeteoriteComplete()
74 | }
75 | }
76 |
77 |
--------------------------------------------------------------------------------
/stars/src/main/java/com/sofakingforever/stars/entities/stars/BaseStar.kt:
--------------------------------------------------------------------------------
1 | package com.sofakingforever.stars.entities.stars
2 |
3 | import android.graphics.Paint
4 | import com.sofakingforever.stars.entities.Star
5 | import com.sofakingforever.stars.entities.StarConstraints
6 |
7 | abstract class BaseStar(
8 | starConstraints: StarConstraints,
9 | override var x: Int,
10 | override var y: Int,
11 | override var color: Int,
12 | private val listener: StarCompleteListener) : Star {
13 |
14 | val alphaInt: Int
15 | get() {
16 | return when {
17 | alphaDouble > 1.0 -> 255
18 | alphaDouble < 0.0 -> 0
19 | else -> (alphaDouble * 255.0).toInt()
20 | }
21 | }
22 |
23 | override var alphaDouble: Double = 0.0
24 | override var multiplierFactor: Int = 1
25 |
26 | override val starSize: Double = starConstraints.getRandomStarSize()
27 |
28 |
29 | internal var paint = initPaintColor()
30 |
31 |
32 | abstract fun initPaintColor(): Paint
33 |
34 | private var calculated: Boolean = false
35 |
36 | /**
37 | * calculate single frame for star (multiplierFactor, alphaDouble, and location if needed)
38 | */
39 | override fun calculateFrame() {
40 |
41 | calculated = true
42 |
43 |
44 | // calculate direction / multiplierFactor of alphaDouble
45 |
46 | if (alphaDouble > 1) {
47 | multiplierFactor *= -1
48 | }
49 |
50 | // calculate new alphaDouble for star
51 | alphaDouble += incrementFactor * multiplierFactor
52 |
53 | if (alphaDouble < 0.0) {
54 |
55 | // need to remove star and add new one
56 | listener.onStarAnimationComplete()
57 |
58 | return
59 | }
60 |
61 |
62 | }
63 |
64 |
65 | interface StarCompleteListener {
66 | fun onStarAnimationComplete()
67 | }
68 |
69 |
70 | }
--------------------------------------------------------------------------------
/stars/src/main/java/com/sofakingforever/stars/entities/stars/RoundyStar.kt:
--------------------------------------------------------------------------------
1 | package com.sofakingforever.stars.entities.stars
2 |
3 | import android.graphics.Canvas
4 | import android.graphics.Paint
5 | import com.sofakingforever.stars.entities.StarConstraints
6 |
7 | class RoundyStar(starConstraints: StarConstraints, x: Int, y: Int, color: Int, listener: StarCompleteListener) : BaseStar(starConstraints, x, y, color, listener) {
8 | override fun initPaintColor(): Paint {
9 | val paint = Paint(Paint.ANTI_ALIAS_FLAG)
10 | paint.color = color
11 | paint.style = Paint.Style.STROKE
12 | paint.strokeWidth = starSize.toFloat() / 4f
13 | return paint
14 | }
15 |
16 | override var incrementFactor: Double = Math.random() * .025
17 |
18 | override fun onDraw(canvas: Canvas?): Canvas? {
19 | paint?.also {
20 | it.alpha = alphaInt
21 | canvas?.drawCircle(x.toFloat(), y.toFloat(), starSize.toFloat() / 2f, it)
22 |
23 | }
24 | return canvas
25 | }
26 | }
--------------------------------------------------------------------------------
/stars/src/main/java/com/sofakingforever/stars/entities/stars/ShinyStar.kt:
--------------------------------------------------------------------------------
1 | package com.sofakingforever.stars.entities.stars
2 |
3 | import android.graphics.Canvas
4 | import android.graphics.Paint
5 | import android.graphics.RectF
6 | import com.sofakingforever.stars.entities.StarConstraints
7 |
8 | class ShinyStar(starConstraints: StarConstraints, x: Int, y: Int, color: Int, listener: StarCompleteListener) : BaseStar(starConstraints, x, y, color, listener) {
9 |
10 |
11 | private var hRect: RectF? = null
12 | private var vRect: RectF? = null
13 |
14 | override var incrementFactor: Double = Math.random() * .030
15 |
16 | override fun initPaintColor(): Paint {
17 | val paint = Paint(Paint.ANTI_ALIAS_FLAG)
18 | paint.color = color
19 | return paint
20 | }
21 |
22 | override fun calculateFrame() {
23 |
24 | if (hRect == null || vRect == null) {
25 |
26 |
27 | val hLeft = (x - starSize / 2).toFloat()
28 | val hRight = (x + starSize / 2).toFloat()
29 | val hTop = (y - starSize / 6).toFloat()
30 | val hBottom = (y + starSize / 6).toFloat()
31 |
32 | hRect = RectF(hLeft, hTop, hRight, hBottom)
33 |
34 |
35 | val vLeft = (x - starSize / 6).toFloat()
36 | val vRight = (x + starSize / 6).toFloat()
37 | val vTop = (y - starSize / 2).toFloat()
38 | val vBottom = (y + starSize / 2).toFloat()
39 |
40 | vRect = RectF(vLeft, vTop, vRight, vBottom)
41 | }
42 |
43 | super.calculateFrame()
44 |
45 |
46 | }
47 |
48 | override fun onDraw(canvas: Canvas?): Canvas? {
49 | paint?.also {
50 | it.alpha = alphaInt
51 |
52 | if (hRect != null && vRect != null) {
53 | canvas?.drawRoundRect(hRect, 6f, 6f, it)
54 | canvas?.drawRoundRect(vRect, 6f, 6f, it)
55 |
56 | }
57 | }
58 | return canvas
59 | }
60 | }
--------------------------------------------------------------------------------
/stars/src/main/java/com/sofakingforever/stars/entities/stars/TinyStar.kt:
--------------------------------------------------------------------------------
1 | package com.sofakingforever.stars.entities.stars
2 |
3 | import android.graphics.Canvas
4 | import android.graphics.Paint
5 | import com.sofakingforever.stars.entities.StarConstraints
6 |
7 | class TinyStar(starConstraints: StarConstraints, x: Int, y: Int, color: Int, listener: StarCompleteListener) : BaseStar(starConstraints, x, y, color, listener) {
8 | override var incrementFactor: Double = Math.random() * .045
9 |
10 | override fun initPaintColor(): Paint {
11 | val paint = Paint(Paint.ANTI_ALIAS_FLAG)
12 | paint.color = color
13 | return paint
14 | }
15 |
16 | override fun onDraw(canvas: Canvas?): Canvas? {
17 | paint?.also {
18 | it.alpha = alphaInt
19 | canvas?.drawCircle(x.toFloat(), y.toFloat(), starSize.toFloat() / 2f, it)
20 |
21 | }
22 | return canvas
23 | }
24 | }
--------------------------------------------------------------------------------
/stars/src/main/res/values/attrs_stars.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/stars/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Animated Stars View
3 |
4 |
--------------------------------------------------------------------------------
/stars/src/test/java/com/sofakingforever/stars/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.sofakingforever.stars;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------