() {
127 | @Override
128 | public Customization createFromParcel(Parcel source) {
129 | return new Customization(source);
130 | }
131 |
132 | @Override
133 | public Customization[] newArray(int size) {
134 | return new Customization[size];
135 | }
136 | };
137 | }
138 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/multiindicator/data/CustomizationConverter.java:
--------------------------------------------------------------------------------
1 | package com.example.multiindicator.data;
2 |
3 |
4 | import com.example.indicatorlib.views.animation.type.AnimationType;
5 | import com.example.indicatorlib.views.draw.data.Orientation;
6 | import com.example.indicatorlib.views.draw.data.RtlMode;
7 |
8 | public class CustomizationConverter {
9 |
10 | public static AnimationType getAnimationType(int position) {
11 | switch (position) {
12 | case 0:
13 | return AnimationType.NONE;
14 |
15 | case 1:
16 | return AnimationType.COLOR;
17 |
18 | case 2:
19 | return AnimationType.SCALE;
20 |
21 | case 3:
22 | return AnimationType.WORM;
23 |
24 | case 4:
25 | return AnimationType.SLIDE;
26 |
27 | case 5:
28 | return AnimationType.FILL;
29 |
30 | case 6:
31 | return AnimationType.THIN_WORM;
32 |
33 | case 7:
34 | return AnimationType.DROP;
35 |
36 | case 8:
37 | return AnimationType.SWAP;
38 |
39 | case 9:
40 | return AnimationType.SCALE_DOWN;
41 |
42 | default:
43 | return AnimationType.NONE;
44 | }
45 | }
46 |
47 | public static Orientation getOrientation(int position) {
48 | switch (position) {
49 | case 0:
50 | return Orientation.HORIZONTAL;
51 |
52 | case 1:
53 | return Orientation.VERTICAL;
54 |
55 | default:
56 | return Orientation.HORIZONTAL;
57 | }
58 | }
59 |
60 | public static RtlMode getRtlMode(int position) {
61 | switch (position) {
62 | case 0:
63 | return RtlMode.On;
64 |
65 | case 1:
66 | return RtlMode.Off;
67 |
68 | case 2:
69 | return RtlMode.Auto;
70 |
71 | default:
72 | return RtlMode.Off;
73 | }
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/multiindicator/frag/TestFragment.java:
--------------------------------------------------------------------------------
1 | package com.example.multiindicator.frag;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.NonNull;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.Fragment;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 |
11 | import com.example.multiindicator.R;
12 |
13 | /**
14 | *
15 | * author : Wp
16 | * e-mail : 1101313414@qq.com
17 | * time : 2019/5/28 4:22 PM
18 | * desc :
19 | * version: 1.0
20 | *
21 | */
22 | public class TestFragment extends Fragment {
23 |
24 | @Nullable
25 | @Override
26 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
27 | return inflater.inflate(R.layout.frag_test,null);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/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/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/drawable/selector_black_10_transparent.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_circle_red.xml:
--------------------------------------------------------------------------------
1 |
5 |
8 |
11 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/act_customize.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
12 |
13 |
17 |
18 |
24 |
25 |
32 |
33 |
38 |
39 |
40 |
44 |
45 |
49 |
50 |
56 |
57 |
64 |
65 |
70 |
71 |
72 |
76 |
77 |
83 |
84 |
91 |
92 |
97 |
98 |
99 |
100 |
104 |
105 |
114 |
115 |
119 |
120 |
129 |
130 |
134 |
135 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/act_page_indicator.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
16 |
17 |
27 |
28 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/act_tab_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
17 |
18 |
27 |
28 |
40 |
41 |
42 |
43 |
48 |
49 |
50 |
69 |
70 |
71 |
72 |
81 |
82 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/act_tab_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
20 |
21 |
29 |
30 |
43 |
44 |
45 |
46 |
52 |
53 |
54 |
59 |
60 |
68 |
69 |
81 |
82 |
83 |
84 |
85 |
86 |
95 |
96 |
97 |
98 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
19 |
20 |
29 |
30 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/frag_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_spinner_drop_down.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_spinner_selected.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_customize.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/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/pengMaster/MultiIndicator/211ae7d03d45d6291b6c9153026fc07b9ab96312/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pengMaster/MultiIndicator/211ae7d03d45d6291b6c9153026fc07b9ab96312/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pengMaster/MultiIndicator/211ae7d03d45d6291b6c9153026fc07b9ab96312/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pengMaster/MultiIndicator/211ae7d03d45d6291b6c9153026fc07b9ab96312/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pengMaster/MultiIndicator/211ae7d03d45d6291b6c9153026fc07b9ab96312/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pengMaster/MultiIndicator/211ae7d03d45d6291b6c9153026fc07b9ab96312/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pengMaster/MultiIndicator/211ae7d03d45d6291b6c9153026fc07b9ab96312/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pengMaster/MultiIndicator/211ae7d03d45d6291b6c9153026fc07b9ab96312/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pengMaster/MultiIndicator/211ae7d03d45d6291b6c9153026fc07b9ab96312/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pengMaster/MultiIndicator/211ae7d03d45d6291b6c9153026fc07b9ab96312/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | - Tab1
6 | - Tab2
7 | - Tab3
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 | #f1f2f7
7 | #FFFFFF
8 | #f4f4f4
9 | #7082a8
10 | #453d3b
11 | #e2211c
12 | #ffeeee
13 | #fd6853
14 | #eb2d4d
15 | #e2211c
16 | #fe6b55
17 | #c25c59
18 | #ff2d55
19 | #341b1c
20 | #433f3d
21 | #999999
22 | #996d13
23 |
24 | #4cd964
25 | #221815
26 | #8d8887
27 | #474747
28 | #555555
29 | #7fffffff
30 | #f1f2f7
31 | #f1f2f7
32 | #ffe8e4
33 | #f8f8f9
34 | #b2b2b2
35 | #dedddc
36 | #555555
37 | #fee94e
38 |
39 | #a3000000
40 | #19000000
41 | #99000000
42 |
43 | #aa72d572
44 | #aa738ffe
45 | #aae84e40
46 | #00000000
47 | #25808080
48 | #f5f5f5
49 | #e64340
50 |
51 | #333333
52 | #59B29C
53 | #333333
54 | #FFFFFF
55 | #00ffffff
56 |
57 | #D0382B
58 | #B4B4B4
59 | #e53732
60 |
61 | #ffcf00
62 |
63 | #E3F2FD
64 | #BBDEFB
65 | #90CAF9
66 | #64B5F6
67 | #42A5F5
68 | #2196F3
69 | #1E88E5
70 | #1976D2
71 | #1565C0
72 | #0D47A1
73 |
74 | #FAFAFA
75 | #F5F5F5
76 | #EEEEEE
77 | #E0E0E0
78 | #BDBDBD
79 | #9E9E9E
80 | #757575
81 | #616161
82 | #424242
83 | #212121
84 |
85 | #ea5a4f
86 | #6099f5
87 | #edc855
88 | #5cb171
89 |
90 | - #1A000000
91 |
92 |
93 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 9sp
6 | 10sp
7 | 11sp
8 | 12sp
9 | 13sp
10 | 14sp
11 | 15sp
12 | 16sp
13 | 17sp
14 | 18sp
15 | 19sp
16 | 20sp
17 | 22sp
18 | 30sp
19 |
20 | 1dp
21 | 2dp
22 | 3dp
23 | 4dp
24 | 5dp
25 | 6dp
26 | 7dp
27 | 8dp
28 | 9dp
29 | 10dp
30 | 11dp
31 | 12dp
32 | 13dp
33 | 14dp
34 | 15dp
35 | 16dp
36 | 19dp
37 | 20dp
38 | 25dp
39 | 30dp
40 | 35dp
41 | 36dp
42 | 40dp
43 | 45dp
44 | 49dp
45 | 50dp
46 | 52dp
47 | 55dp
48 | 60dp
49 | 64dp
50 |
51 | 16sp
52 | 14sp
53 | 13sp
54 | 3dp
55 | 5dp
56 | 7dp
57 | 9dp
58 | 18dp
59 | 24dp
60 | 40dp
61 | 44dp
62 | 50dp
63 | 16dp
64 | 8dp
65 | 10dp
66 | 12dp
67 | 13dp
68 | 14dp
69 | 15dp
70 | 16dp
71 | 17dp
72 | 18dp
73 | 20dp
74 | 25dp
75 |
76 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | MultiIndicator
3 |
4 |
5 | - None
6 | - Color
7 | - Scale
8 | - Worm
9 | - Slide
10 | - Fill
11 | - Thin Worm
12 | - Drop
13 | - Swap
14 | - Scale Down
15 |
16 |
17 |
18 | - Horizontal
19 | - Vertical
20 |
21 |
22 |
23 | - On
24 | - Off
25 | - Auto
26 |
27 |
28 | Interactive animation
29 | Auto visibility
30 | Animation type
31 | Orientation
32 | Customize
33 | Home
34 | Right to left mode
35 | Fade on idle
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
16 |
17 |
21 |
22 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/test/java/com/example/multiindicator/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.example.multiindicator;
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 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | google()
6 | jcenter()
7 |
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.3.2'
11 |
12 | // NOTE: Do not place your application dependencies here; they belong
13 | // in the individual module build.gradle files
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | google()
20 | jcenter()
21 | maven { url 'https://jitpack.io' }
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 |
15 |
16 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pengMaster/MultiIndicator/211ae7d03d45d6291b6c9153026fc07b9ab96312/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue May 28 15:33:39 CST 2019
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.10.1-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 |
--------------------------------------------------------------------------------
/indicatorlib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/indicatorlib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 28
5 |
6 |
7 |
8 | defaultConfig {
9 | minSdkVersion 15
10 | targetSdkVersion 28
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
15 |
16 | }
17 |
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 |
25 | }
26 |
27 | dependencies {
28 | implementation fileTree(dir: 'libs', include: ['*.jar'])
29 |
30 | implementation 'com.android.support:appcompat-v7:28.0.0'
31 | testImplementation 'junit:junit:4.12'
32 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
33 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
34 | }
35 |
--------------------------------------------------------------------------------
/indicatorlib/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 |
--------------------------------------------------------------------------------
/indicatorlib/src/androidTest/java/com/example/indicatorlib/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib;
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.example.indicatorlib.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/base/BaseFragmentAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.base;
2 |
3 | import android.support.v4.app.Fragment;
4 | import android.support.v4.app.FragmentManager;
5 | import android.support.v4.app.FragmentPagerAdapter;
6 |
7 | import java.util.ArrayList;
8 | import java.util.Collection;
9 | import java.util.List;
10 |
11 | /**
12 | *
13 | * author : Wp
14 | * e-mail : 18141924293@163.com
15 | * time : 2018/06/25
16 | * desc : BaseFragmentAdapter
17 | * version: 1.0
18 | *
19 | */
20 | public class BaseFragmentAdapter extends FragmentPagerAdapter {
21 |
22 | List fragmentList = new ArrayList();
23 | private List mTitles;
24 |
25 | public BaseFragmentAdapter(FragmentManager fm, List fragmentList) {
26 | super(fm);
27 | this.fragmentList = fragmentList;
28 | }
29 |
30 | public BaseFragmentAdapter(FragmentManager fm, List fragmentList, List mTitles) {
31 | super(fm);
32 | this.fragmentList = fragmentList;
33 | this.mTitles = mTitles;
34 | }
35 |
36 | @Override
37 | public CharSequence getPageTitle(int position) {
38 | return !isNullOrEmpty(mTitles) ? mTitles.get(position) : "";
39 | }
40 |
41 | @Override
42 | public Fragment getItem(int position) {
43 | return fragmentList.get(position);
44 | }
45 |
46 | @Override
47 | public int getCount() {
48 | return fragmentList.size();
49 | }
50 | /**
51 | * 判断集合是否为null或者0个元素
52 | *
53 | * @param c
54 | * @return
55 | */
56 | public static boolean isNullOrEmpty(Collection c) {
57 | if (null == c || c.isEmpty()) {
58 | return true;
59 | }
60 | return false;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/utils/Utils.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.os.Build;
6 | import android.os.Environment;
7 | import android.util.DisplayMetrics;
8 | import android.util.TypedValue;
9 | import android.view.Display;
10 | import android.view.KeyCharacterMap;
11 | import android.view.KeyEvent;
12 | import android.view.ViewConfiguration;
13 | import android.view.WindowManager;
14 |
15 |
16 | public class Utils {
17 |
18 | /** 获得状态栏的高度 */
19 | public static int getStatusHeight(Context context) {
20 | int statusHeight = -1;
21 | try {
22 | Class> clazz = Class.forName("com.android.internal.R$dimen");
23 | Object object = clazz.newInstance();
24 | int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString());
25 | statusHeight = context.getResources().getDimensionPixelSize(height);
26 | } catch (Exception e) {
27 | e.printStackTrace();
28 | }
29 | return statusHeight;
30 | }
31 |
32 | /** 根据屏幕宽度与密度计算GridView显示的列数, 最少为三列,并获取Item宽度 */
33 | public static int getImageItemWidth(Activity activity) {
34 | int screenWidth = activity.getResources().getDisplayMetrics().widthPixels;
35 | int densityDpi = activity.getResources().getDisplayMetrics().densityDpi;
36 | int cols = screenWidth / densityDpi;
37 | cols = cols < 3 ? 3 : cols;
38 | int columnSpace = (int) (2 * activity.getResources().getDisplayMetrics().density);
39 | return (screenWidth - columnSpace * (cols - 1)) / cols;
40 | }
41 |
42 | /**
43 | * 判断SDCard是否可用
44 | */
45 | public static boolean existSDCard() {
46 | return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
47 | }
48 |
49 | /**
50 | * 获取手机大小(分辨率)
51 | */
52 | public static DisplayMetrics getScreenPix(Activity activity) {
53 | DisplayMetrics displaysMetrics = new DisplayMetrics();
54 | activity.getWindowManager().getDefaultDisplay().getMetrics(displaysMetrics);
55 | return displaysMetrics;
56 | }
57 |
58 | /** dp转px */
59 | public static int dp2px(Context context, float dpVal) {
60 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, context.getResources().getDisplayMetrics());
61 | }
62 |
63 | /**
64 | * 判断手机是否含有虚拟按键 99%
65 | */
66 | public static boolean hasVirtualNavigationBar(Context context) {
67 | boolean hasSoftwareKeys = true;
68 |
69 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
70 | Display d = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
71 |
72 | DisplayMetrics realDisplayMetrics = new DisplayMetrics();
73 | d.getRealMetrics(realDisplayMetrics);
74 |
75 | int realHeight = realDisplayMetrics.heightPixels;
76 | int realWidth = realDisplayMetrics.widthPixels;
77 |
78 | DisplayMetrics displayMetrics = new DisplayMetrics();
79 | d.getMetrics(displayMetrics);
80 |
81 | int displayHeight = displayMetrics.heightPixels;
82 | int displayWidth = displayMetrics.widthPixels;
83 |
84 | hasSoftwareKeys = (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0;
85 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
86 | boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey();
87 | boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
88 | hasSoftwareKeys = !hasMenuKey && !hasBackKey;
89 | }
90 |
91 | return hasSoftwareKeys;
92 | }
93 |
94 | /**
95 | * 获取导航栏高度,有些没有虚拟导航栏的手机也能获取到,建议先判断是否有虚拟按键
96 | */
97 | public static int getNavigationBarHeight(Context context) {
98 | int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
99 | return resourceId > 0 ? context.getResources().getDimensionPixelSize(resourceId) : 0;
100 | }
101 |
102 | public static int getScreenW(Context aty) {
103 | DisplayMetrics dm = aty.getResources().getDisplayMetrics();
104 | return dm.widthPixels;
105 | }
106 |
107 | public static int getScreenH(Context aty) {
108 | DisplayMetrics dm = aty.getResources().getDisplayMetrics();
109 | return dm.heightPixels;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/IndicatorManager.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views;
2 |
3 | import android.support.annotation.Nullable;
4 |
5 | import com.example.indicatorlib.views.animation.AnimationManager;
6 | import com.example.indicatorlib.views.animation.controller.ValueController;
7 | import com.example.indicatorlib.views.animation.data.Value;
8 | import com.example.indicatorlib.views.draw.DrawManager;
9 | import com.example.indicatorlib.views.draw.data.Indicator;
10 |
11 |
12 | public class IndicatorManager implements ValueController.UpdateListener {
13 |
14 | private DrawManager drawManager;
15 | private AnimationManager animationManager;
16 | private Listener listener;
17 |
18 | interface Listener {
19 | void onIndicatorUpdated();
20 | }
21 |
22 | IndicatorManager(@Nullable Listener listener) {
23 | this.listener = listener;
24 | this.drawManager = new DrawManager();
25 | this.animationManager = new AnimationManager(drawManager.indicator(), this);
26 | }
27 |
28 | public AnimationManager animate() {
29 | return animationManager;
30 | }
31 |
32 | public Indicator indicator() {
33 | return drawManager.indicator();
34 | }
35 |
36 | public DrawManager drawer() {
37 | return drawManager;
38 | }
39 |
40 | @Override
41 | public void onValueUpdated(@Nullable Value value) {
42 | drawManager.updateValue(value);
43 | if (listener != null) {
44 | listener.onIndicatorUpdated();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/TabView.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.graphics.Paint;
7 | import android.graphics.RectF;
8 | import android.support.v4.view.ViewPager;
9 | import android.util.AttributeSet;
10 | import android.view.View;
11 |
12 | import com.example.indicatorlib.R;
13 | import com.example.indicatorlib.utils.Utils;
14 |
15 |
16 | /**
17 | *
18 | * author : Wp
19 | * e-mail : 1101313414@qq.com
20 | * time : 2019/5/24 10:35 AM
21 | * desc : viewPager 指示器
22 | * version: 1.0
23 | *
24 | */
25 | public class TabView extends View implements ViewPager.OnPageChangeListener {
26 |
27 | private Paint tabPaint;
28 | private float tabCount; //根据内容自动匹配
29 | private float tabWidth; //tab的宽度
30 | private int screenWidth; //屏幕看度
31 | private int tabHeight; //tab高度
32 | private int tabColor; //tab颜色
33 | private int tabRadius; //tab圆角读度数
34 | private float tabStart; //tab距离左边的边距
35 | private float tabEnd; //tab右边的位置
36 |
37 |
38 | private RectF mStripBounds = new RectF();
39 |
40 | public TabView(Context context) {
41 | super(context);
42 | }
43 |
44 | public TabView(Context context, AttributeSet attrs) {
45 | super(context, attrs);
46 | init(context,attrs);
47 | }
48 |
49 | public TabView(Context context, AttributeSet attrs, int defStyleAttr) {
50 | super(context, attrs, defStyleAttr);
51 | init(context,attrs);
52 | }
53 |
54 | private void init(Context context, AttributeSet attrs) {
55 |
56 | int defaultColor = context.getResources().getColor(R.color.red);
57 | int defaultHeight = Utils.dp2px(context, 3);
58 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TabViewDrawable);
59 | tabHeight = typedArray.getDimensionPixelSize(R.styleable.TabViewDrawable_tabHeight, defaultHeight);
60 | tabRadius = typedArray.getDimensionPixelSize(R.styleable.TabViewDrawable_tabRadius, 20);
61 | tabColor = typedArray.getColor(R.styleable.TabViewDrawable_tabColor, defaultColor);
62 | typedArray.recycle();
63 |
64 | tabPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
65 | tabPaint.setColor(tabColor);
66 | tabPaint.setStyle(Paint.Style.FILL);
67 |
68 | screenWidth = Utils.getScreenW(context);
69 | }
70 |
71 | @Override
72 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
73 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
74 | int width = measureLength(widthMeasureSpec, screenWidth);
75 | int height = measureLength(heightMeasureSpec, tabHeight);
76 | setMeasuredDimension(width, height);
77 |
78 | }
79 |
80 | private int measureLength(int measureSpec, int defaultLength) {
81 | int length = 0;
82 | int mode = MeasureSpec.getMode(measureSpec);
83 | int size = MeasureSpec.getSize(measureSpec);
84 | switch (mode) {
85 | case MeasureSpec.AT_MOST:
86 | length = Math.min(size, defaultLength);
87 | break;
88 | case MeasureSpec.EXACTLY:
89 | length = size;
90 | break;
91 | case MeasureSpec.UNSPECIFIED:
92 | length = defaultLength;
93 | break;
94 | }
95 | return length;
96 | }
97 |
98 | @Override
99 | protected void onDraw(Canvas canvas) {
100 | super.onDraw(canvas);
101 | drawTab(canvas);
102 | }
103 |
104 | private void drawTab(Canvas canvas) {
105 | //重点在于计算这个开始start位置的值和 tabWidth这个tab宽度的值 此值在滑动时都可能是变化的
106 | mStripBounds.set(tabStart, 0, tabEnd, tabHeight);
107 | canvas.drawRoundRect(mStripBounds, tabRadius, tabRadius, tabPaint);
108 | }
109 |
110 | public void setScroll(int position, float positionOffset) {
111 | tabWidth = screenWidth / tabCount;
112 | tabEnd = tabStart + tabWidth;
113 | tabStart = positionOffset * tabWidth + position * tabWidth;
114 | invalidate();
115 | }
116 |
117 | public void setViewPager(ViewPager viewPager){
118 | viewPager.addOnPageChangeListener(this);
119 | tabCount = viewPager.getAdapter().getCount();
120 | }
121 |
122 | @Override
123 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
124 | setScroll(position, positionOffset);
125 | }
126 |
127 | @Override
128 | public void onPageSelected(int position) {
129 | }
130 |
131 | @Override
132 | public void onPageScrollStateChanged(int state) {
133 |
134 | }
135 | }
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/AnimationManager.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation;
2 |
3 | import com.example.indicatorlib.views.animation.controller.AnimationController;
4 | import com.example.indicatorlib.views.animation.controller.ValueController;
5 | import com.example.indicatorlib.views.draw.data.Indicator;
6 |
7 | import android.support.annotation.NonNull;
8 |
9 | public class AnimationManager {
10 |
11 | private AnimationController animationController;
12 |
13 | public AnimationManager(@NonNull Indicator indicator, @NonNull ValueController.UpdateListener listener) {
14 | this.animationController = new AnimationController(indicator, listener);
15 | }
16 |
17 | public void basic() {
18 | if (animationController != null) {
19 | animationController.end();
20 | animationController.basic();
21 | }
22 | }
23 |
24 | public void interactive(float progress) {
25 | if (animationController != null) {
26 | animationController.interactive(progress);
27 | }
28 | }
29 |
30 | public void end() {
31 | if (animationController != null) {
32 | animationController.end();
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/controller/ValueController.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.controller;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 |
6 | import com.example.indicatorlib.views.animation.data.Value;
7 | import com.example.indicatorlib.views.animation.type.*;
8 |
9 |
10 | public class ValueController {
11 |
12 | private ColorAnimation colorAnimation;
13 | private ScaleAnimation scaleAnimation;
14 | private WormAnimation wormAnimation;
15 | private SlideAnimation slideAnimation;
16 | private FillAnimation fillAnimation;
17 | private ThinWormAnimation thinWormAnimation;
18 | private DropAnimation dropAnimation;
19 | private SwapAnimation swapAnimation;
20 | private ScaleDownAnimation scaleDownAnimation;
21 |
22 | private UpdateListener updateListener;
23 |
24 | public interface UpdateListener {
25 | void onValueUpdated(@Nullable Value value);
26 | }
27 |
28 | public ValueController(@Nullable UpdateListener listener) {
29 | updateListener = listener;
30 | }
31 |
32 | @NonNull
33 | public ColorAnimation color() {
34 | if (colorAnimation == null) {
35 | colorAnimation = new ColorAnimation(updateListener);
36 | }
37 |
38 | return colorAnimation;
39 | }
40 |
41 | @NonNull
42 | public ScaleAnimation scale() {
43 | if (scaleAnimation == null) {
44 | scaleAnimation = new ScaleAnimation(updateListener);
45 | }
46 |
47 | return scaleAnimation;
48 | }
49 |
50 | @NonNull
51 | public WormAnimation worm() {
52 | if (wormAnimation == null) {
53 | wormAnimation = new WormAnimation(updateListener);
54 | }
55 |
56 | return wormAnimation;
57 | }
58 |
59 | @NonNull
60 | public SlideAnimation slide() {
61 | if (slideAnimation == null) {
62 | slideAnimation = new SlideAnimation(updateListener);
63 | }
64 |
65 | return slideAnimation;
66 | }
67 |
68 | @NonNull
69 | public FillAnimation fill() {
70 | if (fillAnimation == null) {
71 | fillAnimation = new FillAnimation(updateListener);
72 | }
73 |
74 | return fillAnimation;
75 | }
76 |
77 | @NonNull
78 | public ThinWormAnimation thinWorm() {
79 | if (thinWormAnimation == null) {
80 | thinWormAnimation = new ThinWormAnimation(updateListener);
81 | }
82 |
83 | return thinWormAnimation;
84 | }
85 |
86 | @NonNull
87 | public DropAnimation drop() {
88 | if (dropAnimation == null) {
89 | dropAnimation = new DropAnimation(updateListener);
90 | }
91 |
92 | return dropAnimation;
93 | }
94 |
95 | @NonNull
96 | public SwapAnimation swap() {
97 | if (swapAnimation == null) {
98 | swapAnimation = new SwapAnimation(updateListener);
99 | }
100 |
101 | return swapAnimation;
102 | }
103 |
104 | @NonNull
105 | public ScaleDownAnimation scaleDown() {
106 | if (scaleDownAnimation == null) {
107 | scaleDownAnimation = new ScaleDownAnimation(updateListener);
108 | }
109 |
110 | return scaleDownAnimation;
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/data/AnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.data;
2 |
3 | import com.example.indicatorlib.views.animation.data.type.*;
4 |
5 | import android.support.annotation.NonNull;
6 |
7 | public class AnimationValue {
8 |
9 | private ColorAnimationValue colorAnimationValue;
10 | private ScaleAnimationValue scaleAnimationValue;
11 | private WormAnimationValue wormAnimationValue;
12 | private FillAnimationValue fillAnimationValue;
13 | private ThinWormAnimationValue thinWormAnimationValue;
14 | private DropAnimationValue dropAnimationValue;
15 | private SwapAnimationValue swapAnimationValue;
16 |
17 | @NonNull
18 | public ColorAnimationValue getColorAnimationValue() {
19 | if (colorAnimationValue == null) {
20 | colorAnimationValue = new ColorAnimationValue();
21 | }
22 | return colorAnimationValue;
23 | }
24 |
25 | @NonNull
26 | public ScaleAnimationValue getScaleAnimationValue() {
27 | if (scaleAnimationValue == null) {
28 | scaleAnimationValue = new ScaleAnimationValue();
29 | }
30 | return scaleAnimationValue;
31 | }
32 |
33 | @NonNull
34 | public WormAnimationValue getWormAnimationValue() {
35 | if (wormAnimationValue == null) {
36 | wormAnimationValue = new WormAnimationValue();
37 | }
38 | return wormAnimationValue;
39 | }
40 |
41 | @NonNull
42 | public FillAnimationValue getFillAnimationValue() {
43 | if (fillAnimationValue == null) {
44 | fillAnimationValue = new FillAnimationValue();
45 | }
46 | return fillAnimationValue;
47 | }
48 |
49 | @NonNull
50 | public ThinWormAnimationValue getThinWormAnimationValue() {
51 | if (thinWormAnimationValue == null) {
52 | thinWormAnimationValue = new ThinWormAnimationValue();
53 | }
54 | return thinWormAnimationValue;
55 | }
56 |
57 | @NonNull
58 | public DropAnimationValue getDropAnimationValue() {
59 | if (dropAnimationValue == null) {
60 | dropAnimationValue = new DropAnimationValue();
61 | }
62 | return dropAnimationValue;
63 | }
64 |
65 | @NonNull
66 | public SwapAnimationValue getSwapAnimationValue() {
67 | if (swapAnimationValue == null) {
68 | swapAnimationValue = new SwapAnimationValue();
69 | }
70 | return swapAnimationValue;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/data/Value.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.data;
2 |
3 | public interface Value {/*empty*/}
4 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/data/type/ColorAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.data.type;
2 |
3 | import com.example.indicatorlib.views.animation.data.Value;
4 |
5 | public class ColorAnimationValue implements Value {
6 |
7 | private int color;
8 | private int colorReverse;
9 |
10 | public int getColor() {
11 | return color;
12 | }
13 |
14 | public void setColor(int color) {
15 | this.color = color;
16 | }
17 |
18 | public int getColorReverse() {
19 | return colorReverse;
20 | }
21 |
22 | public void setColorReverse(int colorReverse) {
23 | this.colorReverse = colorReverse;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/data/type/DropAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.data.type;
2 |
3 | import com.example.indicatorlib.views.animation.data.Value;
4 |
5 | public class DropAnimationValue implements Value {
6 |
7 | private int width;
8 | private int height;
9 | private int radius;
10 |
11 | public int getWidth() {
12 | return width;
13 | }
14 |
15 | public void setWidth(int width) {
16 | this.width = width;
17 | }
18 |
19 | public int getHeight() {
20 | return height;
21 | }
22 |
23 | public void setHeight(int height) {
24 | this.height = height;
25 | }
26 |
27 | public int getRadius() {
28 | return radius;
29 | }
30 |
31 | public void setRadius(int radius) {
32 | this.radius = radius;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/data/type/FillAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.data.type;
2 |
3 | import com.example.indicatorlib.views.animation.data.Value;
4 |
5 | public class FillAnimationValue extends ColorAnimationValue implements Value {
6 |
7 | private int radius;
8 | private int radiusReverse;
9 |
10 | private int stroke;
11 | private int strokeReverse;
12 |
13 | public int getRadius() {
14 | return radius;
15 | }
16 |
17 | public void setRadius(int radius) {
18 | this.radius = radius;
19 | }
20 |
21 | public int getRadiusReverse() {
22 | return radiusReverse;
23 | }
24 |
25 | public void setRadiusReverse(int radiusReverse) {
26 | this.radiusReverse = radiusReverse;
27 | }
28 |
29 | public int getStroke() {
30 | return stroke;
31 | }
32 |
33 | public void setStroke(int stroke) {
34 | this.stroke = stroke;
35 | }
36 |
37 | public int getStrokeReverse() {
38 | return strokeReverse;
39 | }
40 |
41 | public void setStrokeReverse(int strokeReverse) {
42 | this.strokeReverse = strokeReverse;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/data/type/ScaleAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.data.type;
2 |
3 | import com.example.indicatorlib.views.animation.data.Value;
4 |
5 | public class ScaleAnimationValue extends ColorAnimationValue implements Value {
6 |
7 | private int radius;
8 | private int radiusReverse;
9 |
10 | public int getRadius() {
11 | return radius;
12 | }
13 |
14 | public void setRadius(int radius) {
15 | this.radius = radius;
16 | }
17 |
18 | public int getRadiusReverse() {
19 | return radiusReverse;
20 | }
21 |
22 | public void setRadiusReverse(int radiusReverse) {
23 | this.radiusReverse = radiusReverse;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/data/type/SlideAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.data.type;
2 |
3 | import com.example.indicatorlib.views.animation.data.Value;
4 |
5 | public class SlideAnimationValue implements Value {
6 |
7 | private int coordinate;
8 |
9 | public int getCoordinate() {
10 | return coordinate;
11 | }
12 |
13 | public void setCoordinate(int coordinate) {
14 | this.coordinate = coordinate;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/data/type/SwapAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.data.type;
2 |
3 | import com.example.indicatorlib.views.animation.data.Value;
4 |
5 | public class SwapAnimationValue implements Value {
6 |
7 | private int coordinate;
8 | private int coordinateReverse;
9 |
10 | public int getCoordinate() {
11 | return coordinate;
12 | }
13 |
14 | public void setCoordinate(int coordinate) {
15 | this.coordinate = coordinate;
16 | }
17 |
18 | public int getCoordinateReverse() {
19 | return coordinateReverse;
20 | }
21 |
22 | public void setCoordinateReverse(int coordinateReverse) {
23 | this.coordinateReverse = coordinateReverse;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/data/type/ThinWormAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.data.type;
2 |
3 | import com.example.indicatorlib.views.animation.data.Value;
4 |
5 | public class ThinWormAnimationValue extends WormAnimationValue implements Value {
6 |
7 | private int height;
8 |
9 | public int getHeight() {
10 | return height;
11 | }
12 |
13 | public void setHeight(int height) {
14 | this.height = height;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/data/type/WormAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.data.type;
2 |
3 | import com.example.indicatorlib.views.animation.data.Value;
4 |
5 | public class WormAnimationValue implements Value {
6 |
7 | private int rectStart;
8 | private int rectEnd;
9 |
10 | public int getRectStart() {
11 | return rectStart;
12 | }
13 |
14 | public void setRectStart(int rectStartEdge) {
15 | this.rectStart = rectStartEdge;
16 | }
17 |
18 | public int getRectEnd() {
19 | return rectEnd;
20 | }
21 |
22 | public void setRectEnd(int rectEnd) {
23 | this.rectEnd = rectEnd;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/type/AnimationType.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.type;
2 |
3 | public enum AnimationType {NONE, COLOR, SCALE, WORM, SLIDE, FILL, THIN_WORM, DROP, SWAP, SCALE_DOWN}
4 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/type/BaseAnimation.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.type;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ValueAnimator;
5 |
6 | import com.example.indicatorlib.views.animation.controller.ValueController;
7 |
8 | import android.support.annotation.NonNull;
9 | import android.support.annotation.NonNull;
10 | import android.support.annotation.Nullable;
11 |
12 | public abstract class BaseAnimation {
13 |
14 | public static final int DEFAULT_ANIMATION_TIME = 350;
15 | protected long animationDuration = DEFAULT_ANIMATION_TIME;
16 |
17 | protected ValueController.UpdateListener listener;
18 | protected T animator;
19 |
20 | public BaseAnimation(@Nullable ValueController.UpdateListener listener) {
21 | this.listener = listener;
22 | animator = createAnimator();
23 | }
24 |
25 | @NonNull
26 | public abstract T createAnimator();
27 |
28 | public abstract BaseAnimation progress(float progress);
29 |
30 | public BaseAnimation duration(long duration) {
31 | animationDuration = duration;
32 |
33 | if (animator instanceof ValueAnimator) {
34 | animator.setDuration(animationDuration);
35 | }
36 |
37 | return this;
38 | }
39 |
40 | public void start() {
41 | if (animator != null && !animator.isRunning()) {
42 | animator.start();
43 | }
44 | }
45 |
46 | public void end() {
47 | if (animator != null && animator.isStarted()) {
48 | animator.end();
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/type/ColorAnimation.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.type;
2 |
3 | import android.animation.ArgbEvaluator;
4 | import android.animation.PropertyValuesHolder;
5 | import android.animation.ValueAnimator;
6 | import android.support.annotation.Nullable;
7 | import android.view.animation.AccelerateDecelerateInterpolator;
8 |
9 | import com.example.indicatorlib.views.animation.controller.ValueController;
10 | import com.example.indicatorlib.views.animation.data.type.ColorAnimationValue;
11 |
12 | import android.support.annotation.NonNull;
13 | import android.support.annotation.NonNull;
14 |
15 | public class ColorAnimation extends BaseAnimation {
16 |
17 | public static final String DEFAULT_UNSELECTED_COLOR = "#33ffffff";
18 | public static final String DEFAULT_SELECTED_COLOR = "#ffffff";
19 |
20 | static final String ANIMATION_COLOR_REVERSE = "ANIMATION_COLOR_REVERSE";
21 | static final String ANIMATION_COLOR = "ANIMATION_COLOR";
22 |
23 | private ColorAnimationValue value;
24 |
25 | int colorStart;
26 | int colorEnd;
27 |
28 | public ColorAnimation(@Nullable ValueController.UpdateListener listener) {
29 | super(listener);
30 | value = new ColorAnimationValue();
31 | }
32 |
33 | @NonNull
34 | @Override
35 | public ValueAnimator createAnimator() {
36 | ValueAnimator animator = new ValueAnimator();
37 | animator.setDuration(BaseAnimation.DEFAULT_ANIMATION_TIME);
38 | animator.setInterpolator(new AccelerateDecelerateInterpolator());
39 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
40 | @Override
41 | public void onAnimationUpdate(ValueAnimator animation) {
42 | onAnimateUpdated(animation);
43 | }
44 | });
45 |
46 | return animator;
47 | }
48 |
49 | @Override
50 | public ColorAnimation progress(float progress) {
51 | if (animator != null) {
52 | long playTime = (long) (progress * animationDuration);
53 |
54 | if (animator.getValues() != null && animator.getValues().length > 0) {
55 | animator.setCurrentPlayTime(playTime);
56 | }
57 | }
58 |
59 | return this;
60 | }
61 |
62 | @NonNull
63 | public ColorAnimation with(int colorStart, int colorEnd) {
64 | if (animator != null && hasChanges(colorStart, colorEnd)) {
65 |
66 | this.colorStart = colorStart;
67 | this.colorEnd = colorEnd;
68 |
69 | PropertyValuesHolder colorHolder = createColorPropertyHolder(false);
70 | PropertyValuesHolder reverseColorHolder = createColorPropertyHolder(true);
71 |
72 | animator.setValues(colorHolder, reverseColorHolder);
73 | }
74 |
75 | return this;
76 | }
77 |
78 | PropertyValuesHolder createColorPropertyHolder(boolean isReverse) {
79 | String propertyName;
80 | int colorStart;
81 | int colorEnd;
82 |
83 | if (isReverse) {
84 | propertyName = ANIMATION_COLOR_REVERSE;
85 | colorStart = this.colorEnd;
86 | colorEnd = this.colorStart;
87 |
88 | } else {
89 | propertyName = ANIMATION_COLOR;
90 | colorStart = this.colorStart;
91 | colorEnd = this.colorEnd;
92 | }
93 |
94 | PropertyValuesHolder holder = PropertyValuesHolder.ofInt(propertyName, colorStart, colorEnd);
95 | holder.setEvaluator(new ArgbEvaluator());
96 |
97 | return holder;
98 | }
99 |
100 | @SuppressWarnings("RedundantIfStatement")
101 | private boolean hasChanges(int colorStart, int colorEnd) {
102 | if (this.colorStart != colorStart) {
103 | return true;
104 | }
105 |
106 | if (this.colorEnd != colorEnd) {
107 | return true;
108 | }
109 |
110 | return false;
111 | }
112 |
113 | private void onAnimateUpdated(@NonNull ValueAnimator animation) {
114 | int color = (int) animation.getAnimatedValue(ANIMATION_COLOR);
115 | int colorReverse = (int) animation.getAnimatedValue(ANIMATION_COLOR_REVERSE);
116 |
117 | value.setColor(color);
118 | value.setColorReverse(colorReverse);
119 |
120 | if (listener != null) {
121 | listener.onValueUpdated(value);
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/type/DropAnimation.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.type;
2 |
3 | import android.animation.Animator;
4 | import android.animation.AnimatorSet;
5 | import android.animation.ValueAnimator;
6 | import android.view.animation.AccelerateDecelerateInterpolator;
7 |
8 | import com.example.indicatorlib.views.animation.controller.ValueController;
9 | import com.example.indicatorlib.views.animation.data.type.DropAnimationValue;
10 |
11 | import android.support.annotation.NonNull;
12 |
13 | public class DropAnimation extends BaseAnimation {
14 |
15 | private int widthStart;
16 | private int widthEnd;
17 | private int heightStart;
18 | private int heightEnd;
19 | private int radius;
20 |
21 | private enum AnimationType {Width, Height, Radius}
22 |
23 | private DropAnimationValue value;
24 |
25 | public DropAnimation(@NonNull ValueController.UpdateListener listener) {
26 | super(listener);
27 | value = new DropAnimationValue();
28 | }
29 |
30 | @NonNull
31 | @Override
32 | public AnimatorSet createAnimator() {
33 | AnimatorSet animator = new AnimatorSet();
34 | animator.setInterpolator(new AccelerateDecelerateInterpolator());
35 |
36 | return animator;
37 | }
38 |
39 | @Override
40 | public DropAnimation progress(float progress) {
41 | if (animator != null) {
42 | long playTimeLeft = (long) (progress * animationDuration);
43 | boolean isReverse = false;
44 |
45 | for (Animator anim : animator.getChildAnimations()) {
46 | ValueAnimator animator = (ValueAnimator) anim;
47 | long animDuration = animator.getDuration();
48 | long currPlayTime = playTimeLeft;
49 |
50 | if (isReverse) {
51 | currPlayTime -= animDuration;
52 | }
53 |
54 | if (currPlayTime < 0) {
55 | continue;
56 |
57 | } else if (currPlayTime >= animDuration) {
58 | currPlayTime = animDuration;
59 | }
60 |
61 | if (animator.getValues() != null && animator.getValues().length > 0) {
62 | animator.setCurrentPlayTime(currPlayTime);
63 | }
64 |
65 | if (!isReverse && animDuration >= animationDuration) {
66 | isReverse = true;
67 | }
68 | }
69 | }
70 |
71 | return this;
72 | }
73 |
74 | @Override
75 | public DropAnimation duration(long duration) {
76 | super.duration(duration);
77 | return this;
78 | }
79 |
80 | @SuppressWarnings("UnnecessaryLocalVariable")
81 | public DropAnimation with(int widthStart, int widthEnd, int heightStart, int heightEnd, int radius) {
82 | if (hasChanges(widthStart, widthEnd, heightStart, heightEnd, radius)) {
83 | animator = createAnimator();
84 |
85 | this.widthStart = widthStart;
86 | this.widthEnd = widthEnd;
87 | this.heightStart = heightStart;
88 | this.heightEnd = heightEnd;
89 | this.radius = radius;
90 |
91 | int fromRadius = radius;
92 | int toRadius = (int) (radius / 1.5);
93 | long halfDuration = animationDuration / 2;
94 |
95 | ValueAnimator widthAnimator = createValueAnimation(widthStart, widthEnd, animationDuration, AnimationType.Width);
96 | ValueAnimator heightForwardAnimator = createValueAnimation(heightStart, heightEnd, halfDuration, AnimationType.Height);
97 | ValueAnimator radiusForwardAnimator = createValueAnimation(fromRadius, toRadius, halfDuration, AnimationType.Radius);
98 |
99 | ValueAnimator heightBackwardAnimator = createValueAnimation(heightEnd, heightStart, halfDuration, AnimationType.Height);
100 | ValueAnimator radiusBackwardAnimator = createValueAnimation(toRadius, fromRadius, halfDuration, AnimationType.Radius);
101 |
102 | animator.play(heightForwardAnimator)
103 | .with(radiusForwardAnimator)
104 | .with(widthAnimator)
105 | .before(heightBackwardAnimator)
106 | .before(radiusBackwardAnimator);
107 | }
108 |
109 | return this;
110 | }
111 |
112 | private ValueAnimator createValueAnimation(int fromValue, int toValue, long duration, final AnimationType type) {
113 | ValueAnimator anim = ValueAnimator.ofInt(fromValue, toValue);
114 | anim.setInterpolator(new AccelerateDecelerateInterpolator());
115 | anim.setDuration(duration);
116 | anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
117 | @Override
118 | public void onAnimationUpdate(ValueAnimator animation) {
119 | onAnimatorUpdate(animation, type);
120 | }
121 | });
122 |
123 | return anim;
124 | }
125 |
126 | private void onAnimatorUpdate(@NonNull ValueAnimator animation, @NonNull AnimationType type) {
127 | int frameValue = (int) animation.getAnimatedValue();
128 |
129 | switch (type) {
130 | case Width:
131 | value.setWidth(frameValue);
132 | break;
133 |
134 | case Height:
135 | value.setHeight(frameValue);
136 | break;
137 |
138 | case Radius:
139 | value.setRadius(frameValue);
140 | break;
141 | }
142 |
143 | if (listener != null) {
144 | listener.onValueUpdated(value);
145 | }
146 | }
147 |
148 | @SuppressWarnings("RedundantIfStatement")
149 | private boolean hasChanges(int widthStart, int widthEnd, int heightStart, int heightEnd, int radius) {
150 | if (this.widthStart != widthStart) {
151 | return true;
152 | }
153 |
154 | if (this.widthEnd != widthEnd) {
155 | return true;
156 | }
157 |
158 | if (this.heightStart != heightStart) {
159 | return true;
160 | }
161 |
162 | if (this.heightEnd != heightEnd) {
163 | return true;
164 | }
165 |
166 | if (this.radius != radius) {
167 | return true;
168 | }
169 |
170 | return false;
171 | }
172 |
173 | }
174 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/type/FillAnimation.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.type;
2 |
3 | import android.animation.IntEvaluator;
4 | import android.animation.PropertyValuesHolder;
5 | import android.animation.ValueAnimator;
6 | import android.view.animation.AccelerateDecelerateInterpolator;
7 |
8 | import com.example.indicatorlib.views.animation.controller.ValueController;
9 | import com.example.indicatorlib.views.animation.data.type.FillAnimationValue;
10 |
11 | import android.support.annotation.NonNull;
12 |
13 | public class FillAnimation extends ColorAnimation {
14 |
15 | private static final String ANIMATION_RADIUS_REVERSE = "ANIMATION_RADIUS_REVERSE";
16 | private static final String ANIMATION_RADIUS = "ANIMATION_RADIUS";
17 |
18 | private static final String ANIMATION_STROKE_REVERSE = "ANIMATION_STROKE_REVERSE";
19 | private static final String ANIMATION_STROKE = "ANIMATION_STROKE";
20 |
21 | public static final int DEFAULT_STROKE_DP = 1;
22 | private FillAnimationValue value;
23 |
24 | private int radius;
25 | private int stroke;
26 |
27 | public FillAnimation(@NonNull ValueController.UpdateListener listener) {
28 | super(listener);
29 | value = new FillAnimationValue();
30 | }
31 |
32 | @NonNull
33 | @Override
34 | public ValueAnimator createAnimator() {
35 | ValueAnimator animator = new ValueAnimator();
36 | animator.setDuration(BaseAnimation.DEFAULT_ANIMATION_TIME);
37 | animator.setInterpolator(new AccelerateDecelerateInterpolator());
38 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
39 | @Override
40 | public void onAnimationUpdate(ValueAnimator animation) {
41 | onAnimateUpdated(animation);
42 | }
43 | });
44 |
45 | return animator;
46 | }
47 |
48 | @NonNull
49 | public FillAnimation with(int colorStart, int colorEnd, int radius, int stroke) {
50 | if (animator != null && hasChanges(colorStart, colorEnd, radius, stroke)) {
51 |
52 | this.colorStart = colorStart;
53 | this.colorEnd = colorEnd;
54 |
55 | this.radius = radius;
56 | this.stroke = stroke;
57 |
58 | PropertyValuesHolder colorHolder = createColorPropertyHolder(false);
59 | PropertyValuesHolder reverseColorHolder = createColorPropertyHolder(true);
60 |
61 | PropertyValuesHolder radiusHolder = createRadiusPropertyHolder(false);
62 | PropertyValuesHolder radiusReverseHolder = createRadiusPropertyHolder(true);
63 |
64 | PropertyValuesHolder strokeHolder = createStrokePropertyHolder(false);
65 | PropertyValuesHolder strokeReverseHolder = createStrokePropertyHolder(true);
66 |
67 | animator.setValues(
68 | colorHolder,
69 | reverseColorHolder,
70 |
71 | radiusHolder,
72 | radiusReverseHolder,
73 |
74 | strokeHolder,
75 | strokeReverseHolder);
76 | }
77 |
78 | return this;
79 | }
80 |
81 | @NonNull
82 | private PropertyValuesHolder createRadiusPropertyHolder(boolean isReverse) {
83 | String propertyName;
84 | int startRadiusValue;
85 | int endRadiusValue;
86 |
87 | if (isReverse) {
88 | propertyName = ANIMATION_RADIUS_REVERSE;
89 | startRadiusValue = radius / 2;
90 | endRadiusValue = radius;
91 | } else {
92 | propertyName = ANIMATION_RADIUS;
93 | startRadiusValue = radius;
94 | endRadiusValue = radius / 2;
95 | }
96 |
97 | PropertyValuesHolder holder = PropertyValuesHolder.ofInt(propertyName, startRadiusValue, endRadiusValue);
98 | holder.setEvaluator(new IntEvaluator());
99 |
100 | return holder;
101 | }
102 |
103 | @NonNull
104 | private PropertyValuesHolder createStrokePropertyHolder(boolean isReverse) {
105 | String propertyName;
106 | int startStrokeValue;
107 | int endStrokeValue;
108 |
109 | if (isReverse) {
110 | propertyName = ANIMATION_STROKE_REVERSE;
111 | startStrokeValue = radius;
112 | endStrokeValue = 0;
113 | } else {
114 | propertyName = ANIMATION_STROKE;
115 | startStrokeValue = 0;
116 | endStrokeValue = radius;
117 | }
118 |
119 | PropertyValuesHolder holder = PropertyValuesHolder.ofInt(propertyName, startStrokeValue, endStrokeValue);
120 | holder.setEvaluator(new IntEvaluator());
121 |
122 | return holder;
123 | }
124 |
125 | private void onAnimateUpdated(@NonNull ValueAnimator animation) {
126 | int color = (int) animation.getAnimatedValue(ANIMATION_COLOR);
127 | int colorReverse = (int) animation.getAnimatedValue(ANIMATION_COLOR_REVERSE);
128 |
129 | int radius = (int) animation.getAnimatedValue(ANIMATION_RADIUS);
130 | int radiusReverse = (int) animation.getAnimatedValue(ANIMATION_RADIUS_REVERSE);
131 |
132 | int stroke = (int) animation.getAnimatedValue(ANIMATION_STROKE);
133 | int strokeReverse = (int) animation.getAnimatedValue(ANIMATION_STROKE_REVERSE);
134 |
135 | value.setColor(color);
136 | value.setColorReverse(colorReverse);
137 |
138 | value.setRadius(radius);
139 | value.setRadiusReverse(radiusReverse);
140 |
141 | value.setStroke(stroke);
142 | value.setStrokeReverse(strokeReverse);
143 |
144 | if (listener != null) {
145 | listener.onValueUpdated(value);
146 | }
147 | }
148 |
149 | @SuppressWarnings("RedundantIfStatement")
150 | private boolean hasChanges(int colorStart, int colorEnd, int radiusValue, int strokeValue) {
151 | if (this.colorStart != colorStart) {
152 | return true;
153 | }
154 |
155 | if (this.colorEnd != colorEnd) {
156 | return true;
157 | }
158 |
159 | if (radius != radiusValue) {
160 | return true;
161 | }
162 |
163 | if (stroke != strokeValue) {
164 | return true;
165 | }
166 |
167 | return false;
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/type/ScaleAnimation.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.type;
2 |
3 | import android.animation.IntEvaluator;
4 | import android.animation.PropertyValuesHolder;
5 | import android.animation.ValueAnimator;
6 | import android.view.animation.AccelerateDecelerateInterpolator;
7 |
8 | import com.example.indicatorlib.views.animation.controller.ValueController;
9 | import com.example.indicatorlib.views.animation.data.type.ScaleAnimationValue;
10 |
11 | import android.support.annotation.NonNull;
12 |
13 | public class ScaleAnimation extends ColorAnimation {
14 |
15 | public static final float DEFAULT_SCALE_FACTOR = 0.7f;
16 | public static final float MIN_SCALE_FACTOR = 0.3f;
17 | public static final float MAX_SCALE_FACTOR = 1;
18 |
19 | static final String ANIMATION_SCALE_REVERSE = "ANIMATION_SCALE_REVERSE";
20 | static final String ANIMATION_SCALE = "ANIMATION_SCALE";
21 |
22 | int radius;
23 | float scaleFactor;
24 |
25 | private ScaleAnimationValue value;
26 |
27 | public ScaleAnimation(@NonNull ValueController.UpdateListener listener) {
28 | super(listener);
29 | value = new ScaleAnimationValue();
30 | }
31 |
32 | @NonNull
33 | @Override
34 | public ValueAnimator createAnimator() {
35 | ValueAnimator animator = new ValueAnimator();
36 | animator.setDuration(BaseAnimation.DEFAULT_ANIMATION_TIME);
37 | animator.setInterpolator(new AccelerateDecelerateInterpolator());
38 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
39 | @Override
40 | public void onAnimationUpdate(ValueAnimator animation) {
41 | onAnimateUpdated(animation);
42 | }
43 | });
44 |
45 | return animator;
46 | }
47 |
48 | @NonNull
49 | public ScaleAnimation with(int colorStart, int colorEnd, int radius, float scaleFactor) {
50 | if (animator != null && hasChanges(colorStart, colorEnd, radius, scaleFactor)) {
51 |
52 | this.colorStart = colorStart;
53 | this.colorEnd = colorEnd;
54 |
55 | this.radius = radius;
56 | this.scaleFactor = scaleFactor;
57 |
58 | PropertyValuesHolder colorHolder = createColorPropertyHolder(false);
59 | PropertyValuesHolder reverseColorHolder = createColorPropertyHolder(true);
60 |
61 | PropertyValuesHolder scaleHolder = createScalePropertyHolder(false);
62 | PropertyValuesHolder scaleReverseHolder = createScalePropertyHolder(true);
63 |
64 | animator.setValues(colorHolder, reverseColorHolder, scaleHolder, scaleReverseHolder);
65 | }
66 |
67 | return this;
68 | }
69 |
70 | private void onAnimateUpdated(@NonNull ValueAnimator animation) {
71 | int color = (int) animation.getAnimatedValue(ANIMATION_COLOR);
72 | int colorReverse = (int) animation.getAnimatedValue(ANIMATION_COLOR_REVERSE);
73 |
74 | int radius = (int) animation.getAnimatedValue(ANIMATION_SCALE);
75 | int radiusReverse = (int) animation.getAnimatedValue(ANIMATION_SCALE_REVERSE);
76 |
77 | value.setColor(color);
78 | value.setColorReverse(colorReverse);
79 |
80 | value.setRadius(radius);
81 | value.setRadiusReverse(radiusReverse);
82 |
83 | if (listener != null) {
84 | listener.onValueUpdated(value);
85 | }
86 | }
87 |
88 | @NonNull
89 | protected PropertyValuesHolder createScalePropertyHolder(boolean isReverse) {
90 | String propertyName;
91 | int startRadiusValue;
92 | int endRadiusValue;
93 |
94 | if (isReverse) {
95 | propertyName = ANIMATION_SCALE_REVERSE;
96 | startRadiusValue = radius;
97 | endRadiusValue = (int) (radius * scaleFactor);
98 | } else {
99 | propertyName = ANIMATION_SCALE;
100 | startRadiusValue = (int) (radius * scaleFactor);
101 | endRadiusValue = radius;
102 | }
103 |
104 | PropertyValuesHolder holder = PropertyValuesHolder.ofInt(propertyName, startRadiusValue, endRadiusValue);
105 | holder.setEvaluator(new IntEvaluator());
106 |
107 | return holder;
108 | }
109 |
110 | @SuppressWarnings("RedundantIfStatement")
111 | private boolean hasChanges(int colorStart, int colorEnd, int radiusValue, float scaleFactorValue) {
112 | if (this.colorStart != colorStart) {
113 | return true;
114 | }
115 |
116 | if (this.colorEnd != colorEnd) {
117 | return true;
118 | }
119 |
120 | if (radius != radiusValue) {
121 | return true;
122 | }
123 |
124 | if (scaleFactor != scaleFactorValue) {
125 | return true;
126 | }
127 |
128 | return false;
129 | }
130 | }
131 |
132 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/type/ScaleDownAnimation.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.type;
2 |
3 | import android.animation.IntEvaluator;
4 | import android.animation.PropertyValuesHolder;
5 |
6 | import com.example.indicatorlib.views.animation.controller.ValueController;
7 |
8 | import android.support.annotation.NonNull;
9 |
10 | public class ScaleDownAnimation extends ScaleAnimation {
11 |
12 | public ScaleDownAnimation(@NonNull ValueController.UpdateListener listener) {
13 | super(listener);
14 | }
15 |
16 | @NonNull
17 | @Override
18 | protected PropertyValuesHolder createScalePropertyHolder(boolean isReverse) {
19 | String propertyName;
20 | int startRadiusValue;
21 | int endRadiusValue;
22 |
23 | if (isReverse) {
24 | propertyName = ANIMATION_SCALE_REVERSE;
25 | startRadiusValue = (int) (radius * scaleFactor);
26 | endRadiusValue = radius;
27 | } else {
28 | propertyName = ANIMATION_SCALE;
29 | startRadiusValue = radius;
30 | endRadiusValue = (int) (radius * scaleFactor);
31 | }
32 |
33 | PropertyValuesHolder holder = PropertyValuesHolder.ofInt(propertyName, startRadiusValue, endRadiusValue);
34 | holder.setEvaluator(new IntEvaluator());
35 |
36 | return holder;
37 | }
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/type/SlideAnimation.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.type;
2 |
3 | import android.animation.IntEvaluator;
4 | import android.animation.PropertyValuesHolder;
5 | import android.animation.ValueAnimator;
6 | import android.view.animation.AccelerateDecelerateInterpolator;
7 |
8 | import com.example.indicatorlib.views.animation.controller.ValueController;
9 | import com.example.indicatorlib.views.animation.data.type.SlideAnimationValue;
10 |
11 | import android.support.annotation.NonNull;
12 |
13 | public class SlideAnimation extends BaseAnimation {
14 |
15 | private static final String ANIMATION_COORDINATE = "ANIMATION_COORDINATE";
16 | private static final int COORDINATE_NONE = -1;
17 |
18 | private SlideAnimationValue value;
19 | private int coordinateStart = COORDINATE_NONE;
20 | private int coordinateEnd = COORDINATE_NONE;
21 |
22 | public SlideAnimation(@NonNull ValueController.UpdateListener listener) {
23 | super(listener);
24 | value = new SlideAnimationValue();
25 | }
26 |
27 | @NonNull
28 | @Override
29 | public ValueAnimator createAnimator() {
30 | ValueAnimator animator = new ValueAnimator();
31 | animator.setDuration(BaseAnimation.DEFAULT_ANIMATION_TIME);
32 | animator.setInterpolator(new AccelerateDecelerateInterpolator());
33 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
34 | @Override
35 | public void onAnimationUpdate(ValueAnimator animation) {
36 | onAnimateUpdated(animation);
37 | }
38 | });
39 |
40 | return animator;
41 | }
42 |
43 | @Override
44 | public SlideAnimation progress(float progress) {
45 | if (animator != null) {
46 | long playTime = (long) (progress * animationDuration);
47 |
48 | if (animator.getValues() != null && animator.getValues().length > 0) {
49 | animator.setCurrentPlayTime(playTime);
50 | }
51 | }
52 |
53 | return this;
54 | }
55 |
56 | @NonNull
57 | public SlideAnimation with(int coordinateStart, int coordinateEnd) {
58 | if (animator != null && hasChanges(coordinateStart, coordinateEnd)) {
59 |
60 | this.coordinateStart = coordinateStart;
61 | this.coordinateEnd = coordinateEnd;
62 |
63 | PropertyValuesHolder holder = createSlidePropertyHolder();
64 | animator.setValues(holder);
65 | }
66 |
67 | return this;
68 | }
69 |
70 | private PropertyValuesHolder createSlidePropertyHolder() {
71 | PropertyValuesHolder holder = PropertyValuesHolder.ofInt(ANIMATION_COORDINATE, coordinateStart, coordinateEnd);
72 | holder.setEvaluator(new IntEvaluator());
73 |
74 | return holder;
75 | }
76 |
77 | private void onAnimateUpdated(@NonNull ValueAnimator animation) {
78 | int coordinate = (int) animation.getAnimatedValue(ANIMATION_COORDINATE);
79 | value.setCoordinate(coordinate);
80 |
81 | if (listener != null) {
82 | listener.onValueUpdated(value);
83 | }
84 | }
85 |
86 | @SuppressWarnings("RedundantIfStatement")
87 | private boolean hasChanges(int coordinateStart, int coordinateEnd) {
88 | if (this.coordinateStart != coordinateStart) {
89 | return true;
90 | }
91 |
92 | if (this.coordinateEnd != coordinateEnd) {
93 | return true;
94 | }
95 |
96 | return false;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/type/SwapAnimation.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.type;
2 |
3 | import android.animation.IntEvaluator;
4 | import android.animation.PropertyValuesHolder;
5 | import android.animation.ValueAnimator;
6 | import android.view.animation.AccelerateDecelerateInterpolator;
7 |
8 | import com.example.indicatorlib.views.animation.controller.ValueController;
9 | import com.example.indicatorlib.views.animation.data.type.SwapAnimationValue;
10 |
11 | import android.support.annotation.NonNull;
12 |
13 | public class SwapAnimation extends BaseAnimation {
14 |
15 | private static final String ANIMATION_COORDINATE = "ANIMATION_COORDINATE";
16 | private static final String ANIMATION_COORDINATE_REVERSE = "ANIMATION_COORDINATE_REVERSE";
17 | private static final int COORDINATE_NONE = -1;
18 |
19 | private int coordinateStart = COORDINATE_NONE;
20 | private int coordinateEnd = COORDINATE_NONE;
21 |
22 | private SwapAnimationValue value;
23 |
24 | public SwapAnimation(@NonNull ValueController.UpdateListener listener) {
25 | super(listener);
26 | value = new SwapAnimationValue();
27 | }
28 |
29 | @NonNull
30 | @Override
31 | public ValueAnimator createAnimator() {
32 | ValueAnimator animator = new ValueAnimator();
33 | animator.setDuration(BaseAnimation.DEFAULT_ANIMATION_TIME);
34 | animator.setInterpolator(new AccelerateDecelerateInterpolator());
35 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
36 | @Override
37 | public void onAnimationUpdate(ValueAnimator animation) {
38 | onAnimateUpdated(animation);
39 | }
40 | });
41 |
42 | return animator;
43 | }
44 |
45 | @Override
46 | public SwapAnimation progress(float progress) {
47 | if (animator != null) {
48 | long playTime = (long) (progress * animationDuration);
49 |
50 | if (animator.getValues() != null && animator.getValues().length > 0) {
51 | animator.setCurrentPlayTime(playTime);
52 | }
53 | }
54 |
55 | return this;
56 | }
57 |
58 | @NonNull
59 | public SwapAnimation with(int coordinateStart, int coordinateEnd) {
60 | if (animator != null && hasChanges(coordinateStart, coordinateEnd)) {
61 | this.coordinateStart = coordinateStart;
62 | this.coordinateEnd = coordinateEnd;
63 |
64 | PropertyValuesHolder holder = createColorPropertyHolder(ANIMATION_COORDINATE, coordinateStart, coordinateEnd);
65 | PropertyValuesHolder holderReverse = createColorPropertyHolder(ANIMATION_COORDINATE_REVERSE, coordinateEnd, coordinateStart);
66 | animator.setValues(holder, holderReverse);
67 | }
68 |
69 | return this;
70 | }
71 |
72 | private PropertyValuesHolder createColorPropertyHolder(String propertyName, int startValue, int endValue) {
73 | PropertyValuesHolder holder = PropertyValuesHolder.ofInt(propertyName, startValue, endValue);
74 | holder.setEvaluator(new IntEvaluator());
75 |
76 | return holder;
77 | }
78 |
79 | private void onAnimateUpdated(@NonNull ValueAnimator animation) {
80 | int coordinate = (int) animation.getAnimatedValue(ANIMATION_COORDINATE);
81 | int coordinateReverse = (int) animation.getAnimatedValue(ANIMATION_COORDINATE_REVERSE);
82 |
83 | value.setCoordinate(coordinate);
84 | value.setCoordinateReverse(coordinateReverse);
85 |
86 | if (listener != null) {
87 | listener.onValueUpdated(value);
88 | }
89 | }
90 |
91 | @SuppressWarnings("RedundantIfStatement")
92 | private boolean hasChanges(int coordinateStart, int coordinateEnd) {
93 | if (this.coordinateStart != coordinateStart) {
94 | return true;
95 | }
96 |
97 | if (this.coordinateEnd != coordinateEnd) {
98 | return true;
99 | }
100 |
101 | return false;
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/type/ThinWormAnimation.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.type;
2 |
3 | import android.animation.ValueAnimator;
4 | import android.view.animation.AccelerateDecelerateInterpolator;
5 |
6 | import com.example.indicatorlib.views.animation.controller.ValueController;
7 | import com.example.indicatorlib.views.animation.data.type.ThinWormAnimationValue;
8 |
9 | import android.support.annotation.NonNull;
10 |
11 | public class ThinWormAnimation extends WormAnimation {
12 |
13 | private ThinWormAnimationValue value;
14 |
15 | public ThinWormAnimation(@NonNull ValueController.UpdateListener listener) {
16 | super(listener);
17 | value = new ThinWormAnimationValue();
18 | }
19 |
20 | @Override
21 | public ThinWormAnimation duration(long duration) {
22 | super.duration(duration);
23 | return this;
24 | }
25 |
26 | @Override
27 | public WormAnimation with(int coordinateStart, int coordinateEnd, int radius, boolean isRightSide) {
28 | if (hasChanges(coordinateStart, coordinateEnd, radius, isRightSide)) {
29 | animator = createAnimator();
30 |
31 | this.coordinateStart = coordinateStart;
32 | this.coordinateEnd = coordinateEnd;
33 |
34 | this.radius = radius;
35 | this.isRightSide = isRightSide;
36 |
37 | int height = radius * 2;
38 | rectLeftEdge = coordinateStart - radius;
39 | rectRightEdge = coordinateStart + radius;
40 |
41 | value.setRectStart(rectLeftEdge);
42 | value.setRectEnd(rectRightEdge);
43 | value.setHeight(height);
44 |
45 | RectValues rec = createRectValues(isRightSide);
46 | long sizeDuration = (long) (animationDuration * 0.8);
47 | long reverseDelay = (long) (animationDuration * 0.2);
48 |
49 | long heightDuration = (long) (animationDuration * 0.5);
50 | long reverseHeightDelay = (long) (animationDuration * 0.5);
51 |
52 | ValueAnimator straightAnimator = createWormAnimator(rec.fromX, rec.toX, sizeDuration, false, value);
53 | ValueAnimator reverseAnimator = createWormAnimator(rec.reverseFromX, rec.reverseToX, sizeDuration, true, value);
54 | reverseAnimator.setStartDelay(reverseDelay);
55 |
56 | ValueAnimator straightHeightAnimator = createHeightAnimator(height, radius, heightDuration);
57 | ValueAnimator reverseHeightAnimator = createHeightAnimator(radius, height, heightDuration);
58 | reverseHeightAnimator.setStartDelay(reverseHeightDelay);
59 |
60 | animator.playTogether(straightAnimator, reverseAnimator, straightHeightAnimator, reverseHeightAnimator);
61 | }
62 | return this;
63 | }
64 |
65 | private ValueAnimator createHeightAnimator(int fromHeight, int toHeight, long duration) {
66 | ValueAnimator anim = ValueAnimator.ofInt(fromHeight, toHeight);
67 | anim.setInterpolator(new AccelerateDecelerateInterpolator());
68 | anim.setDuration(duration);
69 | anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
70 | @Override
71 | public void onAnimationUpdate(ValueAnimator animation) {
72 | onAnimateUpdated(animation);
73 | }
74 | });
75 |
76 | return anim;
77 | }
78 |
79 | private void onAnimateUpdated(@NonNull ValueAnimator animation) {
80 | value.setHeight((int) animation.getAnimatedValue());
81 |
82 | if (listener != null) {
83 | listener.onValueUpdated(value);
84 | }
85 | }
86 |
87 | @Override
88 | public ThinWormAnimation progress(float progress) {
89 | if (animator != null) {
90 | long progressDuration = (long) (progress * animationDuration);
91 | int size = animator.getChildAnimations().size();
92 |
93 | for (int i = 0; i < size; i++) {
94 | ValueAnimator anim = (ValueAnimator) animator.getChildAnimations().get(i);
95 |
96 | long setDuration = progressDuration - anim.getStartDelay();
97 | long duration = anim.getDuration();
98 |
99 | if (setDuration > duration) {
100 | setDuration = duration;
101 |
102 | } else if (setDuration < 0) {
103 | setDuration = 0;
104 | }
105 |
106 | if (i == size - 1 && setDuration <= 0) {
107 | continue;
108 | }
109 |
110 | if (anim.getValues() != null && anim.getValues().length > 0) {
111 | anim.setCurrentPlayTime(setDuration);
112 | }
113 | }
114 | }
115 |
116 | return this;
117 | }
118 | }
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/animation/type/WormAnimation.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.animation.type;
2 |
3 | import android.animation.Animator;
4 | import android.animation.AnimatorSet;
5 | import android.animation.ValueAnimator;
6 | import android.view.animation.AccelerateDecelerateInterpolator;
7 |
8 | import com.example.indicatorlib.views.animation.controller.ValueController;
9 | import com.example.indicatorlib.views.animation.data.type.WormAnimationValue;
10 |
11 | import android.support.annotation.NonNull;
12 |
13 | public class WormAnimation extends BaseAnimation {
14 |
15 | int coordinateStart;
16 | int coordinateEnd;
17 |
18 | int radius;
19 | boolean isRightSide;
20 |
21 | int rectLeftEdge;
22 | int rectRightEdge;
23 |
24 | private WormAnimationValue value;
25 |
26 | public WormAnimation(@NonNull ValueController.UpdateListener listener) {
27 | super(listener);
28 | value = new WormAnimationValue();
29 | }
30 |
31 | @NonNull
32 | @Override
33 | public AnimatorSet createAnimator() {
34 | AnimatorSet animator = new AnimatorSet();
35 | animator.setInterpolator(new AccelerateDecelerateInterpolator());
36 |
37 | return animator;
38 | }
39 |
40 | @Override
41 | public WormAnimation duration(long duration) {
42 | super.duration(duration);
43 | return this;
44 | }
45 |
46 | public WormAnimation with(int coordinateStart, int coordinateEnd, int radius, boolean isRightSide) {
47 | if (hasChanges(coordinateStart, coordinateEnd, radius, isRightSide)) {
48 | animator = createAnimator();
49 |
50 | this.coordinateStart = coordinateStart;
51 | this.coordinateEnd = coordinateEnd;
52 |
53 | this.radius = radius;
54 | this.isRightSide = isRightSide;
55 |
56 | rectLeftEdge = coordinateStart - radius;
57 | rectRightEdge = coordinateStart + radius;
58 |
59 | value.setRectStart(rectLeftEdge);
60 | value.setRectEnd(rectRightEdge);
61 |
62 | RectValues rect = createRectValues(isRightSide);
63 | long duration = animationDuration / 2;
64 |
65 | ValueAnimator straightAnimator = createWormAnimator(rect.fromX, rect.toX, duration, false, value);
66 | ValueAnimator reverseAnimator = createWormAnimator(rect.reverseFromX, rect.reverseToX, duration, true, value);
67 | animator.playSequentially(straightAnimator, reverseAnimator);
68 | }
69 | return this;
70 | }
71 |
72 | @Override
73 | public WormAnimation progress(float progress) {
74 | if (animator == null) {
75 | return this;
76 | }
77 |
78 | long progressDuration = (long) (progress * animationDuration);
79 | for (Animator anim : animator.getChildAnimations()) {
80 | ValueAnimator animator = (ValueAnimator) anim;
81 | long duration = animator.getDuration();
82 | long setDuration = progressDuration;
83 |
84 | if (setDuration > duration) {
85 | setDuration = duration;
86 | }
87 |
88 | animator.setCurrentPlayTime(setDuration);
89 | progressDuration -= setDuration;
90 | }
91 |
92 | return this;
93 | }
94 |
95 | ValueAnimator createWormAnimator(
96 | int fromValue,
97 | int toValue,
98 | long duration,
99 | final boolean isReverse,
100 | final WormAnimationValue value) {
101 |
102 | ValueAnimator anim = ValueAnimator.ofInt(fromValue, toValue);
103 | anim.setInterpolator(new AccelerateDecelerateInterpolator());
104 | anim.setDuration(duration);
105 | anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
106 | @Override
107 | public void onAnimationUpdate(ValueAnimator animation) {
108 | onAnimateUpdated(value, animation, isReverse);
109 | }
110 | });
111 |
112 | return anim;
113 | }
114 |
115 | private void onAnimateUpdated(@NonNull WormAnimationValue value, @NonNull ValueAnimator animation, final boolean isReverse) {
116 | int rectEdge = (int) animation.getAnimatedValue();
117 |
118 | if (isRightSide) {
119 | if (!isReverse) {
120 | value.setRectEnd(rectEdge);
121 | } else {
122 | value.setRectStart(rectEdge);
123 | }
124 |
125 | } else {
126 | if (!isReverse) {
127 | value.setRectStart(rectEdge);
128 | } else {
129 | value.setRectEnd(rectEdge);
130 | }
131 | }
132 |
133 | if (listener != null) {
134 | listener.onValueUpdated(value);
135 | }
136 | }
137 |
138 | @SuppressWarnings("RedundantIfStatement")
139 | boolean hasChanges(int coordinateStart, int coordinateEnd, int radius, boolean isRightSide) {
140 | if (this.coordinateStart != coordinateStart) {
141 | return true;
142 | }
143 |
144 | if (this.coordinateEnd != coordinateEnd) {
145 | return true;
146 | }
147 |
148 | if (this.radius != radius) {
149 | return true;
150 | }
151 |
152 | if (this.isRightSide != isRightSide) {
153 | return true;
154 | }
155 |
156 | return false;
157 | }
158 |
159 | @NonNull
160 | RectValues createRectValues(boolean isRightSide) {
161 | int fromX;
162 | int toX;
163 |
164 | int reverseFromX;
165 | int reverseToX;
166 |
167 | if (isRightSide) {
168 | fromX = coordinateStart + radius;
169 | toX = coordinateEnd + radius;
170 |
171 | reverseFromX = coordinateStart - radius;
172 | reverseToX = coordinateEnd - radius;
173 |
174 | } else {
175 | fromX = coordinateStart - radius;
176 | toX = coordinateEnd - radius;
177 |
178 | reverseFromX = coordinateStart + radius;
179 | reverseToX = coordinateEnd + radius;
180 | }
181 |
182 | return new RectValues(fromX, toX, reverseFromX, reverseToX);
183 | }
184 |
185 | class RectValues {
186 |
187 | final int fromX;
188 | final int toX;
189 |
190 | final int reverseFromX;
191 | final int reverseToX;
192 |
193 | RectValues(int fromX, int toX, int reverseFromX, int reverseToX) {
194 | this.fromX = fromX;
195 | this.toX = toX;
196 |
197 | this.reverseFromX = reverseFromX;
198 | this.reverseToX = reverseToX;
199 | }
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/DrawManager.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.support.annotation.Nullable;
6 | import android.util.AttributeSet;
7 | import android.util.Pair;
8 | import android.view.MotionEvent;
9 |
10 | import com.example.indicatorlib.views.animation.data.Value;
11 | import com.example.indicatorlib.views.draw.controller.AttributeController;
12 | import com.example.indicatorlib.views.draw.controller.DrawController;
13 | import com.example.indicatorlib.views.draw.controller.MeasureController;
14 | import com.example.indicatorlib.views.draw.data.Indicator;
15 |
16 | import android.support.annotation.NonNull;
17 |
18 | public class DrawManager {
19 |
20 | private Indicator indicator;
21 | private DrawController drawController;
22 | private MeasureController measureController;
23 | private AttributeController attributeController;
24 |
25 | public DrawManager() {
26 | this.indicator = new Indicator();
27 | this.drawController = new DrawController(indicator);
28 | this.measureController = new MeasureController();
29 | this.attributeController = new AttributeController(indicator);
30 | }
31 |
32 | @NonNull
33 | public Indicator indicator() {
34 | if (indicator == null) {
35 | indicator = new Indicator();
36 | }
37 |
38 | return indicator;
39 | }
40 |
41 | public void setClickListener(@Nullable DrawController.ClickListener listener) {
42 | drawController.setClickListener(listener);
43 | }
44 |
45 | public void touch(@Nullable MotionEvent event) {
46 | drawController.touch(event);
47 | }
48 |
49 | public void updateValue(@Nullable Value value) {
50 | drawController.updateValue(value);
51 | }
52 |
53 | public void draw(@NonNull Canvas canvas) {
54 | drawController.draw(canvas);
55 | }
56 |
57 | public Pair measureViewSize(int widthMeasureSpec, int heightMeasureSpec) {
58 | return measureController.measureViewSize(indicator, widthMeasureSpec, heightMeasureSpec);
59 | }
60 |
61 | public void initAttributes(@NonNull Context context, @Nullable AttributeSet attrs) {
62 | attributeController.init(context, attrs);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/controller/DrawController.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.controller;
2 |
3 | import android.graphics.Canvas;
4 | import android.support.annotation.Nullable;
5 | import android.view.MotionEvent;
6 |
7 | import com.example.indicatorlib.views.animation.data.Value;
8 | import com.example.indicatorlib.views.animation.type.AnimationType;
9 | import com.example.indicatorlib.views.draw.data.Indicator;
10 | import com.example.indicatorlib.views.draw.drawer.Drawer;
11 | import com.example.indicatorlib.views.utils.CoordinatesUtils;
12 |
13 | import android.support.annotation.NonNull;
14 |
15 | public class DrawController {
16 |
17 | private Value value;
18 | private Drawer drawer;
19 | private Indicator indicator;
20 | private ClickListener listener;
21 |
22 | public interface ClickListener {
23 |
24 | void onIndicatorClicked(int position);
25 | }
26 |
27 | public DrawController(@NonNull Indicator indicator) {
28 | this.indicator = indicator;
29 | this.drawer = new Drawer(indicator);
30 | }
31 |
32 | public void updateValue(@Nullable Value value) {
33 | this.value = value;
34 | }
35 |
36 | public void setClickListener(@Nullable ClickListener listener) {
37 | this.listener = listener;
38 | }
39 |
40 | public void touch(@Nullable MotionEvent event) {
41 | if (event == null) {
42 | return;
43 | }
44 |
45 | switch (event.getAction()) {
46 | case MotionEvent.ACTION_UP:
47 | onIndicatorTouched(event.getX(), event.getY());
48 | break;
49 | default:
50 | }
51 | }
52 |
53 | private void onIndicatorTouched(float x, float y) {
54 | if (listener != null) {
55 | int position = CoordinatesUtils.getPosition(indicator, x, y);
56 | if (position >= 0) {
57 | listener.onIndicatorClicked(position);
58 | }
59 | }
60 | }
61 |
62 | public void draw(@NonNull Canvas canvas) {
63 | int count = indicator.getCount();
64 |
65 | for (int position = 0; position < count; position++) {
66 | int coordinateX = CoordinatesUtils.getXCoordinate(indicator, position);
67 | int coordinateY = CoordinatesUtils.getYCoordinate(indicator, position);
68 | drawIndicator(canvas, position, coordinateX, coordinateY);
69 | }
70 | }
71 |
72 | private void drawIndicator(
73 | @NonNull Canvas canvas,
74 | int position,
75 | int coordinateX,
76 | int coordinateY) {
77 |
78 | boolean interactiveAnimation = indicator.isInteractiveAnimation();
79 | int selectedPosition = indicator.getSelectedPosition();
80 | int selectingPosition = indicator.getSelectingPosition();
81 | int lastSelectedPosition = indicator.getLastSelectedPosition();
82 |
83 | boolean selectedItem = !interactiveAnimation && (position == selectedPosition || position == lastSelectedPosition);
84 | boolean selectingItem = interactiveAnimation && (position == selectedPosition || position == selectingPosition);
85 | boolean isSelectedItem = selectedItem | selectingItem;
86 | drawer.setup(position, coordinateX, coordinateY);
87 |
88 | if (value != null && isSelectedItem) {
89 | drawWithAnimation(canvas);
90 | } else {
91 | drawer.drawBasic(canvas, isSelectedItem);
92 | }
93 | }
94 |
95 | private void drawWithAnimation(@NonNull Canvas canvas) {
96 | AnimationType animationType = indicator.getAnimationType();
97 | switch (animationType) {
98 | case NONE:
99 | drawer.drawBasic(canvas, true);
100 | break;
101 |
102 | case COLOR:
103 | drawer.drawColor(canvas, value);
104 | break;
105 |
106 | case SCALE:
107 | drawer.drawScale(canvas, value);
108 | break;
109 |
110 | case WORM:
111 | drawer.drawWorm(canvas, value);
112 | break;
113 |
114 | case SLIDE:
115 | drawer.drawSlide(canvas, value);
116 | break;
117 |
118 | case FILL:
119 | drawer.drawFill(canvas, value);
120 | break;
121 |
122 | case THIN_WORM:
123 | drawer.drawThinWorm(canvas, value);
124 | break;
125 |
126 | case DROP:
127 | drawer.drawDrop(canvas, value);
128 | break;
129 |
130 | case SWAP:
131 | drawer.drawSwap(canvas, value);
132 | break;
133 |
134 | case SCALE_DOWN:
135 | drawer.drawScaleDown(canvas, value);
136 | break;
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/controller/MeasureController.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.controller;
2 |
3 | import android.util.Pair;
4 | import android.view.View;
5 |
6 | import com.example.indicatorlib.views.animation.type.AnimationType;
7 | import com.example.indicatorlib.views.draw.data.Indicator;
8 | import com.example.indicatorlib.views.draw.data.Orientation;
9 |
10 | import android.support.annotation.NonNull;
11 |
12 | public class MeasureController {
13 |
14 | public Pair measureViewSize(@NonNull Indicator indicator, int widthMeasureSpec, int heightMeasureSpec) {
15 | int widthMode = View.MeasureSpec.getMode(widthMeasureSpec);
16 | int widthSize = View.MeasureSpec.getSize(widthMeasureSpec);
17 |
18 | int heightMode = View.MeasureSpec.getMode(heightMeasureSpec);
19 | int heightSize = View.MeasureSpec.getSize(heightMeasureSpec);
20 |
21 | int count = indicator.getCount();
22 | int radius = indicator.getRadius();
23 | int stroke = indicator.getStroke();
24 |
25 | int padding = indicator.getPadding();
26 | int paddingLeft = indicator.getPaddingLeft();
27 | int paddingTop = indicator.getPaddingTop();
28 | int paddingRight = indicator.getPaddingRight();
29 | int paddingBottom = indicator.getPaddingBottom();
30 |
31 | int circleDiameterPx = radius * 2;
32 | int desiredWidth = 0;
33 | int desiredHeight = 0;
34 |
35 | int width;
36 | int height;
37 |
38 | Orientation orientation = indicator.getOrientation();
39 | if (count != 0) {
40 | int diameterSum = circleDiameterPx * count;
41 | int strokeSum = (stroke * 2) * count;
42 |
43 | int paddingSum = padding * (count - 1);
44 | int w = diameterSum + strokeSum + paddingSum;
45 | int h = circleDiameterPx + stroke;
46 |
47 | if (orientation == Orientation.HORIZONTAL) {
48 | desiredWidth = w;
49 | desiredHeight = h;
50 |
51 | } else {
52 | desiredWidth = h;
53 | desiredHeight = w;
54 | }
55 | }
56 |
57 | if (indicator.getAnimationType() == AnimationType.DROP) {
58 | if (orientation == Orientation.HORIZONTAL) {
59 | desiredHeight *= 2;
60 | } else {
61 | desiredWidth *= 2;
62 | }
63 | }
64 |
65 | int horizontalPadding = paddingLeft + paddingRight;
66 | int verticalPadding = paddingTop + paddingBottom;
67 |
68 | if (orientation == Orientation.HORIZONTAL) {
69 | desiredWidth += horizontalPadding;
70 | desiredHeight += verticalPadding;
71 |
72 | } else {
73 | desiredWidth += horizontalPadding;
74 | desiredHeight += verticalPadding;
75 | }
76 |
77 | if (widthMode == View.MeasureSpec.EXACTLY) {
78 | width = widthSize;
79 | } else if (widthMode == View.MeasureSpec.AT_MOST) {
80 | width = Math.min(desiredWidth, widthSize);
81 | } else {
82 | width = desiredWidth;
83 | }
84 |
85 | if (heightMode == View.MeasureSpec.EXACTLY) {
86 | height = heightSize;
87 | } else if (heightMode == View.MeasureSpec.AT_MOST) {
88 | height = Math.min(desiredHeight, heightSize);
89 | } else {
90 | height = desiredHeight;
91 | }
92 |
93 | if (width < 0) {
94 | width = 0;
95 | }
96 |
97 | if (height < 0) {
98 | height = 0;
99 | }
100 |
101 | indicator.setWidth(width);
102 | indicator.setHeight(height);
103 |
104 | return new Pair<>(width, height);
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/data/Orientation.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.data;
2 |
3 | public enum Orientation {HORIZONTAL, VERTICAL}
4 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/data/PositionSavedState.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.data;
2 |
3 | import android.os.Parcel;
4 | import android.os.Parcelable;
5 | import android.view.View;
6 |
7 | public class PositionSavedState extends View.BaseSavedState {
8 |
9 | private int selectedPosition;
10 | private int selectingPosition;
11 | private int lastSelectedPosition;
12 |
13 | public PositionSavedState(Parcelable superState) {
14 | super(superState);
15 | }
16 |
17 | private PositionSavedState(Parcel in) {
18 | super(in);
19 | this.selectedPosition = in.readInt();
20 | this.selectingPosition = in.readInt();
21 | this.lastSelectedPosition = in.readInt();
22 | }
23 |
24 | public int getSelectedPosition() {
25 | return selectedPosition;
26 | }
27 |
28 | public void setSelectedPosition(int selectedPosition) {
29 | this.selectedPosition = selectedPosition;
30 | }
31 |
32 | public int getSelectingPosition() {
33 | return selectingPosition;
34 | }
35 |
36 | public void setSelectingPosition(int selectingPosition) {
37 | this.selectingPosition = selectingPosition;
38 | }
39 |
40 | public int getLastSelectedPosition() {
41 | return lastSelectedPosition;
42 | }
43 |
44 | public void setLastSelectedPosition(int lastSelectedPosition) {
45 | this.lastSelectedPosition = lastSelectedPosition;
46 | }
47 |
48 | @Override
49 | public void writeToParcel(Parcel out, int flags) {
50 | super.writeToParcel(out, flags);
51 | out.writeInt(this.selectedPosition);
52 | out.writeInt(this.selectingPosition);
53 | out.writeInt(this.lastSelectedPosition);
54 | }
55 |
56 | public static final Creator CREATOR = new Creator() {
57 | public PositionSavedState createFromParcel(Parcel in) {
58 | return new PositionSavedState(in);
59 | }
60 |
61 | public PositionSavedState[] newArray(int size) {
62 | return new PositionSavedState[size];
63 | }
64 | };
65 | }
66 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/data/RtlMode.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.data;
2 |
3 | public enum RtlMode {On, Off, Auto}
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/drawer/Drawer.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.drawer;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.example.indicatorlib.views.animation.data.Value;
7 | import com.example.indicatorlib.views.draw.data.Indicator;
8 | import com.example.indicatorlib.views.draw.drawer.type.*;
9 |
10 | import android.support.annotation.NonNull;
11 |
12 | public class Drawer {
13 |
14 | private BasicDrawer basicDrawer;
15 | private ColorDrawer colorDrawer;
16 | private ScaleDrawer scaleDrawer;
17 | private WormDrawer wormDrawer;
18 | private SlideDrawer slideDrawer;
19 | private FillDrawer fillDrawer;
20 | private ThinWormDrawer thinWormDrawer;
21 | private DropDrawer dropDrawer;
22 | private SwapDrawer swapDrawer;
23 | private ScaleDownDrawer scaleDownDrawer;
24 |
25 | private int position;
26 | private int coordinateX;
27 | private int coordinateY;
28 |
29 | public Drawer(@NonNull Indicator indicator) {
30 | Paint paint = new Paint();
31 | paint.setStyle(Paint.Style.FILL);
32 | paint.setAntiAlias(true);
33 |
34 | basicDrawer = new BasicDrawer(paint, indicator);
35 | colorDrawer = new ColorDrawer(paint, indicator);
36 | scaleDrawer = new ScaleDrawer(paint, indicator);
37 | wormDrawer = new WormDrawer(paint, indicator);
38 | slideDrawer = new SlideDrawer(paint, indicator);
39 | fillDrawer = new FillDrawer(paint, indicator);
40 | thinWormDrawer = new ThinWormDrawer(paint, indicator);
41 | dropDrawer = new DropDrawer(paint, indicator);
42 | swapDrawer = new SwapDrawer(paint, indicator);
43 | scaleDownDrawer = new ScaleDownDrawer(paint, indicator);
44 | }
45 |
46 | public void setup(int position, int coordinateX, int coordinateY) {
47 | this.position = position;
48 | this.coordinateX = coordinateX;
49 | this.coordinateY = coordinateY;
50 | }
51 |
52 | public void drawBasic(@NonNull Canvas canvas, boolean isSelectedItem) {
53 | if (colorDrawer != null) {
54 | basicDrawer.draw(canvas, position, isSelectedItem, coordinateX, coordinateY);
55 | }
56 | }
57 |
58 | public void drawColor(@NonNull Canvas canvas, @NonNull Value value) {
59 | if (colorDrawer != null) {
60 | colorDrawer.draw(canvas, value, position, coordinateX, coordinateY);
61 | }
62 | }
63 |
64 | public void drawScale(@NonNull Canvas canvas, @NonNull Value value) {
65 | if (scaleDrawer != null) {
66 | scaleDrawer.draw(canvas, value, position, coordinateX, coordinateY);
67 | }
68 | }
69 |
70 | public void drawWorm(@NonNull Canvas canvas, @NonNull Value value) {
71 | if (wormDrawer != null) {
72 | wormDrawer.draw(canvas, value, coordinateX, coordinateY);
73 | }
74 | }
75 |
76 | public void drawSlide(@NonNull Canvas canvas, @NonNull Value value) {
77 | if (slideDrawer != null) {
78 | slideDrawer.draw(canvas, value, coordinateX, coordinateY);
79 | }
80 | }
81 |
82 | public void drawFill(@NonNull Canvas canvas, @NonNull Value value) {
83 | if (fillDrawer != null) {
84 | fillDrawer.draw(canvas, value, position, coordinateX, coordinateY);
85 | }
86 | }
87 |
88 | public void drawThinWorm(@NonNull Canvas canvas, @NonNull Value value) {
89 | if (thinWormDrawer != null) {
90 | thinWormDrawer.draw(canvas, value, coordinateX, coordinateY);
91 | }
92 | }
93 |
94 | public void drawDrop(@NonNull Canvas canvas, @NonNull Value value) {
95 | if (dropDrawer != null) {
96 | dropDrawer.draw(canvas, value, coordinateX, coordinateY);
97 | }
98 | }
99 |
100 | public void drawSwap(@NonNull Canvas canvas, @NonNull Value value) {
101 | if (swapDrawer != null) {
102 | swapDrawer.draw(canvas, value, position, coordinateX, coordinateY);
103 | }
104 | }
105 |
106 | public void drawScaleDown(@NonNull Canvas canvas, @NonNull Value value) {
107 | if (scaleDownDrawer != null) {
108 | scaleDownDrawer.draw(canvas, value, position, coordinateX, coordinateY);
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/drawer/type/BaseDrawer.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.drawer.type;
2 |
3 | import android.graphics.Paint;
4 |
5 | import com.example.indicatorlib.views.draw.data.Indicator;
6 |
7 | import android.support.annotation.NonNull;
8 |
9 | class BaseDrawer {
10 |
11 | Paint paint;
12 | Indicator indicator;
13 |
14 | BaseDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
15 | this.paint = paint;
16 | this.indicator = indicator;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/drawer/type/BasicDrawer.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.example.indicatorlib.views.animation.type.AnimationType;
7 | import com.example.indicatorlib.views.draw.data.Indicator;
8 |
9 | import android.support.annotation.NonNull;
10 |
11 | public class BasicDrawer extends BaseDrawer {
12 |
13 | private Paint strokePaint;
14 |
15 | public BasicDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
16 | super(paint, indicator);
17 |
18 | strokePaint = new Paint();
19 | strokePaint.setStyle(Paint.Style.STROKE);
20 | strokePaint.setAntiAlias(true);
21 | strokePaint.setStrokeWidth(indicator.getStroke());
22 | }
23 |
24 | public void draw(
25 | @NonNull Canvas canvas,
26 | int position,
27 | boolean isSelectedItem,
28 | int coordinateX,
29 | int coordinateY) {
30 |
31 | float radius = indicator.getRadius();
32 | int strokePx = indicator.getStroke();
33 | float scaleFactor = indicator.getScaleFactor();
34 |
35 | int selectedColor = indicator.getSelectedColor();
36 | int unselectedColor = indicator.getUnselectedColor();
37 | int selectedPosition = indicator.getSelectedPosition();
38 | AnimationType animationType = indicator.getAnimationType();
39 |
40 | if (animationType == AnimationType.SCALE && !isSelectedItem) {
41 | radius *= scaleFactor;
42 |
43 | } else if (animationType == AnimationType.SCALE_DOWN && isSelectedItem) {
44 | radius *= scaleFactor;
45 | }
46 |
47 | int color = unselectedColor;
48 | if (position == selectedPosition) {
49 | color = selectedColor;
50 | }
51 |
52 | Paint paint;
53 | if (animationType == AnimationType.FILL && position != selectedPosition) {
54 | paint = strokePaint;
55 | paint.setStrokeWidth(strokePx);
56 | } else {
57 | paint = this.paint;
58 | }
59 |
60 | paint.setColor(color);
61 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/drawer/type/ColorDrawer.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.example.indicatorlib.views.animation.data.Value;
7 | import com.example.indicatorlib.views.animation.data.type.ColorAnimationValue;
8 | import com.example.indicatorlib.views.draw.data.Indicator;
9 |
10 | import android.support.annotation.NonNull;
11 |
12 | public class ColorDrawer extends BaseDrawer {
13 |
14 | public ColorDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
15 | super(paint, indicator);
16 | }
17 |
18 | public void draw(@NonNull Canvas canvas,
19 | @NonNull Value value,
20 | int position,
21 | int coordinateX,
22 | int coordinateY) {
23 |
24 | if (!(value instanceof ColorAnimationValue)) {
25 | return;
26 | }
27 |
28 | ColorAnimationValue v = (ColorAnimationValue) value;
29 | float radius = indicator.getRadius();
30 | int color = indicator.getSelectedColor();
31 |
32 | int selectedPosition = indicator.getSelectedPosition();
33 | int selectingPosition = indicator.getSelectingPosition();
34 | int lastSelectedPosition = indicator.getLastSelectedPosition();
35 |
36 | if (indicator.isInteractiveAnimation()) {
37 | if (position == selectingPosition) {
38 | color = v.getColor();
39 |
40 | } else if (position == selectedPosition) {
41 | color = v.getColorReverse();
42 | }
43 |
44 | } else {
45 | if (position == selectedPosition) {
46 | color = v.getColor();
47 |
48 | } else if (position == lastSelectedPosition) {
49 | color = v.getColorReverse();
50 | }
51 | }
52 |
53 | paint.setColor(color);
54 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/drawer/type/DropDrawer.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.example.indicatorlib.views.animation.data.Value;
7 | import com.example.indicatorlib.views.animation.data.type.DropAnimationValue;
8 | import com.example.indicatorlib.views.draw.data.Indicator;
9 | import com.example.indicatorlib.views.draw.data.Orientation;
10 |
11 | import android.support.annotation.NonNull;
12 |
13 | public class DropDrawer extends BaseDrawer {
14 |
15 | public DropDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
16 | super(paint, indicator);
17 | }
18 |
19 | public void draw(
20 | @NonNull Canvas canvas,
21 | @NonNull Value value,
22 | int coordinateX,
23 | int coordinateY) {
24 |
25 | if (!(value instanceof DropAnimationValue)) {
26 | return;
27 | }
28 |
29 | DropAnimationValue v = (DropAnimationValue) value;
30 | int unselectedColor = indicator.getUnselectedColor();
31 | int selectedColor = indicator.getSelectedColor();
32 | float radius = indicator.getRadius();
33 |
34 | paint.setColor(unselectedColor);
35 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
36 |
37 | paint.setColor(selectedColor);
38 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
39 | canvas.drawCircle(v.getWidth(), v.getHeight(), v.getRadius(), paint);
40 | } else {
41 | canvas.drawCircle(v.getHeight(), v.getWidth(), v.getRadius(), paint);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/drawer/type/FillDrawer.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.example.indicatorlib.views.animation.data.Value;
7 | import com.example.indicatorlib.views.animation.data.type.FillAnimationValue;
8 | import com.example.indicatorlib.views.draw.data.Indicator;
9 |
10 | import android.support.annotation.NonNull;
11 |
12 | public class FillDrawer extends BaseDrawer {
13 |
14 | private Paint strokePaint;
15 |
16 | public FillDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
17 | super(paint, indicator);
18 |
19 | strokePaint = new Paint();
20 | strokePaint.setStyle(Paint.Style.STROKE);
21 | strokePaint.setAntiAlias(true);
22 | }
23 |
24 | public void draw(
25 | @NonNull Canvas canvas,
26 | @NonNull Value value,
27 | int position,
28 | int coordinateX,
29 | int coordinateY) {
30 |
31 | if (!(value instanceof FillAnimationValue)) {
32 | return;
33 | }
34 |
35 | FillAnimationValue v = (FillAnimationValue) value;
36 | int color = indicator.getUnselectedColor();
37 | float radius = indicator.getRadius();
38 | int stroke = indicator.getStroke();
39 |
40 | int selectedPosition = indicator.getSelectedPosition();
41 | int selectingPosition = indicator.getSelectingPosition();
42 | int lastSelectedPosition = indicator.getLastSelectedPosition();
43 |
44 | if (indicator.isInteractiveAnimation()) {
45 | if (position == selectingPosition) {
46 | color = v.getColor();
47 | radius = v.getRadius();
48 | stroke = v.getStroke();
49 |
50 | } else if (position == selectedPosition) {
51 | color = v.getColorReverse();
52 | radius = v.getRadiusReverse();
53 | stroke = v.getStrokeReverse();
54 | }
55 |
56 | } else {
57 | if (position == selectedPosition) {
58 | color = v.getColor();
59 | radius = v.getRadius();
60 | stroke = v.getStroke();
61 |
62 | } else if (position == lastSelectedPosition) {
63 | color = v.getColorReverse();
64 | radius = v.getRadiusReverse();
65 | stroke = v.getStrokeReverse();
66 | }
67 | }
68 |
69 | strokePaint.setColor(color);
70 | strokePaint.setStrokeWidth(indicator.getStroke());
71 | canvas.drawCircle(coordinateX, coordinateY, indicator.getRadius(), strokePaint);
72 |
73 | strokePaint.setStrokeWidth(stroke);
74 | canvas.drawCircle(coordinateX, coordinateY, radius, strokePaint);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/drawer/type/ScaleDownDrawer.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.example.indicatorlib.views.animation.data.Value;
7 | import com.example.indicatorlib.views.animation.data.type.ScaleAnimationValue;
8 | import com.example.indicatorlib.views.draw.data.Indicator;
9 |
10 | import android.support.annotation.NonNull;
11 |
12 | public class ScaleDownDrawer extends BaseDrawer {
13 |
14 | public ScaleDownDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
15 | super(paint, indicator);
16 | }
17 |
18 | public void draw(
19 | @NonNull Canvas canvas,
20 | @NonNull Value value,
21 | int position,
22 | int coordinateX,
23 | int coordinateY) {
24 |
25 | if (!(value instanceof ScaleAnimationValue)) {
26 | return;
27 | }
28 |
29 | ScaleAnimationValue v = (ScaleAnimationValue) value;
30 | float radius = indicator.getRadius();
31 | int color = indicator.getSelectedColor();
32 |
33 | int selectedPosition = indicator.getSelectedPosition();
34 | int selectingPosition = indicator.getSelectingPosition();
35 | int lastSelectedPosition = indicator.getLastSelectedPosition();
36 |
37 | if (indicator.isInteractiveAnimation()) {
38 | if (position == selectingPosition) {
39 | radius = v.getRadius();
40 | color = v.getColor();
41 |
42 | } else if (position == selectedPosition) {
43 | radius = v.getRadiusReverse();
44 | color = v.getColorReverse();
45 | }
46 |
47 | } else {
48 | if (position == selectedPosition) {
49 | radius = v.getRadius();
50 | color = v.getColor();
51 |
52 | } else if (position == lastSelectedPosition) {
53 | radius = v.getRadiusReverse();
54 | color = v.getColorReverse();
55 | }
56 | }
57 |
58 | paint.setColor(color);
59 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/drawer/type/ScaleDrawer.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.example.indicatorlib.views.animation.data.Value;
7 | import com.example.indicatorlib.views.animation.data.type.ScaleAnimationValue;
8 | import com.example.indicatorlib.views.draw.data.Indicator;
9 |
10 | import android.support.annotation.NonNull;
11 |
12 | public class ScaleDrawer extends BaseDrawer {
13 |
14 | public ScaleDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
15 | super(paint, indicator);
16 | }
17 |
18 | public void draw(
19 | @NonNull Canvas canvas,
20 | @NonNull Value value,
21 | int position,
22 | int coordinateX,
23 | int coordinateY) {
24 |
25 | if (!(value instanceof ScaleAnimationValue)) {
26 | return;
27 | }
28 |
29 | ScaleAnimationValue v = (ScaleAnimationValue) value;
30 | float radius = indicator.getRadius();
31 | int color = indicator.getSelectedColor();
32 |
33 | int selectedPosition = indicator.getSelectedPosition();
34 | int selectingPosition = indicator.getSelectingPosition();
35 | int lastSelectedPosition = indicator.getLastSelectedPosition();
36 |
37 | if (indicator.isInteractiveAnimation()) {
38 | if (position == selectingPosition) {
39 | radius = v.getRadius();
40 | color = v.getColor();
41 |
42 | } else if (position == selectedPosition) {
43 | radius = v.getRadiusReverse();
44 | color = v.getColorReverse();
45 | }
46 |
47 | } else {
48 | if (position == selectedPosition) {
49 | radius = v.getRadius();
50 | color = v.getColor();
51 |
52 | } else if (position == lastSelectedPosition) {
53 | radius = v.getRadiusReverse();
54 | color = v.getColorReverse();
55 | }
56 | }
57 |
58 | paint.setColor(color);
59 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/drawer/type/SlideDrawer.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.example.indicatorlib.views.animation.data.Value;
7 | import com.example.indicatorlib.views.animation.data.type.SlideAnimationValue;
8 | import com.example.indicatorlib.views.draw.data.Indicator;
9 | import com.example.indicatorlib.views.draw.data.Orientation;
10 |
11 | import android.support.annotation.NonNull;
12 |
13 | public class SlideDrawer extends BaseDrawer {
14 |
15 | public SlideDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
16 | super(paint, indicator);
17 | }
18 |
19 | public void draw(
20 | @NonNull Canvas canvas,
21 | @NonNull Value value,
22 | int coordinateX,
23 | int coordinateY) {
24 |
25 | if (!(value instanceof SlideAnimationValue)) {
26 | return;
27 | }
28 |
29 | SlideAnimationValue v = (SlideAnimationValue) value;
30 | int coordinate = v.getCoordinate();
31 | int unselectedColor = indicator.getUnselectedColor();
32 | int selectedColor = indicator.getSelectedColor();
33 | int radius = indicator.getRadius();
34 |
35 | paint.setColor(unselectedColor);
36 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
37 |
38 | paint.setColor(selectedColor);
39 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
40 | canvas.drawCircle(coordinate, coordinateY, radius, paint);
41 | } else {
42 | canvas.drawCircle(coordinateX, coordinate, radius, paint);
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/drawer/type/SwapDrawer.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.example.indicatorlib.views.animation.data.Value;
7 | import com.example.indicatorlib.views.animation.data.type.SwapAnimationValue;
8 | import com.example.indicatorlib.views.draw.data.Indicator;
9 | import com.example.indicatorlib.views.draw.data.Orientation;
10 |
11 | import android.support.annotation.NonNull;
12 |
13 | public class SwapDrawer extends BaseDrawer {
14 |
15 | public SwapDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
16 | super(paint, indicator);
17 | }
18 |
19 | public void draw(
20 | @NonNull Canvas canvas,
21 | @NonNull Value value,
22 | int position,
23 | int coordinateX,
24 | int coordinateY) {
25 |
26 | if (!(value instanceof SwapAnimationValue)) {
27 | return;
28 | }
29 |
30 | SwapAnimationValue v = (SwapAnimationValue) value;
31 | int selectedColor = indicator.getSelectedColor();
32 | int unselectedColor = indicator.getUnselectedColor();
33 | int radius = indicator.getRadius();
34 |
35 | int selectedPosition = indicator.getSelectedPosition();
36 | int selectingPosition = indicator.getSelectingPosition();
37 | int lastSelectedPosition = indicator.getLastSelectedPosition();
38 |
39 | int coordinate = v.getCoordinate();
40 | int color = unselectedColor;
41 |
42 | if (indicator.isInteractiveAnimation()) {
43 | if (position == selectingPosition) {
44 | coordinate = v.getCoordinate();
45 | color = selectedColor;
46 |
47 | } else if (position == selectedPosition) {
48 | coordinate = v.getCoordinateReverse();
49 | color = unselectedColor;
50 | }
51 |
52 | } else {
53 | if (position == lastSelectedPosition) {
54 | coordinate = v.getCoordinate();
55 | color = selectedColor;
56 |
57 | } else if (position == selectedPosition) {
58 | coordinate = v.getCoordinateReverse();
59 | color = unselectedColor;
60 | }
61 | }
62 |
63 | paint.setColor(color);
64 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
65 | canvas.drawCircle(coordinate, coordinateY, radius, paint);
66 | } else {
67 | canvas.drawCircle(coordinateX, coordinate, radius, paint);
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/drawer/type/ThinWormDrawer.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 |
6 | import com.example.indicatorlib.views.animation.data.Value;
7 | import com.example.indicatorlib.views.animation.data.type.ThinWormAnimationValue;
8 | import com.example.indicatorlib.views.draw.data.Indicator;
9 | import com.example.indicatorlib.views.draw.data.Orientation;
10 |
11 | import android.support.annotation.NonNull;
12 |
13 | public class ThinWormDrawer extends WormDrawer {
14 |
15 | public ThinWormDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
16 | super(paint, indicator);
17 | }
18 |
19 | public void draw(
20 | @NonNull Canvas canvas,
21 | @NonNull Value value,
22 | int coordinateX,
23 | int coordinateY) {
24 |
25 | if (!(value instanceof ThinWormAnimationValue)) {
26 | return;
27 | }
28 |
29 | ThinWormAnimationValue v = (ThinWormAnimationValue) value;
30 | int rectStart = v.getRectStart();
31 | int rectEnd = v.getRectEnd();
32 | int height = v.getHeight() / 2;
33 |
34 | int radius = indicator.getRadius();
35 | int unselectedColor = indicator.getUnselectedColor();
36 | int selectedColor = indicator.getSelectedColor();
37 |
38 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
39 | rect.left = rectStart;
40 | rect.right = rectEnd;
41 | rect.top = coordinateY - height;
42 | rect.bottom = coordinateY + height;
43 |
44 | } else {
45 | rect.left = coordinateX - height;
46 | rect.right = coordinateX + height;
47 | rect.top = rectStart;
48 | rect.bottom = rectEnd;
49 | }
50 |
51 | paint.setColor(unselectedColor);
52 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
53 |
54 | paint.setColor(selectedColor);
55 | canvas.drawRoundRect(rect, radius, radius, paint);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/draw/drawer/type/WormDrawer.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import android.graphics.RectF;
6 |
7 | import com.example.indicatorlib.views.animation.data.Value;
8 | import com.example.indicatorlib.views.animation.data.type.WormAnimationValue;
9 | import com.example.indicatorlib.views.draw.data.Indicator;
10 | import com.example.indicatorlib.views.draw.data.Orientation;
11 |
12 | import android.support.annotation.NonNull;
13 |
14 | public class WormDrawer extends BaseDrawer {
15 |
16 | public RectF rect;
17 |
18 | public WormDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
19 | super(paint, indicator);
20 | rect = new RectF();
21 | }
22 |
23 | public void draw(
24 | @NonNull Canvas canvas,
25 | @NonNull Value value,
26 | int coordinateX,
27 | int coordinateY) {
28 |
29 | if (!(value instanceof WormAnimationValue)) {
30 | return;
31 | }
32 |
33 | WormAnimationValue v = (WormAnimationValue) value;
34 | int rectStart = v.getRectStart();
35 | int rectEnd = v.getRectEnd();
36 |
37 | int radius = indicator.getRadius();
38 | int unselectedColor = indicator.getUnselectedColor();
39 | int selectedColor = indicator.getSelectedColor();
40 |
41 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
42 | rect.left = rectStart;
43 | rect.right = rectEnd;
44 | rect.top = coordinateY - radius;
45 | rect.bottom = coordinateY + radius;
46 |
47 | } else {
48 | rect.left = coordinateX - radius;
49 | rect.right = coordinateX + radius;
50 | rect.top = rectStart;
51 | rect.bottom = rectEnd;
52 | }
53 |
54 | paint.setColor(unselectedColor);
55 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
56 |
57 | paint.setColor(selectedColor);
58 | canvas.drawRoundRect(rect, radius, radius, paint);
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/utils/CoordinatesUtils.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.utils;
2 |
3 | import android.support.annotation.Nullable;
4 | import android.util.Pair;
5 |
6 | import com.example.indicatorlib.views.animation.type.AnimationType;
7 | import com.example.indicatorlib.views.draw.data.Indicator;
8 | import com.example.indicatorlib.views.draw.data.Orientation;
9 |
10 | import android.support.annotation.NonNull;
11 | import android.support.annotation.NonNull;
12 |
13 | public class CoordinatesUtils {
14 |
15 | @SuppressWarnings("UnnecessaryLocalVariable")
16 | public static int getCoordinate(@Nullable Indicator indicator, int position) {
17 | if (indicator == null) {
18 | return 0;
19 | }
20 |
21 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
22 | return getXCoordinate(indicator, position);
23 | } else {
24 | return getYCoordinate(indicator, position);
25 | }
26 | }
27 |
28 | @SuppressWarnings("UnnecessaryLocalVariable")
29 | public static int getXCoordinate(@Nullable Indicator indicator, int position) {
30 | if (indicator == null) {
31 | return 0;
32 | }
33 |
34 | int coordinate;
35 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
36 | coordinate = getHorizontalCoordinate(indicator, position);
37 | } else {
38 | coordinate = getVerticalCoordinate(indicator);
39 | }
40 |
41 | coordinate += indicator.getPaddingLeft();
42 | return coordinate;
43 | }
44 |
45 | public static int getYCoordinate(@Nullable Indicator indicator, int position) {
46 | if (indicator == null) {
47 | return 0;
48 | }
49 |
50 | int coordinate;
51 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
52 | coordinate = getVerticalCoordinate(indicator);
53 | } else {
54 | coordinate = getHorizontalCoordinate(indicator, position);
55 | }
56 |
57 | coordinate += indicator.getPaddingTop();
58 | return coordinate;
59 | }
60 |
61 | @SuppressWarnings("SuspiciousNameCombination")
62 | public static int getPosition(@Nullable Indicator indicator, float x, float y) {
63 | if (indicator == null) {
64 | return -1;
65 | }
66 |
67 | float lengthCoordinate;
68 | float heightCoordinate;
69 |
70 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
71 | lengthCoordinate = x;
72 | heightCoordinate = y;
73 | } else {
74 | lengthCoordinate = y;
75 | heightCoordinate = x;
76 | }
77 |
78 | return getFitPosition(indicator, lengthCoordinate, heightCoordinate);
79 | }
80 |
81 | private static int getFitPosition(@NonNull Indicator indicator, float lengthCoordinate, float heightCoordinate) {
82 | int count = indicator.getCount();
83 | int radius = indicator.getRadius();
84 | int stroke = indicator.getStroke();
85 | int padding = indicator.getPadding();
86 |
87 | int height = indicator.getOrientation() == Orientation.HORIZONTAL ? indicator.getHeight() : indicator.getWidth();
88 | int length = 0;
89 |
90 | for (int i = 0; i < count; i++) {
91 | int indicatorPadding = i > 0 ? padding : padding / 2;
92 | int startValue = length;
93 |
94 | length += radius * 2 + (stroke / 2) + indicatorPadding;
95 | int endValue = length;
96 |
97 | boolean fitLength = lengthCoordinate >= startValue && lengthCoordinate <= endValue;
98 | boolean fitHeight = heightCoordinate >= 0 && heightCoordinate <= height;
99 |
100 | if (fitLength && fitHeight) {
101 | return i;
102 | }
103 | }
104 |
105 | return -1;
106 | }
107 |
108 | private static int getHorizontalCoordinate(@NonNull Indicator indicator, int position) {
109 | int count = indicator.getCount();
110 | int radius = indicator.getRadius();
111 | int stroke = indicator.getStroke();
112 | int padding = indicator.getPadding();
113 |
114 | int coordinate = 0;
115 | for (int i = 0; i < count; i++) {
116 | coordinate += radius + (stroke / 2);
117 |
118 | if (position == i) {
119 | return coordinate;
120 | }
121 |
122 | coordinate += radius + padding + (stroke / 2);
123 | }
124 |
125 | if (indicator.getAnimationType() == AnimationType.DROP) {
126 | coordinate += radius * 2;
127 | }
128 |
129 | return coordinate;
130 | }
131 |
132 | private static int getVerticalCoordinate(@NonNull Indicator indicator) {
133 | int radius = indicator.getRadius();
134 | int coordinate;
135 |
136 | if (indicator.getAnimationType() == AnimationType.DROP) {
137 | coordinate = radius * 3;
138 | } else {
139 | coordinate = radius;
140 | }
141 |
142 | return coordinate;
143 | }
144 |
145 | public static Pair getProgress(@NonNull Indicator indicator, int position, float positionOffset, boolean isRtl) {
146 | int count = indicator.getCount();
147 | int selectedPosition = indicator.getSelectedPosition();
148 |
149 | if (isRtl) {
150 | position = (count - 1) - position;
151 | }
152 |
153 | if (position < 0) {
154 | position = 0;
155 |
156 | } else if (position > count - 1) {
157 | position = count - 1;
158 | }
159 |
160 | boolean isRightOverScrolled = position > selectedPosition;
161 | boolean isLeftOverScrolled;
162 |
163 | if (isRtl) {
164 | isLeftOverScrolled = position - 1 < selectedPosition;
165 | } else {
166 | isLeftOverScrolled = position + 1 < selectedPosition;
167 | }
168 |
169 | if (isRightOverScrolled || isLeftOverScrolled) {
170 | selectedPosition = position;
171 | indicator.setSelectedPosition(selectedPosition);
172 | }
173 |
174 | boolean slideToRightSide = selectedPosition == position && positionOffset != 0;
175 | int selectingPosition;
176 | float selectingProgress;
177 |
178 | if (slideToRightSide) {
179 | selectingPosition = isRtl ? position - 1 : position + 1;
180 | selectingProgress = positionOffset;
181 |
182 | } else {
183 | selectingPosition = position;
184 | selectingProgress = 1 - positionOffset;
185 | }
186 |
187 | if (selectingProgress > 1) {
188 | selectingProgress = 1;
189 |
190 | } else if (selectingProgress < 0) {
191 | selectingProgress = 0;
192 | }
193 |
194 | return new Pair<>(selectingPosition, selectingProgress);
195 | }
196 | }
197 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/utils/DensityUtils.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.utils;
2 |
3 | import android.content.res.Resources;
4 | import android.util.TypedValue;
5 |
6 | public class DensityUtils {
7 |
8 | public static int dpToPx(int dp) {
9 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().getDisplayMetrics());
10 | }
11 |
12 | public static int pxToDp(float px) {
13 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px, Resources.getSystem().getDisplayMetrics());
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/java/com/example/indicatorlib/views/utils/IdUtils.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib.views.utils;
2 |
3 | import android.os.Build;
4 | import android.view.View;
5 |
6 | import java.util.concurrent.atomic.AtomicInteger;
7 |
8 | public class IdUtils {
9 |
10 | private static final AtomicInteger nextGeneratedId = new AtomicInteger(1);
11 |
12 | public static int generateViewId(){
13 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
14 | return generateId();
15 | } else {
16 | return View.generateViewId();
17 | }
18 | }
19 |
20 | /**
21 | * Generate a value suitable for use in #setId(int).
22 | * This value will not collide with ID values generated at build time by aapt for R.id.
23 | *
24 | * @return a generated ID value
25 | */
26 | private static int generateId() {
27 | for (; ; ) {
28 | final int result = nextGeneratedId.get();
29 | // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
30 | int newValue = result + 1;
31 | if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
32 | if (nextGeneratedId.compareAndSet(result, newValue)) {
33 | return result;
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 | #f1f2f7
7 | #FFFFFF
8 | #f4f4f4
9 | #7082a8
10 | #453d3b
11 | #e2211c
12 | #ffeeee
13 | #fd6853
14 | #eb2d4d
15 | #e2211c
16 | #fe6b55
17 | #c25c59
18 | #ff2d55
19 | #341b1c
20 | #433f3d
21 | #999999
22 | #996d13
23 |
24 | #4cd964
25 | #221815
26 | #8d8887
27 | #474747
28 | #555555
29 | #7fffffff
30 | #f1f2f7
31 | #f1f2f7
32 | #ffe8e4
33 | #f8f8f9
34 | #b2b2b2
35 | #dedddc
36 | #555555
37 | #fee94e
38 |
39 | #a3000000
40 | #19000000
41 | #99000000
42 |
43 | #aa72d572
44 | #aa738ffe
45 | #aae84e40
46 | #00000000
47 | #25808080
48 | #f5f5f5
49 | #e64340
50 |
51 | #333333
52 | #59B29C
53 | #333333
54 | #FFFFFF
55 | #00ffffff
56 |
57 | #D0382B
58 | #B4B4B4
59 | #e53732
60 |
61 | #ffcf00
62 |
63 |
64 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 9sp
6 | 10sp
7 | 11sp
8 | 12sp
9 | 13sp
10 | 14sp
11 | 15sp
12 | 16sp
13 | 17sp
14 | 18sp
15 | 19sp
16 | 20sp
17 | 22sp
18 | 30sp
19 |
20 | 1dp
21 | 2dp
22 | 3dp
23 | 4dp
24 | 5dp
25 | 6dp
26 | 7dp
27 | 8dp
28 | 9dp
29 | 10dp
30 | 11dp
31 | 12dp
32 | 13dp
33 | 14dp
34 | 15dp
35 | 16dp
36 | 19dp
37 | 20dp
38 | 25dp
39 | 30dp
40 | 35dp
41 | 36dp
42 | 40dp
43 | 45dp
44 | 49dp
45 | 50dp
46 | 52dp
47 | 55dp
48 | 60dp
49 | 64dp
50 |
51 | 16sp
52 | 14sp
53 | 13sp
54 | 3dp
55 | 5dp
56 | 7dp
57 | 9dp
58 | 18dp
59 | 24dp
60 | 40dp
61 | 44dp
62 | 50dp
63 | 16dp
64 | 8dp
65 | 10dp
66 | 12dp
67 | 13dp
68 | 14dp
69 | 15dp
70 | 16dp
71 | 17dp
72 | 18dp
73 | 20dp
74 | 25dp
75 |
76 |
--------------------------------------------------------------------------------
/indicatorlib/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | IndicatorLib
3 |
4 |
--------------------------------------------------------------------------------
/indicatorlib/src/test/java/com/example/indicatorlib/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.example.indicatorlib;
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 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':indicatorlib'
2 |
--------------------------------------------------------------------------------