├── .gitignore
├── LICENSE
├── README.md
├── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── library
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── dmax
│ │ └── dialog
│ │ ├── AnimatedView.java
│ │ ├── AnimatorPlayer.java
│ │ ├── HesitateInterpolator.java
│ │ ├── ProgressLayout.java
│ │ └── SpotsDialog.java
│ └── res
│ ├── drawable-v21
│ └── dmax_spots_spot.xml
│ ├── drawable
│ └── dmax_spots_spot.xml
│ ├── layout
│ └── dmax_spots_dialog.xml
│ ├── values-v21
│ └── style.xml
│ └── values
│ ├── attrs.xml
│ ├── color.xml
│ ├── dimens.xml
│ └── style.xml
├── sample
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── dmax
│ │ └── dialog
│ │ └── sample
│ │ └── MainActivity.java
│ └── res
│ ├── layout
│ └── main.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxxhdpi
│ └── ic_launcher.png
│ ├── values-v21
│ └── style.xml
│ └── values
│ ├── color.xml
│ ├── strings.xml
│ └── style.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | .gradle/
3 | .idea/
4 | *.iml
5 | local.properties
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Maxim Dybarsky
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Spots progress dialog
2 |
3 | [](https://bintray.com/d-max/spots-dialog/d-max.spots-dialog/1.1)
4 |
5 | [](https://medium.com/@dybarsky/spots-progress-dialog-490bd2c737b1)
6 |
7 | [](https://play.google.com/store/apps/details?id=dmax.dialog.sample)
8 |
9 | [](http://android-arsenal.com/details/1/1743)
10 |
11 | Android AlertDialog with moving spots progress indicator packed as android library.
12 |
13 | ![Example Image1][1]
14 |
15 | ===========
16 |
17 | ### Usage
18 |
19 | The library available in maven jcenter repository. You can get it using:
20 | ```groovy
21 | repositories {
22 | jcenter()
23 | }
24 | dependencies {
25 | implementation 'com.github.d-max:spots-dialog:1.1@aar'
26 | }
27 | ```
28 | Javadoc and sources package [classifiers][3] available too.
29 |
30 | **Note:** The library requires minimum API level 15.
31 |
32 | [SpotsDialog][4] class is an inheritor of a AlertDialog class. You can use it just like simple [AlertDialog][5]. For example:
33 | ```kotlin
34 | val dialog: AlertDialog = SpotsDialog.Builder().setContext(context).build()
35 | ...
36 | dialog.show()
37 | ...
38 | dialog.dismiss()
39 | ```
40 |
41 | ### Customization
42 |
43 | For dialog customization of dialog, like message and cancel listener, use `SpotsDialog.Builder` methods.
44 |
45 | ```kotlin
46 | val dialog: AlertDialog = SpotsDialog.Builder()
47 | .setContext(this)
48 | .setMessage(R.string.custom_title)
49 | .setCancelable(false)
50 | ...
51 | .build()
52 | .apply {
53 | show()
54 | }
55 | ...
56 | dialog.dismiss()
57 | ```
58 |
59 | For changing dialogs look and feel, create style and pass it ot dialog builder:
60 | ```kotlin
61 | val dialog: AlertDialog = SpotsDialog.Builder()
62 | .Builder()
63 | .setContext(context)
64 | .setTheme(R.style.Cusom)
65 | .build()
66 | .apply {
67 | show()
68 | }
69 | ```
70 |
71 | For styling the next custom attributes provided:
72 | * DialogTitleAppearance : style reference
73 | * DialogTitleText : string
74 | * DialogSpotColor : color
75 | * DialogSpotCount : integer
76 |
77 | **For example:**
78 |
79 | Provide you own style resource:
80 | ```xml
81 |
82 |
83 |
89 |
90 | ```
91 |
92 | Result:
93 |
94 | ![Example Image1][2]
95 |
96 |
97 | **Note:**
98 | On the pre-lollipop devices _DialogSpotColor_ item won't work. As workaround just override color in your resources.
99 | ```xml
100 |
101 |
102 | @color/your_color_value
103 |
104 | ```
105 |
106 | ### Proguard
107 |
108 | If you're using proguard, add this code to your rules file:
109 |
110 | ```
111 | -keep class dmax.dialog.** {
112 | *;
113 | }
114 | ```
115 |
116 | ===========
117 |
118 |
119 | ### Release notes
120 |
121 | **[v1.1, June 5th 2018][11]**
122 | * Builder provided
123 | * Small fixes
124 |
125 | **[v0.7, November 23th 2015][10]**
126 | * Override message setter
127 |
128 | **[v0.4, July 23th 2015][9]**
129 | * Add custom message constructor
130 |
131 | **[v0.3, May 5th 2015][8]**
132 | * Stop animation when dismiss dialog
133 |
134 | **[v0.2, Feb 10th 2015][7]**
135 | * Fix issue on pre-lollipop
136 |
137 | **[v0.1, Jan 15th 2015][6]**
138 | * Style customization
139 |
140 | ===========
141 |
142 | ### Developed By
143 |
144 | Maksym Dybarskyi - http://d-max.info
145 |
146 | ===========
147 |
148 | ### License
149 |
150 | The MIT License (MIT)
151 | Copyright © 2015 Maxim Dybarsky
152 |
153 | Permission is hereby granted, free of charge, to any person obtaining a copy
154 | of this software and associated documentation files (the “Software”), to deal
155 | in the Software without restriction, including without limitation the rights
156 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
157 | copies of the Software, and to permit persons to whom the Software is
158 | furnished to do so, subject to the following conditions:
159 |
160 | The above copyright notice and this permission notice shall be included in
161 | all copies or substantial portions of the Software.
162 |
163 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
164 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
165 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
166 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
167 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
168 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
169 | THE SOFTWARE.
170 |
171 |
172 | [1]: http://3.bp.blogspot.com/-l1UvVWiMSAg/VLa5ZfW4dDI/AAAAAAAANTc/rsWou_qb0Bc/s320/Y6HaTSw.gif
173 | [2]: http://1.bp.blogspot.com/-GVktyphQy4U/VLa5jqIF2MI/AAAAAAAANTk/SCtC58KAYHI/s320/plYat1p.gif
174 | [3]: http://www.gradle.org/docs/current/userguide/dependency_management.html#sub:classifiers
175 | [4]: library/src/main/java/dmax/dialog/SpotsDialog.java
176 | [5]: http://developer.android.com/reference/android/app/AlertDialog.html
177 | [6]: https://github.com/d-max/spots-dialog/releases/tag/v0.1
178 | [7]: https://github.com/d-max/spots-dialog/releases/tag/v0.2
179 | [8]: https://github.com/d-max/spots-dialog/releases/tag/v0.3
180 | [9]: https://github.com/d-max/spots-dialog/releases/tag/v0.4
181 | [10]: https://github.com/d-max/spots-dialog/releases/tag/v0.7
182 | [11]: https://github.com/d-max/spots-dialog/releases/tag/v1.1
183 |
184 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:3.1.2'
9 | }
10 | }
11 |
12 | ext {
13 | COMPILE_SDK_VERSION = 27
14 | MIN_SDK_VERSION = 15
15 | TARGET_SDK_VERSION = 27
16 |
17 | LIBRARY_VERSION_NAME = "1.1"
18 | LIBRARY_VERSION_CODE = 11
19 |
20 | SAMPLE_VERSION_NAME = "0.1"
21 | SAMPLE_VERSION_CODE_LOLLIPOP = 201
22 | SAMPLE_VERSION_CODE_KITKAT = 101
23 |
24 | ARTIFACT_ID = "spots-dialog"
25 | }
26 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dybarsky/spots-dialog/c5a92f988cf5991b2770d06439dc682d9f97c513/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Aug 21 21:23:56 CEST 2016
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.4-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
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 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'maven'
3 |
4 | repositories {
5 | google()
6 | jcenter()
7 | }
8 |
9 | dependencies {
10 | implementation 'com.android.support:support-annotations:27.1.1'
11 | }
12 |
13 | android {
14 | compileSdkVersion COMPILE_SDK_VERSION
15 |
16 | defaultConfig {
17 | minSdkVersion MIN_SDK_VERSION
18 | targetSdkVersion TARGET_SDK_VERSION
19 | versionCode LIBRARY_VERSION_CODE
20 | versionName LIBRARY_VERSION_NAME
21 | }
22 |
23 | compileOptions {
24 | sourceCompatibility JavaVersion.VERSION_1_8
25 | targetCompatibility JavaVersion.VERSION_1_8
26 | }
27 | }
28 |
29 | task sourcePackage(type: Jar) {
30 | baseName = ARTIFACT_ID
31 | classifier = "sources"
32 | version LIBRARY_VERSION_NAME
33 | from android.sourceSets.main.java.srcDirs
34 | destinationDir file("$buildDir/artifacts")
35 | }
36 |
37 | task generatePom {
38 | doLast {
39 | pom {
40 | project {
41 | groupId "com.github.d-max"
42 | artifactId "spots-dialog"
43 | version LIBRARY_VERSION_NAME
44 | packaging "aar"
45 | name "spots progress dialog"
46 | description "Android AlertDialog with moving spots progress indicator"
47 | url "https://github.com/d-max/spots-dialog"
48 | scm {
49 | url "https://github.com/d-max/spots-dialog"
50 | connection "scm:git@github.com:d-max/spots-dialog.git"
51 | developerConnection "scm:git@github.com:d-max/spots-dialog.git"
52 | }
53 | licenses {
54 | license {
55 | name "MIT License"
56 | url "http://www.opensource.org/licenses/mit-license.php"
57 | distribution "repo"
58 | }
59 | }
60 | developers {
61 | developer {
62 | id "d-max"
63 | name "Maksym Dybarskyi"
64 | email "maxim.dybarskyy@gmail.com"
65 | }
66 | }
67 | }
68 | }.writeTo("$buildDir/artifacts/${ARTIFACT_ID}-${LIBRARY_VERSION_NAME}.pom")
69 | }
70 | }
71 |
72 | task createArtifacts {
73 | dependsOn sourcePackage, generatePom
74 | }
75 |
76 | android.libraryVariants.all { variant ->
77 | if (variant.buildType.name == "release") {
78 | File outDir = file("$buildDir/artifacts")
79 | File apkFile = variant.outputs[0].outputFile
80 |
81 | def task = project.tasks.create("copy${variant.name.capitalize()}Aar", Copy)
82 | task.from apkFile
83 | task.into outDir
84 | task.rename apkFile.name, "${ARTIFACT_ID}-${LIBRARY_VERSION_NAME}.aar"
85 |
86 | task.dependsOn variant.assemble
87 | task.dependsOn sourcePackage
88 | createArtifacts.dependsOn task
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/library/src/main/java/dmax/dialog/AnimatedView.java:
--------------------------------------------------------------------------------
1 | package dmax.dialog;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 |
6 | /**
7 | * Created by Maxim Dybarsky | maxim.dybarskyy@gmail.com
8 | * on 13.01.15 at 14:17
9 | */
10 | class AnimatedView extends View {
11 |
12 | private int target;
13 |
14 | public AnimatedView(Context context) {
15 | super(context);
16 | }
17 |
18 | public float getXFactor() {
19 | return getX() / target;
20 | }
21 |
22 | public void setXFactor(float xFactor) {
23 | setX(target * xFactor);
24 | }
25 |
26 | public void setTarget(int target) {
27 | this.target = target;
28 | }
29 |
30 | public int getTarget() {
31 | return target;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/library/src/main/java/dmax/dialog/AnimatorPlayer.java:
--------------------------------------------------------------------------------
1 | package dmax.dialog;
2 |
3 | import android.animation.*;
4 |
5 | /**
6 | * Created by Maxim Dybarsky | maxim.dybarskyy@gmail.com
7 | * on 05.05.15 at 14:45
8 | */
9 | class AnimatorPlayer extends AnimatorListenerAdapter {
10 |
11 | private boolean interrupted = false;
12 | private Animator[] animators;
13 |
14 | AnimatorPlayer(Animator[] animators) {
15 | this.animators = animators;
16 | }
17 |
18 | @Override
19 | public void onAnimationEnd(Animator animation) {
20 | if (!interrupted) animate();
21 | }
22 |
23 | void play() {
24 | animate();
25 | }
26 |
27 | void stop() {
28 | interrupted = true;
29 | }
30 |
31 | private void animate() {
32 | AnimatorSet set = new AnimatorSet();
33 | set.playTogether(animators);
34 | set.addListener(this);
35 | set.start();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/library/src/main/java/dmax/dialog/HesitateInterpolator.java:
--------------------------------------------------------------------------------
1 | package dmax.dialog;
2 |
3 | import android.view.animation.Interpolator;
4 |
5 | /**
6 | * Created by Maxim Dybarsky | maxim.dybarskyy@gmail.com
7 | * on 13.01.15 at 14:20
8 | */
9 | class HesitateInterpolator implements Interpolator {
10 |
11 | private static double POW = 1.0/2.0;
12 |
13 | @Override
14 | public float getInterpolation(float input) {
15 | return input < 0.5
16 | ? (float) Math.pow(input * 2, POW) * 0.5f
17 | : (float) Math.pow((1 - input) * 2, POW) * -0.5f + 1;
18 | }
19 | }
--------------------------------------------------------------------------------
/library/src/main/java/dmax/dialog/ProgressLayout.java:
--------------------------------------------------------------------------------
1 | package dmax.dialog;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.content.res.TypedArray;
6 | import android.os.Build;
7 | import android.util.AttributeSet;
8 | import android.widget.FrameLayout;
9 |
10 | /**
11 | * Created by Maxim Dybarsky | maxim.dybarskyy@gmail.com
12 | * on 13.01.15 at 17:34
13 | */
14 | public class ProgressLayout extends FrameLayout {
15 |
16 | private static final int DEFAULT_COUNT = 5;
17 | private int spotsCount;
18 |
19 | public ProgressLayout(Context context) {
20 | this(context, null);
21 | }
22 |
23 | public ProgressLayout(Context context, AttributeSet attrs) {
24 | this(context, attrs, 0);
25 | }
26 |
27 | public ProgressLayout(Context context, AttributeSet attrs, int defStyleAttr) {
28 | super(context, attrs, defStyleAttr);
29 | init(attrs, defStyleAttr, 0);
30 | }
31 |
32 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
33 | public ProgressLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
34 | super(context, attrs, defStyleAttr, defStyleRes);
35 | init(attrs, defStyleAttr, defStyleRes);
36 | }
37 |
38 | private void init(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
39 | TypedArray a = getContext().getTheme().obtainStyledAttributes(
40 | attrs,
41 | R.styleable.Dialog,
42 | defStyleAttr, defStyleRes);
43 |
44 | spotsCount = a.getInt(R.styleable.Dialog_DialogSpotCount, DEFAULT_COUNT);
45 | a.recycle();
46 | }
47 |
48 | public int getSpotsCount() {
49 | return spotsCount;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/library/src/main/java/dmax/dialog/SpotsDialog.java:
--------------------------------------------------------------------------------
1 | package dmax.dialog;
2 |
3 | import android.animation.Animator;
4 | import android.animation.AnimatorListenerAdapter;
5 | import android.animation.ObjectAnimator;
6 | import android.app.AlertDialog;
7 | import android.content.Context;
8 | import android.os.Bundle;
9 | import android.support.annotation.StringRes;
10 | import android.support.annotation.StyleRes;
11 | import android.view.View;
12 | import android.widget.TextView;
13 |
14 | /**
15 | * Created by Maxim Dybarsky | maxim.dybarskyy@gmail.com
16 | * on 13.01.15 at 14:22
17 | */
18 | public class SpotsDialog extends AlertDialog {
19 |
20 | public static class Builder {
21 |
22 | private Context context;
23 | private String message;
24 | private int messageId;
25 | private int themeId;
26 | private boolean cancelable = true; // default dialog behaviour
27 | private OnCancelListener cancelListener;
28 |
29 | public Builder setContext(Context context) {
30 | this.context = context;
31 | return this;
32 | }
33 |
34 | public Builder setMessage(String message) {
35 | this.message = message;
36 | return this;
37 | }
38 |
39 | public Builder setMessage(@StringRes int messageId) {
40 | this.messageId = messageId;
41 | return this;
42 | }
43 |
44 | public Builder setTheme(@StyleRes int themeId) {
45 | this.themeId = themeId;
46 | return this;
47 | }
48 |
49 | public Builder setCancelable(boolean cancelable) {
50 | this.cancelable = cancelable;
51 | return this;
52 | }
53 |
54 | public Builder setCancelListener(OnCancelListener cancelListener) {
55 | this.cancelListener = cancelListener;
56 | return this;
57 | }
58 |
59 | public AlertDialog build() {
60 | return new SpotsDialog(
61 | context,
62 | messageId != 0 ? context.getString(messageId) : message,
63 | themeId != 0 ? themeId : R.style.SpotsDialogDefault,
64 | cancelable,
65 | cancelListener
66 | );
67 | }
68 | }
69 |
70 | private static final int DELAY = 150;
71 | private static final int DURATION = 1500;
72 |
73 | private int size;
74 | private AnimatedView[] spots;
75 | private AnimatorPlayer animator;
76 | private CharSequence message;
77 |
78 | private SpotsDialog(Context context, String message, int theme, boolean cancelable, OnCancelListener cancelListener) {
79 | super(context, theme);
80 | this.message = message;
81 |
82 | setCancelable(cancelable);
83 | if (cancelListener != null) setOnCancelListener(cancelListener);
84 | }
85 |
86 | @Override
87 | protected void onCreate(Bundle savedInstanceState) {
88 | super.onCreate(savedInstanceState);
89 |
90 | setContentView(R.layout.dmax_spots_dialog);
91 | setCanceledOnTouchOutside(false);
92 |
93 | initMessage();
94 | initProgress();
95 | }
96 |
97 | @Override
98 | protected void onStart() {
99 | super.onStart();
100 |
101 | for (AnimatedView view : spots) view.setVisibility(View.VISIBLE);
102 |
103 | animator = new AnimatorPlayer(createAnimations());
104 | animator.play();
105 | }
106 |
107 | @Override
108 | protected void onStop() {
109 | super.onStop();
110 |
111 | animator.stop();
112 | }
113 |
114 | @Override
115 | public void setMessage(CharSequence message) {
116 | this.message = message;
117 | if (isShowing()) initMessage();
118 | }
119 |
120 | //~
121 |
122 | private void initMessage() {
123 | if (message != null && message.length() > 0) {
124 | ((TextView) findViewById(R.id.dmax_spots_title)).setText(message);
125 | }
126 | }
127 |
128 | private void initProgress() {
129 | ProgressLayout progress = findViewById(R.id.dmax_spots_progress);
130 | size = progress.getSpotsCount();
131 |
132 | spots = new AnimatedView[size];
133 | int size = getContext().getResources().getDimensionPixelSize(R.dimen.spot_size);
134 | int progressWidth = getContext().getResources().getDimensionPixelSize(R.dimen.progress_width);
135 | for (int i = 0; i < spots.length; i++) {
136 | AnimatedView v = new AnimatedView(getContext());
137 | v.setBackgroundResource(R.drawable.dmax_spots_spot);
138 | v.setTarget(progressWidth);
139 | v.setXFactor(-1f);
140 | v.setVisibility(View.INVISIBLE);
141 | progress.addView(v, size, size);
142 | spots[i] = v;
143 | }
144 | }
145 |
146 | private Animator[] createAnimations() {
147 | Animator[] animators = new Animator[size];
148 | for (int i = 0; i < spots.length; i++) {
149 | final AnimatedView animatedView = spots[i];
150 | Animator move = ObjectAnimator.ofFloat(animatedView, "xFactor", 0, 1);
151 | move.setDuration(DURATION);
152 | move.setInterpolator(new HesitateInterpolator());
153 | move.setStartDelay(DELAY * i);
154 | move.addListener(new AnimatorListenerAdapter() {
155 | @Override
156 | public void onAnimationEnd(Animator animation) {
157 | animatedView.setVisibility(View.INVISIBLE);
158 | }
159 |
160 | @Override
161 | public void onAnimationStart(Animator animation) {
162 | animatedView.setVisibility(View.VISIBLE);
163 | }
164 | });
165 | animators[i] = move;
166 | }
167 | return animators;
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable-v21/dmax_spots_spot.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/dmax_spots_spot.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/dmax_spots_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
18 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/library/src/main/res/values-v21/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
--------------------------------------------------------------------------------
/library/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/library/src/main/res/values/color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | @android:color/holo_blue_dark
4 |
--------------------------------------------------------------------------------
/library/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 6dp
4 | 10dp
5 | 6dp
6 | 24dp
7 | 250dp
8 |
9 |
--------------------------------------------------------------------------------
/library/src/main/res/values/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/sample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | repositories {
4 | google()
5 | jcenter()
6 | maven {
7 | url "https://dl.bintray.com/d-max/spots-dialog"
8 | }
9 | }
10 |
11 | android {
12 | compileSdkVersion COMPILE_SDK_VERSION
13 |
14 | defaultConfig {
15 | versionName SAMPLE_VERSION_NAME
16 | targetSdkVersion 27
17 | }
18 |
19 | flavorDimensions "minApi"
20 |
21 | productFlavors {
22 | lollipop {
23 | minSdkVersion 21
24 | versionCode SAMPLE_VERSION_CODE_LOLLIPOP
25 | dimension "minApi"
26 | }
27 | kitkat {
28 | minSdkVersion 15
29 | versionCode SAMPLE_VERSION_CODE_KITKAT
30 | dimension "minApi"
31 | }
32 | }
33 |
34 | compileOptions {
35 | sourceCompatibility JavaVersion.VERSION_1_6
36 | targetCompatibility JavaVersion.VERSION_1_6
37 | }
38 |
39 | signingConfigs {
40 | release {
41 | storeFile file(System.getProperty("user.home") + "/.android/dmax.keystore")
42 | storePassword keystorePassword
43 | keyAlias "dmax"
44 | keyPassword keystorePassword
45 | }
46 | }
47 |
48 | buildTypes {
49 | release {
50 | signingConfig signingConfigs.release
51 | minifyEnabled false
52 | shrinkResources false
53 | }
54 | }
55 |
56 | lintOptions {
57 | abortOnError false
58 | xmlReport false
59 | htmlReport true
60 | checkReleaseBuilds true
61 | }
62 | }
63 |
64 | dependencies {
65 | // compile 'com.github.d-max:spots-dialog:1.0'
66 | implementation project(':library')
67 | }
68 |
--------------------------------------------------------------------------------
/sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
9 |
10 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/sample/src/main/java/dmax/dialog/sample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package dmax.dialog.sample;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.view.View;
6 |
7 | import dmax.dialog.SpotsDialog;
8 |
9 | /**
10 | * Created by Maxim Dybarsky | maxim.dybarskyy@gmail.com
11 | * on 13.01.15 at 14:32
12 | */
13 | public class MainActivity extends Activity implements View.OnClickListener {
14 |
15 | @Override
16 | public void onCreate(Bundle savedInstanceState) {
17 | super.onCreate(savedInstanceState);
18 |
19 | setContentView(R.layout.main);
20 |
21 | findViewById(android.R.id.button1).setOnClickListener(this);
22 | findViewById(android.R.id.button2).setOnClickListener(this);
23 | findViewById(android.R.id.button3).setOnClickListener(this);
24 | findViewById(android.R.id.closeButton).setOnClickListener(this);
25 | }
26 |
27 | @Override
28 | public void onClick(View v) {
29 | switch (v.getId()) {
30 | case android.R.id.button1:
31 | new SpotsDialog.Builder()
32 | .setContext(this)
33 | .build()
34 | .show();
35 | break;
36 | case android.R.id.button2:
37 | new SpotsDialog.Builder()
38 | .setContext(this)
39 | .setTheme(R.style.Custom)
40 | .build()
41 | .show();
42 | break;
43 | case android.R.id.button3:
44 | new SpotsDialog.Builder()
45 | .setContext(this)
46 | .setMessage("Custom message")
47 | .build()
48 | .show();
49 | break;
50 | case android.R.id.closeButton:
51 | new SpotsDialog.Builder()
52 | .setContext(this)
53 | .setTheme(R.style.Custom)
54 | .setMessage(R.string.app_name)
55 | .build()
56 | .show();
57 | break;
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
19 |
20 |
25 |
26 |
31 |
32 |
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dybarsky/spots-dialog/c5a92f988cf5991b2770d06439dc682d9f97c513/sample/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dybarsky/spots-dialog/c5a92f988cf5991b2770d06439dc682d9f97c513/sample/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dybarsky/spots-dialog/c5a92f988cf5991b2770d06439dc682d9f97c513/sample/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dybarsky/spots-dialog/c5a92f988cf5991b2770d06439dc682d9f97c513/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dybarsky/spots-dialog/c5a92f988cf5991b2770d06439dc682d9f97c513/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/values-v21/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | @android:color/holo_red_light
4 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Spots Dialog
4 | Updating…
5 | Show default dialog
6 | Show styled dialog
7 | Show custom message dialog
8 | Show custom message AND style dialog
9 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':library'
2 | include ':sample'
--------------------------------------------------------------------------------