├── .gitignore
├── README.md
├── assets
├── anim_color.gif
├── anim_drop.gif
├── anim_fill.gif
├── anim_none.gif
├── anim_scale.gif
├── anim_slide.gif
├── anim_swap.gif
├── anim_thin_worm.gif
├── anim_worm.gif
├── animation_worm.gif
├── attributes.gif
└── preview_anim_drop.gif
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── pageindicatorview
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── rd
│ │ ├── IndicatorManager.java
│ │ ├── PageIndicatorView.java
│ │ ├── animation
│ │ ├── AnimationManager.java
│ │ ├── controller
│ │ │ ├── AnimationController.java
│ │ │ └── ValueController.java
│ │ ├── data
│ │ │ ├── AnimationValue.java
│ │ │ ├── Value.java
│ │ │ └── type
│ │ │ │ ├── ColorAnimationValue.java
│ │ │ │ ├── DropAnimationValue.java
│ │ │ │ ├── FillAnimationValue.java
│ │ │ │ ├── ScaleAnimationValue.java
│ │ │ │ ├── SlideAnimationValue.java
│ │ │ │ ├── SwapAnimationValue.java
│ │ │ │ ├── ThinWormAnimationValue.java
│ │ │ │ └── WormAnimationValue.java
│ │ └── type
│ │ │ ├── AnimationType.java
│ │ │ ├── BaseAnimation.java
│ │ │ ├── ColorAnimation.java
│ │ │ ├── DropAnimation.java
│ │ │ ├── FillAnimation.java
│ │ │ ├── ScaleAnimation.java
│ │ │ ├── ScaleDownAnimation.java
│ │ │ ├── SlideAnimation.java
│ │ │ ├── SwapAnimation.java
│ │ │ ├── ThinWormAnimation.java
│ │ │ └── WormAnimation.java
│ │ ├── draw
│ │ ├── DrawManager.java
│ │ ├── controller
│ │ │ ├── AttributeController.java
│ │ │ ├── DrawController.java
│ │ │ └── MeasureController.java
│ │ ├── data
│ │ │ ├── Indicator.java
│ │ │ ├── Orientation.java
│ │ │ ├── PositionSavedState.java
│ │ │ └── RtlMode.java
│ │ └── drawer
│ │ │ ├── Drawer.java
│ │ │ └── type
│ │ │ ├── BaseDrawer.java
│ │ │ ├── BasicDrawer.java
│ │ │ ├── ColorDrawer.java
│ │ │ ├── DropDrawer.java
│ │ │ ├── FillDrawer.java
│ │ │ ├── ScaleDownDrawer.java
│ │ │ ├── ScaleDrawer.java
│ │ │ ├── SlideDrawer.java
│ │ │ ├── SwapDrawer.java
│ │ │ ├── ThinWormDrawer.java
│ │ │ └── WormDrawer.java
│ │ └── utils
│ │ ├── CoordinatesUtils.java
│ │ ├── DensityUtils.java
│ │ └── IdUtils.java
│ └── res
│ └── values
│ └── attrs.xml
├── sample
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── rd
│ │ └── pageindicatorview
│ │ ├── base
│ │ └── BaseActivity.java
│ │ ├── customize
│ │ └── CustomizeActivity.java
│ │ ├── data
│ │ ├── Customization.java
│ │ └── CustomizationConverter.java
│ │ └── home
│ │ ├── HomeActivity.java
│ │ └── HomeAdapter.java
│ └── res
│ ├── drawable-v21
│ └── selector_black_10_transparent.xml
│ ├── drawable
│ └── selector_black_10_transparent.xml
│ ├── layout
│ ├── ac_customize.xml
│ ├── ac_home.xml
│ ├── item_spinner_drop_down.xml
│ └── item_spinner_selected.xml
│ ├── menu
│ └── menu_customize.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxxhdpi
│ └── ic_launcher.png
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Android ###
2 | # Built application files
3 | *.apk
4 | *.ap_
5 |
6 | # Files for the Dalvik VM
7 | *.dex
8 |
9 | # Java class files
10 | *.class
11 |
12 | # Generated files
13 | bin/
14 | gen/
15 |
16 | # Gradle files
17 | .gradle/
18 | build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 | # Android Studio Navigation editor temp files
30 | .navigation/
31 |
32 | ### Android Patch ###
33 | gen-external-apklibs
34 |
35 |
36 | ### Intellij ###
37 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
38 |
39 | *.iml
40 |
41 | ## Directory-based project format:
42 | .idea/
43 | # if you remove the above rule, at least ignore the following:
44 |
45 | # User-specific stuff:
46 | # .idea/workspace.xml
47 | # .idea/tasks.xml
48 | # .idea/dictionaries
49 |
50 | # Sensitive or high-churn files:
51 | # .idea/dataSources.ids
52 | # .idea/dataSources.xml
53 | # .idea/sqlDataSources.xml
54 | # .idea/dynamic.xml
55 | # .idea/uiDesigner.xml
56 |
57 | # Gradle:
58 | # .idea/gradle.xml
59 | # .idea/libraries
60 |
61 | # Mongo Explorer plugin:
62 | # .idea/mongoSettings.xml
63 |
64 | ## File-based project format:
65 | *.ipr
66 | *.iws
67 |
68 | ## Plugin-specific files:
69 |
70 | # IntelliJ
71 | /out/
72 |
73 | # mpeltonen/sbt-idea plugin
74 | .idea_modules/
75 |
76 | # JIRA plugin
77 | atlassian-ide-plugin.xml
78 |
79 | # Crashlytics plugin (for Android Studio and IntelliJ)
80 | com_crashlytics_export_strings.xml
81 | crashlytics.properties
82 | crashlytics-build.properties
83 | *.asc
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ### **PageIndicatorView**
4 | [  ](https://bintray.com/romandanylyk/maven/pageindicatorview/_latestVersion)[](https://android-arsenal.com/details/1/4555)
5 | [](https://android-arsenal.com/api?level=14)
6 |
7 |
8 | `PageIndicatorView` is light library to indicate ViewPager's selected page with different animations and ability to customise it as you need.
9 |
10 | 
11 |
12 | ### **Integration**
13 | To add `pageindicatorview` to your project, first make sure in root `build.gradle` you have specified the following repository:
14 | ```groovy
15 | repositories {
16 | jcenter()
17 | }
18 | ```
19 | >***Note***: by creating new project in Android Studio it will have `jcenter` repository specified by default, so you will not need to add it manually.
20 |
21 | Once you make sure you have `jcenter` repository in your project, all you need to do is to add the following line in `dependencies` section of your project `build.gradle`.
22 |
23 | See latest library version [  ](https://bintray.com/romandanylyk/maven/pageindicatorview/_latestVersion)
24 | ```groovy
25 | implementation 'com.romandanylyk:pageindicatorview:X.X.X'
26 | ```
27 | If your project already use `appcompat-v7` support library, you can omit `PageIndicatorView` dependencies by adding a single .aar file to your project, that will decrease total amount of methods used in your project.
28 |
29 | ```groovy
30 | implementation 'com.romandanylyk:pageindicatorview:X.X.X@aar'
31 | ```
32 |
33 | Keep in mind, that `PageIndicatorView` has min [API level 14](https://developer.android.com/about/dashboards/index.html) and these dependencies:
34 |
35 | ```groovy
36 | implementation 'com.android.support:appcompat-v7:27.1.1'
37 | implementation 'com.android.support:recyclerview-v7:27.1.1'
38 | implementation 'com.android.support:support-core-ui:27.1.1'
39 | ```
40 |
41 | ### **Usage Sample**
42 | Usage of `PageIndicatorView` is quite simple. All you need to do is to declare a view in your `layout.xml` and call `setSelection` method to select specific indicator - that's it!
43 |
44 | ```java
45 | PageIndicatorView pageIndicatorView = findViewById(R.id.pageIndicatorView);
46 | pageIndicatorView.setCount(5); // specify total count of indicators
47 | pageIndicatorView.setSelection(2);
48 | ```
49 |
50 |
51 | But if you're as lazy as I'm - then there is another option to handle `PageIndicatorView`
52 |
53 | ```xml
54 |
67 | ```
68 | All the `piv_` attributes here are specific for `PageIndicatorView` so you can customise it as you want with attributes - pretty handy.
69 |
70 | But what is more important here is `app:piv_viewPager="@id/viewPager"`.
71 | What it actually do is catch up your `ViewPager` and automatically handles all the event's to selected the right page - so you don't need to call `setSelection` method on your own.
72 |
73 | Another handy options here that works with your `ViewPager` as a whole is
74 | `app:piv_dynamicCount="true"` and ` app:piv_interactiveAnimation="true"`
75 |
76 | Dynamic count will automatically updates `PageIndicatorView` total count as you updates pages count in your `ViewPager` - so that's pretty useful.
77 |
78 | While interactive animation will progress the animation process within your swipe position, which makes animation more natural and responsive to end user.
79 |
80 |
81 | > ***Note***: Because `setViewPagerId` uses an instance of `ViewPager`, using it in recycler could lead to id conflicts, so `PageIndicatorView` will not know properly what is the right `ViewPager` to work with. Instead you should handle selected indicators on your own programatically.
82 |
83 |
84 | ```java
85 | pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
86 | @Override
87 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {/*empty*/}
88 |
89 | @Override
90 | public void onPageSelected(int position) {
91 | pageIndicatorView.setSelection(position);
92 | }
93 |
94 | @Override
95 | public void onPageScrollStateChanged(int state) {/*empty*/}
96 | });
97 | ```
98 |
99 |
100 | Here you can see all the animations `PageIndicatorView` support.
101 |
102 | Name| Support version| Preview
103 | -------- | --- | ---
104 | `AnimationType.NONE`| 0.0.1 | 
105 | `AnimationType.COLOR`| 0.0.1 |
106 | `AnimationType.SCALE`| 0.0.1 |
107 | `AnimationType.SLIDE`| 0.0.1 |
108 | `AnimationType.WORM`| 0.0.1 |
109 | `AnimationType.FILL`| 0.0.6 |
110 | `AnimationType.THIN_WORM`| 0.0.7 |
111 | `AnimationType.DROP`| 0.1.0 |
112 | `AnimationType.SWAP`| 0.1.1 |
113 |
114 |
115 | ### **Release Note**
116 | See release notes on [github releases](https://github.com/romandanylyk/PageIndicatorView/releases) or [Bintray release notes](https://bintray.com/romandanylyk/maven/pageindicatorview#release).
117 |
118 | ### **License**
119 |
120 | Copyright 2017 Roman Danylyk
121 |
122 | Licensed under the Apache License, Version 2.0 (the "License");
123 | you may not use this file except in compliance with the License.
124 | You may obtain a copy of the License at
125 |
126 | http://www.apache.org/licenses/LICENSE-2.0
127 |
128 | Unless required by applicable law or agreed to in writing, software
129 | distributed under the License is distributed on an "AS IS" BASIS,
130 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131 | See the License for the specific language governing permissions and
132 | limitations under the License.
133 |
134 |
--------------------------------------------------------------------------------
/assets/anim_color.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/assets/anim_color.gif
--------------------------------------------------------------------------------
/assets/anim_drop.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/assets/anim_drop.gif
--------------------------------------------------------------------------------
/assets/anim_fill.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/assets/anim_fill.gif
--------------------------------------------------------------------------------
/assets/anim_none.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/assets/anim_none.gif
--------------------------------------------------------------------------------
/assets/anim_scale.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/assets/anim_scale.gif
--------------------------------------------------------------------------------
/assets/anim_slide.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/assets/anim_slide.gif
--------------------------------------------------------------------------------
/assets/anim_swap.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/assets/anim_swap.gif
--------------------------------------------------------------------------------
/assets/anim_thin_worm.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/assets/anim_thin_worm.gif
--------------------------------------------------------------------------------
/assets/anim_worm.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/assets/anim_worm.gif
--------------------------------------------------------------------------------
/assets/animation_worm.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/assets/animation_worm.gif
--------------------------------------------------------------------------------
/assets/attributes.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/assets/attributes.gif
--------------------------------------------------------------------------------
/assets/preview_anim_drop.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/assets/preview_anim_drop.gif
--------------------------------------------------------------------------------
/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 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.2.1'
10 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
11 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
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 | }
22 | }
23 |
24 | task clean(type: Delete) {
25 | delete rootProject.buildDir
26 | }
27 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 | android.enableJetifier=false
20 | android.useAndroidX=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Apr 30 21:23:45 EEST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/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 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
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 Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/pageindicatorview/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/pageindicatorview/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | ext {
4 | bintrayRepo = 'maven'
5 | bintrayName = 'pageindicatorview'
6 |
7 | publishedGroupId = 'com.romandanylyk'
8 | libraryName = 'PageIndicatorView'
9 | artifact = 'pageindicatorview'
10 |
11 | libraryDescription = 'Page indicator for android ViewPager'
12 |
13 | siteUrl = 'https://github.com/romandanylyk/PageIndicatorView'
14 | gitUrl = 'https://github.com/romandanylyk/PageIndicatorView.git'
15 |
16 | libraryVersion = '1.0.3'
17 |
18 | developerId = 'romandanylyk'
19 | developerName = 'Roman Danylyk'
20 | developerEmail = 'romandanylyk96@gmail.com'
21 |
22 | licenseName = 'The Apache Software License, Version 2.0'
23 | licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
24 | allLicenses = ["Apache-2.0"]
25 | }
26 |
27 | android {
28 | compileSdkVersion 28
29 | buildToolsVersion '28.0.3'
30 |
31 | defaultConfig {
32 | minSdkVersion 14
33 | targetSdkVersion 28
34 | versionCode 1
35 | versionName "1.0"
36 |
37 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
38 |
39 | }
40 | buildTypes {
41 | release {
42 | minifyEnabled false
43 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
44 | }
45 | }
46 | }
47 |
48 | dependencies {
49 | repositories {
50 | maven { url "https://maven.google.com" }
51 | }
52 | implementation 'androidx.annotation:annotation:1.0.0'
53 | implementation 'androidx.core:core:1.0.0'
54 | implementation 'androidx.viewpager:viewpager:1.0.0'
55 | }
56 |
57 | allprojects {
58 | tasks.withType(Javadoc) {
59 | options.addStringOption('Xdoclint:none', '-quiet')
60 | options.addStringOption('encoding', 'UTF-8')
61 | }
62 |
63 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle'
64 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle'
65 | }
66 |
--------------------------------------------------------------------------------
/pageindicatorview/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Work\IDE\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/IndicatorManager.java:
--------------------------------------------------------------------------------
1 | package com.rd;
2 |
3 | import androidx.annotation.Nullable;
4 | import com.rd.animation.AnimationManager;
5 | import com.rd.animation.controller.ValueController;
6 | import com.rd.animation.data.Value;
7 | import com.rd.draw.DrawManager;
8 | import com.rd.draw.data.Indicator;
9 |
10 | public class IndicatorManager implements ValueController.UpdateListener {
11 |
12 | private DrawManager drawManager;
13 | private AnimationManager animationManager;
14 | private Listener listener;
15 |
16 | interface Listener {
17 | void onIndicatorUpdated();
18 | }
19 |
20 | IndicatorManager(@Nullable Listener listener) {
21 | this.listener = listener;
22 | this.drawManager = new DrawManager();
23 | this.animationManager = new AnimationManager(drawManager.indicator(), this);
24 | }
25 |
26 | public AnimationManager animate() {
27 | return animationManager;
28 | }
29 |
30 | public Indicator indicator() {
31 | return drawManager.indicator();
32 | }
33 |
34 | public DrawManager drawer() {
35 | return drawManager;
36 | }
37 |
38 | @Override
39 | public void onValueUpdated(@Nullable Value value) {
40 | drawManager.updateValue(value);
41 | if (listener != null) {
42 | listener.onIndicatorUpdated();
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/AnimationManager.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation;
2 |
3 | import androidx.annotation.NonNull;
4 | import com.rd.animation.controller.AnimationController;
5 | import com.rd.animation.controller.ValueController;
6 | import com.rd.draw.data.Indicator;
7 |
8 | public class AnimationManager {
9 |
10 | private AnimationController animationController;
11 |
12 | public AnimationManager(@NonNull Indicator indicator, @NonNull ValueController.UpdateListener listener) {
13 | this.animationController = new AnimationController(indicator, listener);
14 | }
15 |
16 | public void basic() {
17 | if (animationController != null) {
18 | animationController.end();
19 | animationController.basic();
20 | }
21 | }
22 |
23 | public void interactive(float progress) {
24 | if (animationController != null) {
25 | animationController.interactive(progress);
26 | }
27 | }
28 |
29 | public void end() {
30 | if (animationController != null) {
31 | animationController.end();
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/controller/AnimationController.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.controller;
2 |
3 | import androidx.annotation.NonNull;
4 | import com.rd.animation.type.AnimationType;
5 | import com.rd.animation.type.BaseAnimation;
6 | import com.rd.draw.data.Indicator;
7 | import com.rd.draw.data.Orientation;
8 | import com.rd.utils.CoordinatesUtils;
9 |
10 | public class AnimationController {
11 |
12 | private ValueController valueController;
13 | private ValueController.UpdateListener listener;
14 |
15 | private BaseAnimation runningAnimation;
16 | private Indicator indicator;
17 |
18 | private float progress;
19 | private boolean isInteractive;
20 |
21 | public AnimationController(@NonNull Indicator indicator, @NonNull ValueController.UpdateListener listener) {
22 | this.valueController = new ValueController(listener);
23 | this.listener = listener;
24 | this.indicator = indicator;
25 | }
26 |
27 | public void interactive(float progress) {
28 | this.isInteractive = true;
29 | this.progress = progress;
30 | animate();
31 | }
32 |
33 | public void basic() {
34 | this.isInteractive = false;
35 | this.progress = 0;
36 | animate();
37 | }
38 |
39 | public void end() {
40 | if (runningAnimation != null) {
41 | runningAnimation.end();
42 | }
43 | }
44 |
45 | private void animate() {
46 | AnimationType animationType = indicator.getAnimationType();
47 | switch (animationType) {
48 | case NONE:
49 | listener.onValueUpdated(null);
50 | break;
51 |
52 | case COLOR:
53 | colorAnimation();
54 | break;
55 |
56 | case SCALE:
57 | scaleAnimation();
58 | break;
59 |
60 | case WORM:
61 | wormAnimation();
62 | break;
63 |
64 | case FILL:
65 | fillAnimation();
66 | break;
67 |
68 | case SLIDE:
69 | slideAnimation();
70 | break;
71 |
72 | case THIN_WORM:
73 | thinWormAnimation();
74 | break;
75 |
76 | case DROP:
77 | dropAnimation();
78 | break;
79 |
80 | case SWAP:
81 | swapAnimation();
82 | break;
83 |
84 | case SCALE_DOWN:
85 | scaleDownAnimation();
86 | break;
87 | }
88 | }
89 |
90 | private void colorAnimation() {
91 | int selectedColor = indicator.getSelectedColor();
92 | int unselectedColor = indicator.getUnselectedColor();
93 | long animationDuration = indicator.getAnimationDuration();
94 |
95 | BaseAnimation animation = valueController
96 | .color()
97 | .with(unselectedColor, selectedColor)
98 | .duration(animationDuration);
99 |
100 | if (isInteractive) {
101 | animation.progress(progress);
102 | } else {
103 | animation.start();
104 | }
105 |
106 | runningAnimation = animation;
107 | }
108 |
109 | private void scaleAnimation() {
110 | int selectedColor = indicator.getSelectedColor();
111 | int unselectedColor = indicator.getUnselectedColor();
112 | int radiusPx = indicator.getRadius();
113 | float scaleFactor = indicator.getScaleFactor();
114 | long animationDuration = indicator.getAnimationDuration();
115 |
116 | BaseAnimation animation = valueController
117 | .scale()
118 | .with(unselectedColor, selectedColor, radiusPx, scaleFactor)
119 | .duration(animationDuration);
120 |
121 | if (isInteractive) {
122 | animation.progress(progress);
123 | } else {
124 | animation.start();
125 | }
126 |
127 | runningAnimation = animation;
128 | }
129 |
130 | private void wormAnimation() {
131 | int fromPosition = indicator.isInteractiveAnimation() ? indicator.getSelectedPosition() : indicator.getLastSelectedPosition();
132 | int toPosition = indicator.isInteractiveAnimation() ? indicator.getSelectingPosition() : indicator.getSelectedPosition();
133 |
134 | int from = CoordinatesUtils.getCoordinate(indicator, fromPosition);
135 | int to = CoordinatesUtils.getCoordinate(indicator, toPosition);
136 | boolean isRightSide = toPosition > fromPosition;
137 |
138 | int radiusPx = indicator.getRadius();
139 | long animationDuration = indicator.getAnimationDuration();
140 |
141 | BaseAnimation animation = valueController
142 | .worm()
143 | .with(from, to, radiusPx, isRightSide)
144 | .duration(animationDuration);
145 |
146 | if (isInteractive) {
147 | animation.progress(progress);
148 | } else {
149 | animation.start();
150 | }
151 |
152 | runningAnimation = animation;
153 | }
154 |
155 | private void slideAnimation() {
156 | int fromPosition = indicator.isInteractiveAnimation() ? indicator.getSelectedPosition() : indicator.getLastSelectedPosition();
157 | int toPosition = indicator.isInteractiveAnimation() ? indicator.getSelectingPosition() : indicator.getSelectedPosition();
158 |
159 | int from = CoordinatesUtils.getCoordinate(indicator, fromPosition);
160 | int to = CoordinatesUtils.getCoordinate(indicator, toPosition);
161 | long animationDuration = indicator.getAnimationDuration();
162 |
163 | BaseAnimation animation = valueController
164 | .slide()
165 | .with(from, to)
166 | .duration(animationDuration);
167 |
168 | if (isInteractive) {
169 | animation.progress(progress);
170 | } else {
171 | animation.start();
172 | }
173 |
174 | runningAnimation = animation;
175 | }
176 |
177 | private void fillAnimation() {
178 | int selectedColor = indicator.getSelectedColor();
179 | int unselectedColor = indicator.getUnselectedColor();
180 | int radiusPx = indicator.getRadius();
181 | int strokePx = indicator.getStroke();
182 | long animationDuration = indicator.getAnimationDuration();
183 |
184 | BaseAnimation animation = valueController
185 | .fill()
186 | .with(unselectedColor, selectedColor, radiusPx, strokePx)
187 | .duration(animationDuration);
188 |
189 | if (isInteractive) {
190 | animation.progress(progress);
191 | } else {
192 | animation.start();
193 | }
194 |
195 | runningAnimation = animation;
196 | }
197 |
198 | private void thinWormAnimation() {
199 | int fromPosition = indicator.isInteractiveAnimation() ? indicator.getSelectedPosition() : indicator.getLastSelectedPosition();
200 | int toPosition = indicator.isInteractiveAnimation() ? indicator.getSelectingPosition() : indicator.getSelectedPosition();
201 |
202 | int from = CoordinatesUtils.getCoordinate(indicator, fromPosition);
203 | int to = CoordinatesUtils.getCoordinate(indicator, toPosition);
204 | boolean isRightSide = toPosition > fromPosition;
205 |
206 | int radiusPx = indicator.getRadius();
207 | long animationDuration = indicator.getAnimationDuration();
208 |
209 | BaseAnimation animation = valueController
210 | .thinWorm()
211 | .with(from, to, radiusPx, isRightSide)
212 | .duration(animationDuration);
213 |
214 | if (isInteractive) {
215 | animation.progress(progress);
216 | } else {
217 | animation.start();
218 | }
219 |
220 | runningAnimation = animation;
221 | }
222 |
223 | private void dropAnimation() {
224 | int fromPosition = indicator.isInteractiveAnimation() ? indicator.getSelectedPosition() : indicator.getLastSelectedPosition();
225 | int toPosition = indicator.isInteractiveAnimation() ? indicator.getSelectingPosition() : indicator.getSelectedPosition();
226 |
227 | int widthFrom = CoordinatesUtils.getCoordinate(indicator, fromPosition);
228 | int widthTo = CoordinatesUtils.getCoordinate(indicator, toPosition);
229 |
230 | int paddingTop = indicator.getPaddingTop();
231 | int paddingLeft = indicator.getPaddingLeft();
232 | int padding = indicator.getOrientation() == Orientation.HORIZONTAL ? paddingTop : paddingLeft;
233 |
234 | int radius = indicator.getRadius();
235 | int heightFrom = radius * 3 + padding;
236 | int heightTo = radius + padding;
237 |
238 | long animationDuration = indicator.getAnimationDuration();
239 |
240 | BaseAnimation animation = valueController
241 | .drop()
242 | .duration(animationDuration)
243 | .with(widthFrom, widthTo, heightFrom, heightTo, radius);
244 |
245 | if (isInteractive) {
246 | animation.progress(progress);
247 | } else {
248 | animation.start();
249 | }
250 |
251 | runningAnimation = animation;
252 | }
253 |
254 | private void swapAnimation() {
255 | int fromPosition = indicator.isInteractiveAnimation() ? indicator.getSelectedPosition() : indicator.getLastSelectedPosition();
256 | int toPosition = indicator.isInteractiveAnimation() ? indicator.getSelectingPosition() : indicator.getSelectedPosition();
257 |
258 | int from = CoordinatesUtils.getCoordinate(indicator, fromPosition);
259 | int to = CoordinatesUtils.getCoordinate(indicator, toPosition);
260 | long animationDuration = indicator.getAnimationDuration();
261 |
262 | BaseAnimation animation = valueController
263 | .swap()
264 | .with(from, to)
265 | .duration(animationDuration);
266 |
267 | if (isInteractive) {
268 | animation.progress(progress);
269 | } else {
270 | animation.start();
271 | }
272 |
273 | runningAnimation = animation;
274 | }
275 |
276 | private void scaleDownAnimation() {
277 | int selectedColor = indicator.getSelectedColor();
278 | int unselectedColor = indicator.getUnselectedColor();
279 | int radiusPx = indicator.getRadius();
280 | float scaleFactor = indicator.getScaleFactor();
281 | long animationDuration = indicator.getAnimationDuration();
282 |
283 | BaseAnimation animation = valueController
284 | .scaleDown()
285 | .with(unselectedColor, selectedColor, radiusPx, scaleFactor)
286 | .duration(animationDuration);
287 |
288 | if (isInteractive) {
289 | animation.progress(progress);
290 | } else {
291 | animation.start();
292 | }
293 |
294 | runningAnimation = animation;
295 | }
296 | }
297 |
298 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/controller/ValueController.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.controller;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 | import com.rd.animation.data.Value;
6 | import com.rd.animation.type.*;
7 |
8 | public class ValueController {
9 |
10 | private ColorAnimation colorAnimation;
11 | private ScaleAnimation scaleAnimation;
12 | private WormAnimation wormAnimation;
13 | private SlideAnimation slideAnimation;
14 | private FillAnimation fillAnimation;
15 | private ThinWormAnimation thinWormAnimation;
16 | private DropAnimation dropAnimation;
17 | private SwapAnimation swapAnimation;
18 | private ScaleDownAnimation scaleDownAnimation;
19 |
20 | private UpdateListener updateListener;
21 |
22 | public interface UpdateListener {
23 | void onValueUpdated(@Nullable Value value);
24 | }
25 |
26 | public ValueController(@Nullable UpdateListener listener) {
27 | updateListener = listener;
28 | }
29 |
30 | @NonNull
31 | public ColorAnimation color() {
32 | if (colorAnimation == null) {
33 | colorAnimation = new ColorAnimation(updateListener);
34 | }
35 |
36 | return colorAnimation;
37 | }
38 |
39 | @NonNull
40 | public ScaleAnimation scale() {
41 | if (scaleAnimation == null) {
42 | scaleAnimation = new ScaleAnimation(updateListener);
43 | }
44 |
45 | return scaleAnimation;
46 | }
47 |
48 | @NonNull
49 | public WormAnimation worm() {
50 | if (wormAnimation == null) {
51 | wormAnimation = new WormAnimation(updateListener);
52 | }
53 |
54 | return wormAnimation;
55 | }
56 |
57 | @NonNull
58 | public SlideAnimation slide() {
59 | if (slideAnimation == null) {
60 | slideAnimation = new SlideAnimation(updateListener);
61 | }
62 |
63 | return slideAnimation;
64 | }
65 |
66 | @NonNull
67 | public FillAnimation fill() {
68 | if (fillAnimation == null) {
69 | fillAnimation = new FillAnimation(updateListener);
70 | }
71 |
72 | return fillAnimation;
73 | }
74 |
75 | @NonNull
76 | public ThinWormAnimation thinWorm() {
77 | if (thinWormAnimation == null) {
78 | thinWormAnimation = new ThinWormAnimation(updateListener);
79 | }
80 |
81 | return thinWormAnimation;
82 | }
83 |
84 | @NonNull
85 | public DropAnimation drop() {
86 | if (dropAnimation == null) {
87 | dropAnimation = new DropAnimation(updateListener);
88 | }
89 |
90 | return dropAnimation;
91 | }
92 |
93 | @NonNull
94 | public SwapAnimation swap() {
95 | if (swapAnimation == null) {
96 | swapAnimation = new SwapAnimation(updateListener);
97 | }
98 |
99 | return swapAnimation;
100 | }
101 |
102 | @NonNull
103 | public ScaleDownAnimation scaleDown() {
104 | if (scaleDownAnimation == null) {
105 | scaleDownAnimation = new ScaleDownAnimation(updateListener);
106 | }
107 |
108 | return scaleDownAnimation;
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/data/AnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.data;
2 |
3 | import androidx.annotation.NonNull;
4 | import com.rd.animation.data.type.*;
5 |
6 | public class AnimationValue {
7 |
8 | private ColorAnimationValue colorAnimationValue;
9 | private ScaleAnimationValue scaleAnimationValue;
10 | private WormAnimationValue wormAnimationValue;
11 | private FillAnimationValue fillAnimationValue;
12 | private ThinWormAnimationValue thinWormAnimationValue;
13 | private DropAnimationValue dropAnimationValue;
14 | private SwapAnimationValue swapAnimationValue;
15 |
16 | @NonNull
17 | public ColorAnimationValue getColorAnimationValue() {
18 | if (colorAnimationValue == null) {
19 | colorAnimationValue = new ColorAnimationValue();
20 | }
21 | return colorAnimationValue;
22 | }
23 |
24 | @NonNull
25 | public ScaleAnimationValue getScaleAnimationValue() {
26 | if (scaleAnimationValue == null) {
27 | scaleAnimationValue = new ScaleAnimationValue();
28 | }
29 | return scaleAnimationValue;
30 | }
31 |
32 | @NonNull
33 | public WormAnimationValue getWormAnimationValue() {
34 | if (wormAnimationValue == null) {
35 | wormAnimationValue = new WormAnimationValue();
36 | }
37 | return wormAnimationValue;
38 | }
39 |
40 | @NonNull
41 | public FillAnimationValue getFillAnimationValue() {
42 | if (fillAnimationValue == null) {
43 | fillAnimationValue = new FillAnimationValue();
44 | }
45 | return fillAnimationValue;
46 | }
47 |
48 | @NonNull
49 | public ThinWormAnimationValue getThinWormAnimationValue() {
50 | if (thinWormAnimationValue == null) {
51 | thinWormAnimationValue = new ThinWormAnimationValue();
52 | }
53 | return thinWormAnimationValue;
54 | }
55 |
56 | @NonNull
57 | public DropAnimationValue getDropAnimationValue() {
58 | if (dropAnimationValue == null) {
59 | dropAnimationValue = new DropAnimationValue();
60 | }
61 | return dropAnimationValue;
62 | }
63 |
64 | @NonNull
65 | public SwapAnimationValue getSwapAnimationValue() {
66 | if (swapAnimationValue == null) {
67 | swapAnimationValue = new SwapAnimationValue();
68 | }
69 | return swapAnimationValue;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/data/Value.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.data;
2 |
3 | public interface Value {/*empty*/}
4 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/data/type/ColorAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.data.type;
2 |
3 | import com.rd.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 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/data/type/DropAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.data.type;
2 |
3 | import com.rd.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 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/data/type/FillAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.data.type;
2 |
3 | import com.rd.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 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/data/type/ScaleAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.data.type;
2 |
3 | import com.rd.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 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/data/type/SlideAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.data.type;
2 |
3 | import com.rd.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 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/data/type/SwapAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.data.type;
2 |
3 | import com.rd.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 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/data/type/ThinWormAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.data.type;
2 |
3 | import com.rd.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 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/data/type/WormAnimationValue.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.data.type;
2 |
3 | import com.rd.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 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/type/AnimationType.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.type;
2 |
3 | public enum AnimationType {NONE, COLOR, SCALE, WORM, SLIDE, FILL, THIN_WORM, DROP, SWAP, SCALE_DOWN}
4 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/type/BaseAnimation.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.type;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ValueAnimator;
5 | import androidx.annotation.NonNull;
6 | import androidx.annotation.Nullable;
7 | import com.rd.animation.controller.ValueController;
8 |
9 | public abstract class BaseAnimation {
10 |
11 | public static final int DEFAULT_ANIMATION_TIME = 350;
12 | protected long animationDuration = DEFAULT_ANIMATION_TIME;
13 |
14 | protected ValueController.UpdateListener listener;
15 | protected T animator;
16 |
17 | public BaseAnimation(@Nullable ValueController.UpdateListener listener) {
18 | this.listener = listener;
19 | animator = createAnimator();
20 | }
21 |
22 | @NonNull
23 | public abstract T createAnimator();
24 |
25 | public abstract BaseAnimation progress(float progress);
26 |
27 | public BaseAnimation duration(long duration) {
28 | animationDuration = duration;
29 |
30 | if (animator instanceof ValueAnimator) {
31 | animator.setDuration(animationDuration);
32 | }
33 |
34 | return this;
35 | }
36 |
37 | public void start() {
38 | if (animator != null && !animator.isRunning()) {
39 | animator.start();
40 | }
41 | }
42 |
43 | public void end() {
44 | if (animator != null && animator.isStarted()) {
45 | animator.end();
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/type/ColorAnimation.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.type;
2 |
3 | import android.animation.ArgbEvaluator;
4 | import android.animation.PropertyValuesHolder;
5 | import android.animation.ValueAnimator;
6 | import androidx.annotation.NonNull;
7 | import androidx.annotation.Nullable;
8 | import android.view.animation.AccelerateDecelerateInterpolator;
9 | import com.rd.animation.controller.ValueController;
10 | import com.rd.animation.data.type.ColorAnimationValue;
11 |
12 | public class ColorAnimation extends BaseAnimation {
13 |
14 | public static final String DEFAULT_UNSELECTED_COLOR = "#33ffffff";
15 | public static final String DEFAULT_SELECTED_COLOR = "#ffffff";
16 |
17 | static final String ANIMATION_COLOR_REVERSE = "ANIMATION_COLOR_REVERSE";
18 | static final String ANIMATION_COLOR = "ANIMATION_COLOR";
19 |
20 | private ColorAnimationValue value;
21 |
22 | int colorStart;
23 | int colorEnd;
24 |
25 | public ColorAnimation(@Nullable ValueController.UpdateListener listener) {
26 | super(listener);
27 | value = new ColorAnimationValue();
28 | }
29 |
30 | @NonNull
31 | @Override
32 | public ValueAnimator createAnimator() {
33 | ValueAnimator animator = new ValueAnimator();
34 | animator.setDuration(BaseAnimation.DEFAULT_ANIMATION_TIME);
35 | animator.setInterpolator(new AccelerateDecelerateInterpolator());
36 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
37 | @Override
38 | public void onAnimationUpdate(ValueAnimator animation) {
39 | onAnimateUpdated(animation);
40 | }
41 | });
42 |
43 | return animator;
44 | }
45 |
46 | @Override
47 | public ColorAnimation progress(float progress) {
48 | if (animator != null) {
49 | long playTime = (long) (progress * animationDuration);
50 |
51 | if (animator.getValues() != null && animator.getValues().length > 0) {
52 | animator.setCurrentPlayTime(playTime);
53 | }
54 | }
55 |
56 | return this;
57 | }
58 |
59 | @NonNull
60 | public ColorAnimation with(int colorStart, int colorEnd) {
61 | if (animator != null && hasChanges(colorStart, colorEnd)) {
62 |
63 | this.colorStart = colorStart;
64 | this.colorEnd = colorEnd;
65 |
66 | PropertyValuesHolder colorHolder = createColorPropertyHolder(false);
67 | PropertyValuesHolder reverseColorHolder = createColorPropertyHolder(true);
68 |
69 | animator.setValues(colorHolder, reverseColorHolder);
70 | }
71 |
72 | return this;
73 | }
74 |
75 | PropertyValuesHolder createColorPropertyHolder(boolean isReverse) {
76 | String propertyName;
77 | int colorStart;
78 | int colorEnd;
79 |
80 | if (isReverse) {
81 | propertyName = ANIMATION_COLOR_REVERSE;
82 | colorStart = this.colorEnd;
83 | colorEnd = this.colorStart;
84 |
85 | } else {
86 | propertyName = ANIMATION_COLOR;
87 | colorStart = this.colorStart;
88 | colorEnd = this.colorEnd;
89 | }
90 |
91 | PropertyValuesHolder holder = PropertyValuesHolder.ofInt(propertyName, colorStart, colorEnd);
92 | holder.setEvaluator(new ArgbEvaluator());
93 |
94 | return holder;
95 | }
96 |
97 | @SuppressWarnings("RedundantIfStatement")
98 | private boolean hasChanges(int colorStart, int colorEnd) {
99 | if (this.colorStart != colorStart) {
100 | return true;
101 | }
102 |
103 | if (this.colorEnd != colorEnd) {
104 | return true;
105 | }
106 |
107 | return false;
108 | }
109 |
110 | private void onAnimateUpdated(@NonNull ValueAnimator animation) {
111 | int color = (int) animation.getAnimatedValue(ANIMATION_COLOR);
112 | int colorReverse = (int) animation.getAnimatedValue(ANIMATION_COLOR_REVERSE);
113 |
114 | value.setColor(color);
115 | value.setColorReverse(colorReverse);
116 |
117 | if (listener != null) {
118 | listener.onValueUpdated(value);
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/type/DropAnimation.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.type;
2 |
3 | import android.animation.Animator;
4 | import android.animation.AnimatorSet;
5 | import android.animation.ValueAnimator;
6 | import androidx.annotation.NonNull;
7 | import android.view.animation.AccelerateDecelerateInterpolator;
8 | import com.rd.animation.controller.ValueController;
9 | import com.rd.animation.data.type.DropAnimationValue;
10 |
11 | public class DropAnimation extends BaseAnimation {
12 |
13 | private int widthStart;
14 | private int widthEnd;
15 | private int heightStart;
16 | private int heightEnd;
17 | private int radius;
18 |
19 | private enum AnimationType {Width, Height, Radius}
20 |
21 | private DropAnimationValue value;
22 |
23 | public DropAnimation(@NonNull ValueController.UpdateListener listener) {
24 | super(listener);
25 | value = new DropAnimationValue();
26 | }
27 |
28 | @NonNull
29 | @Override
30 | public AnimatorSet createAnimator() {
31 | AnimatorSet animator = new AnimatorSet();
32 | animator.setInterpolator(new AccelerateDecelerateInterpolator());
33 |
34 | return animator;
35 | }
36 |
37 | @Override
38 | public DropAnimation progress(float progress) {
39 | if (animator != null) {
40 | long playTimeLeft = (long) (progress * animationDuration);
41 | boolean isReverse = false;
42 |
43 | for (Animator anim : animator.getChildAnimations()) {
44 | ValueAnimator animator = (ValueAnimator) anim;
45 | long animDuration = animator.getDuration();
46 | long currPlayTime = playTimeLeft;
47 |
48 | if (isReverse) {
49 | currPlayTime -= animDuration;
50 | }
51 |
52 | if (currPlayTime < 0) {
53 | continue;
54 |
55 | } else if (currPlayTime >= animDuration) {
56 | currPlayTime = animDuration;
57 | }
58 |
59 | if (animator.getValues() != null && animator.getValues().length > 0) {
60 | animator.setCurrentPlayTime(currPlayTime);
61 | }
62 |
63 | if (!isReverse && animDuration >= animationDuration) {
64 | isReverse = true;
65 | }
66 | }
67 | }
68 |
69 | return this;
70 | }
71 |
72 | @Override
73 | public DropAnimation duration(long duration) {
74 | super.duration(duration);
75 | return this;
76 | }
77 |
78 | @SuppressWarnings("UnnecessaryLocalVariable")
79 | public DropAnimation with(int widthStart, int widthEnd, int heightStart, int heightEnd, int radius) {
80 | if (hasChanges(widthStart, widthEnd, heightStart, heightEnd, radius)) {
81 | animator = createAnimator();
82 |
83 | this.widthStart = widthStart;
84 | this.widthEnd = widthEnd;
85 | this.heightStart = heightStart;
86 | this.heightEnd = heightEnd;
87 | this.radius = radius;
88 |
89 | int fromRadius = radius;
90 | int toRadius = (int) (radius / 1.5);
91 | long halfDuration = animationDuration / 2;
92 |
93 | ValueAnimator widthAnimator = createValueAnimation(widthStart, widthEnd, animationDuration, AnimationType.Width);
94 | ValueAnimator heightForwardAnimator = createValueAnimation(heightStart, heightEnd, halfDuration, AnimationType.Height);
95 | ValueAnimator radiusForwardAnimator = createValueAnimation(fromRadius, toRadius, halfDuration, AnimationType.Radius);
96 |
97 | ValueAnimator heightBackwardAnimator = createValueAnimation(heightEnd, heightStart, halfDuration, AnimationType.Height);
98 | ValueAnimator radiusBackwardAnimator = createValueAnimation(toRadius, fromRadius, halfDuration, AnimationType.Radius);
99 |
100 | animator.play(heightForwardAnimator)
101 | .with(radiusForwardAnimator)
102 | .with(widthAnimator)
103 | .before(heightBackwardAnimator)
104 | .before(radiusBackwardAnimator);
105 | }
106 |
107 | return this;
108 | }
109 |
110 | private ValueAnimator createValueAnimation(int fromValue, int toValue, long duration, final AnimationType type) {
111 | ValueAnimator anim = ValueAnimator.ofInt(fromValue, toValue);
112 | anim.setInterpolator(new AccelerateDecelerateInterpolator());
113 | anim.setDuration(duration);
114 | anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
115 | @Override
116 | public void onAnimationUpdate(ValueAnimator animation) {
117 | onAnimatorUpdate(animation, type);
118 | }
119 | });
120 |
121 | return anim;
122 | }
123 |
124 | private void onAnimatorUpdate(@NonNull ValueAnimator animation, @NonNull AnimationType type) {
125 | int frameValue = (int) animation.getAnimatedValue();
126 |
127 | switch (type) {
128 | case Width:
129 | value.setWidth(frameValue);
130 | break;
131 |
132 | case Height:
133 | value.setHeight(frameValue);
134 | break;
135 |
136 | case Radius:
137 | value.setRadius(frameValue);
138 | break;
139 | }
140 |
141 | if (listener != null) {
142 | listener.onValueUpdated(value);
143 | }
144 | }
145 |
146 | @SuppressWarnings("RedundantIfStatement")
147 | private boolean hasChanges(int widthStart, int widthEnd, int heightStart, int heightEnd, int radius) {
148 | if (this.widthStart != widthStart) {
149 | return true;
150 | }
151 |
152 | if (this.widthEnd != widthEnd) {
153 | return true;
154 | }
155 |
156 | if (this.heightStart != heightStart) {
157 | return true;
158 | }
159 |
160 | if (this.heightEnd != heightEnd) {
161 | return true;
162 | }
163 |
164 | if (this.radius != radius) {
165 | return true;
166 | }
167 |
168 | return false;
169 | }
170 |
171 | }
172 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/type/FillAnimation.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.type;
2 |
3 | import android.animation.IntEvaluator;
4 | import android.animation.PropertyValuesHolder;
5 | import android.animation.ValueAnimator;
6 | import androidx.annotation.NonNull;
7 | import android.view.animation.AccelerateDecelerateInterpolator;
8 | import com.rd.animation.controller.ValueController;
9 | import com.rd.animation.data.type.FillAnimationValue;
10 |
11 | public class FillAnimation extends ColorAnimation {
12 |
13 | private static final String ANIMATION_RADIUS_REVERSE = "ANIMATION_RADIUS_REVERSE";
14 | private static final String ANIMATION_RADIUS = "ANIMATION_RADIUS";
15 |
16 | private static final String ANIMATION_STROKE_REVERSE = "ANIMATION_STROKE_REVERSE";
17 | private static final String ANIMATION_STROKE = "ANIMATION_STROKE";
18 |
19 | public static final int DEFAULT_STROKE_DP = 1;
20 | private FillAnimationValue value;
21 |
22 | private int radius;
23 | private int stroke;
24 |
25 | public FillAnimation(@NonNull ValueController.UpdateListener listener) {
26 | super(listener);
27 | value = new FillAnimationValue();
28 | }
29 |
30 | @NonNull
31 | @Override
32 | public ValueAnimator createAnimator() {
33 | ValueAnimator animator = new ValueAnimator();
34 | animator.setDuration(BaseAnimation.DEFAULT_ANIMATION_TIME);
35 | animator.setInterpolator(new AccelerateDecelerateInterpolator());
36 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
37 | @Override
38 | public void onAnimationUpdate(ValueAnimator animation) {
39 | onAnimateUpdated(animation);
40 | }
41 | });
42 |
43 | return animator;
44 | }
45 |
46 | @NonNull
47 | public FillAnimation with(int colorStart, int colorEnd, int radius, int stroke) {
48 | if (animator != null && hasChanges(colorStart, colorEnd, radius, stroke)) {
49 |
50 | this.colorStart = colorStart;
51 | this.colorEnd = colorEnd;
52 |
53 | this.radius = radius;
54 | this.stroke = stroke;
55 |
56 | PropertyValuesHolder colorHolder = createColorPropertyHolder(false);
57 | PropertyValuesHolder reverseColorHolder = createColorPropertyHolder(true);
58 |
59 | PropertyValuesHolder radiusHolder = createRadiusPropertyHolder(false);
60 | PropertyValuesHolder radiusReverseHolder = createRadiusPropertyHolder(true);
61 |
62 | PropertyValuesHolder strokeHolder = createStrokePropertyHolder(false);
63 | PropertyValuesHolder strokeReverseHolder = createStrokePropertyHolder(true);
64 |
65 | animator.setValues(
66 | colorHolder,
67 | reverseColorHolder,
68 |
69 | radiusHolder,
70 | radiusReverseHolder,
71 |
72 | strokeHolder,
73 | strokeReverseHolder);
74 | }
75 |
76 | return this;
77 | }
78 |
79 | @NonNull
80 | private PropertyValuesHolder createRadiusPropertyHolder(boolean isReverse) {
81 | String propertyName;
82 | int startRadiusValue;
83 | int endRadiusValue;
84 |
85 | if (isReverse) {
86 | propertyName = ANIMATION_RADIUS_REVERSE;
87 | startRadiusValue = radius / 2;
88 | endRadiusValue = radius;
89 | } else {
90 | propertyName = ANIMATION_RADIUS;
91 | startRadiusValue = radius;
92 | endRadiusValue = radius / 2;
93 | }
94 |
95 | PropertyValuesHolder holder = PropertyValuesHolder.ofInt(propertyName, startRadiusValue, endRadiusValue);
96 | holder.setEvaluator(new IntEvaluator());
97 |
98 | return holder;
99 | }
100 |
101 | @NonNull
102 | private PropertyValuesHolder createStrokePropertyHolder(boolean isReverse) {
103 | String propertyName;
104 | int startStrokeValue;
105 | int endStrokeValue;
106 |
107 | if (isReverse) {
108 | propertyName = ANIMATION_STROKE_REVERSE;
109 | startStrokeValue = radius;
110 | endStrokeValue = 0;
111 | } else {
112 | propertyName = ANIMATION_STROKE;
113 | startStrokeValue = 0;
114 | endStrokeValue = radius;
115 | }
116 |
117 | PropertyValuesHolder holder = PropertyValuesHolder.ofInt(propertyName, startStrokeValue, endStrokeValue);
118 | holder.setEvaluator(new IntEvaluator());
119 |
120 | return holder;
121 | }
122 |
123 | private void onAnimateUpdated(@NonNull ValueAnimator animation) {
124 | int color = (int) animation.getAnimatedValue(ANIMATION_COLOR);
125 | int colorReverse = (int) animation.getAnimatedValue(ANIMATION_COLOR_REVERSE);
126 |
127 | int radius = (int) animation.getAnimatedValue(ANIMATION_RADIUS);
128 | int radiusReverse = (int) animation.getAnimatedValue(ANIMATION_RADIUS_REVERSE);
129 |
130 | int stroke = (int) animation.getAnimatedValue(ANIMATION_STROKE);
131 | int strokeReverse = (int) animation.getAnimatedValue(ANIMATION_STROKE_REVERSE);
132 |
133 | value.setColor(color);
134 | value.setColorReverse(colorReverse);
135 |
136 | value.setRadius(radius);
137 | value.setRadiusReverse(radiusReverse);
138 |
139 | value.setStroke(stroke);
140 | value.setStrokeReverse(strokeReverse);
141 |
142 | if (listener != null) {
143 | listener.onValueUpdated(value);
144 | }
145 | }
146 |
147 | @SuppressWarnings("RedundantIfStatement")
148 | private boolean hasChanges(int colorStart, int colorEnd, int radiusValue, int strokeValue) {
149 | if (this.colorStart != colorStart) {
150 | return true;
151 | }
152 |
153 | if (this.colorEnd != colorEnd) {
154 | return true;
155 | }
156 |
157 | if (radius != radiusValue) {
158 | return true;
159 | }
160 |
161 | if (stroke != strokeValue) {
162 | return true;
163 | }
164 |
165 | return false;
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/type/ScaleAnimation.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.type;
2 |
3 | import android.animation.IntEvaluator;
4 | import android.animation.PropertyValuesHolder;
5 | import android.animation.ValueAnimator;
6 | import androidx.annotation.NonNull;
7 | import android.view.animation.AccelerateDecelerateInterpolator;
8 | import com.rd.animation.controller.ValueController;
9 | import com.rd.animation.data.type.ScaleAnimationValue;
10 |
11 | public class ScaleAnimation extends ColorAnimation {
12 |
13 | public static final float DEFAULT_SCALE_FACTOR = 0.7f;
14 | public static final float MIN_SCALE_FACTOR = 0.3f;
15 | public static final float MAX_SCALE_FACTOR = 1;
16 |
17 | static final String ANIMATION_SCALE_REVERSE = "ANIMATION_SCALE_REVERSE";
18 | static final String ANIMATION_SCALE = "ANIMATION_SCALE";
19 |
20 | int radius;
21 | float scaleFactor;
22 |
23 | private ScaleAnimationValue value;
24 |
25 | public ScaleAnimation(@NonNull ValueController.UpdateListener listener) {
26 | super(listener);
27 | value = new ScaleAnimationValue();
28 | }
29 |
30 | @NonNull
31 | @Override
32 | public ValueAnimator createAnimator() {
33 | ValueAnimator animator = new ValueAnimator();
34 | animator.setDuration(BaseAnimation.DEFAULT_ANIMATION_TIME);
35 | animator.setInterpolator(new AccelerateDecelerateInterpolator());
36 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
37 | @Override
38 | public void onAnimationUpdate(ValueAnimator animation) {
39 | onAnimateUpdated(animation);
40 | }
41 | });
42 |
43 | return animator;
44 | }
45 |
46 | @NonNull
47 | public ScaleAnimation with(int colorStart, int colorEnd, int radius, float scaleFactor) {
48 | if (animator != null && hasChanges(colorStart, colorEnd, radius, scaleFactor)) {
49 |
50 | this.colorStart = colorStart;
51 | this.colorEnd = colorEnd;
52 |
53 | this.radius = radius;
54 | this.scaleFactor = scaleFactor;
55 |
56 | PropertyValuesHolder colorHolder = createColorPropertyHolder(false);
57 | PropertyValuesHolder reverseColorHolder = createColorPropertyHolder(true);
58 |
59 | PropertyValuesHolder scaleHolder = createScalePropertyHolder(false);
60 | PropertyValuesHolder scaleReverseHolder = createScalePropertyHolder(true);
61 |
62 | animator.setValues(colorHolder, reverseColorHolder, scaleHolder, scaleReverseHolder);
63 | }
64 |
65 | return this;
66 | }
67 |
68 | private void onAnimateUpdated(@NonNull ValueAnimator animation) {
69 | int color = (int) animation.getAnimatedValue(ANIMATION_COLOR);
70 | int colorReverse = (int) animation.getAnimatedValue(ANIMATION_COLOR_REVERSE);
71 |
72 | int radius = (int) animation.getAnimatedValue(ANIMATION_SCALE);
73 | int radiusReverse = (int) animation.getAnimatedValue(ANIMATION_SCALE_REVERSE);
74 |
75 | value.setColor(color);
76 | value.setColorReverse(colorReverse);
77 |
78 | value.setRadius(radius);
79 | value.setRadiusReverse(radiusReverse);
80 |
81 | if (listener != null) {
82 | listener.onValueUpdated(value);
83 | }
84 | }
85 |
86 | @NonNull
87 | protected PropertyValuesHolder createScalePropertyHolder(boolean isReverse) {
88 | String propertyName;
89 | int startRadiusValue;
90 | int endRadiusValue;
91 |
92 | if (isReverse) {
93 | propertyName = ANIMATION_SCALE_REVERSE;
94 | startRadiusValue = radius;
95 | endRadiusValue = (int) (radius * scaleFactor);
96 | } else {
97 | propertyName = ANIMATION_SCALE;
98 | startRadiusValue = (int) (radius * scaleFactor);
99 | endRadiusValue = radius;
100 | }
101 |
102 | PropertyValuesHolder holder = PropertyValuesHolder.ofInt(propertyName, startRadiusValue, endRadiusValue);
103 | holder.setEvaluator(new IntEvaluator());
104 |
105 | return holder;
106 | }
107 |
108 | @SuppressWarnings("RedundantIfStatement")
109 | private boolean hasChanges(int colorStart, int colorEnd, int radiusValue, float scaleFactorValue) {
110 | if (this.colorStart != colorStart) {
111 | return true;
112 | }
113 |
114 | if (this.colorEnd != colorEnd) {
115 | return true;
116 | }
117 |
118 | if (radius != radiusValue) {
119 | return true;
120 | }
121 |
122 | if (scaleFactor != scaleFactorValue) {
123 | return true;
124 | }
125 |
126 | return false;
127 | }
128 | }
129 |
130 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/type/ScaleDownAnimation.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.type;
2 |
3 | import android.animation.IntEvaluator;
4 | import android.animation.PropertyValuesHolder;
5 | import androidx.annotation.NonNull;
6 | import com.rd.animation.controller.ValueController;
7 |
8 | public class ScaleDownAnimation extends ScaleAnimation {
9 |
10 | public ScaleDownAnimation(@NonNull ValueController.UpdateListener listener) {
11 | super(listener);
12 | }
13 |
14 | @NonNull
15 | @Override
16 | protected PropertyValuesHolder createScalePropertyHolder(boolean isReverse) {
17 | String propertyName;
18 | int startRadiusValue;
19 | int endRadiusValue;
20 |
21 | if (isReverse) {
22 | propertyName = ANIMATION_SCALE_REVERSE;
23 | startRadiusValue = (int) (radius * scaleFactor);
24 | endRadiusValue = radius;
25 | } else {
26 | propertyName = ANIMATION_SCALE;
27 | startRadiusValue = radius;
28 | endRadiusValue = (int) (radius * scaleFactor);
29 | }
30 |
31 | PropertyValuesHolder holder = PropertyValuesHolder.ofInt(propertyName, startRadiusValue, endRadiusValue);
32 | holder.setEvaluator(new IntEvaluator());
33 |
34 | return holder;
35 | }
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/type/SlideAnimation.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.type;
2 |
3 | import android.animation.IntEvaluator;
4 | import android.animation.PropertyValuesHolder;
5 | import android.animation.ValueAnimator;
6 | import androidx.annotation.NonNull;
7 | import android.view.animation.AccelerateDecelerateInterpolator;
8 | import com.rd.animation.controller.ValueController;
9 | import com.rd.animation.data.type.SlideAnimationValue;
10 |
11 | public class SlideAnimation extends BaseAnimation {
12 |
13 | private static final String ANIMATION_COORDINATE = "ANIMATION_COORDINATE";
14 | private static final int COORDINATE_NONE = -1;
15 |
16 | private SlideAnimationValue value;
17 | private int coordinateStart = COORDINATE_NONE;
18 | private int coordinateEnd = COORDINATE_NONE;
19 |
20 | public SlideAnimation(@NonNull ValueController.UpdateListener listener) {
21 | super(listener);
22 | value = new SlideAnimationValue();
23 | }
24 |
25 | @NonNull
26 | @Override
27 | public ValueAnimator createAnimator() {
28 | ValueAnimator animator = new ValueAnimator();
29 | animator.setDuration(BaseAnimation.DEFAULT_ANIMATION_TIME);
30 | animator.setInterpolator(new AccelerateDecelerateInterpolator());
31 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
32 | @Override
33 | public void onAnimationUpdate(ValueAnimator animation) {
34 | onAnimateUpdated(animation);
35 | }
36 | });
37 |
38 | return animator;
39 | }
40 |
41 | @Override
42 | public SlideAnimation progress(float progress) {
43 | if (animator != null) {
44 | long playTime = (long) (progress * animationDuration);
45 |
46 | if (animator.getValues() != null && animator.getValues().length > 0) {
47 | animator.setCurrentPlayTime(playTime);
48 | }
49 | }
50 |
51 | return this;
52 | }
53 |
54 | @NonNull
55 | public SlideAnimation with(int coordinateStart, int coordinateEnd) {
56 | if (animator != null && hasChanges(coordinateStart, coordinateEnd)) {
57 |
58 | this.coordinateStart = coordinateStart;
59 | this.coordinateEnd = coordinateEnd;
60 |
61 | PropertyValuesHolder holder = createSlidePropertyHolder();
62 | animator.setValues(holder);
63 | }
64 |
65 | return this;
66 | }
67 |
68 | private PropertyValuesHolder createSlidePropertyHolder() {
69 | PropertyValuesHolder holder = PropertyValuesHolder.ofInt(ANIMATION_COORDINATE, coordinateStart, coordinateEnd);
70 | holder.setEvaluator(new IntEvaluator());
71 |
72 | return holder;
73 | }
74 |
75 | private void onAnimateUpdated(@NonNull ValueAnimator animation) {
76 | int coordinate = (int) animation.getAnimatedValue(ANIMATION_COORDINATE);
77 | value.setCoordinate(coordinate);
78 |
79 | if (listener != null) {
80 | listener.onValueUpdated(value);
81 | }
82 | }
83 |
84 | @SuppressWarnings("RedundantIfStatement")
85 | private boolean hasChanges(int coordinateStart, int coordinateEnd) {
86 | if (this.coordinateStart != coordinateStart) {
87 | return true;
88 | }
89 |
90 | if (this.coordinateEnd != coordinateEnd) {
91 | return true;
92 | }
93 |
94 | return false;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/type/SwapAnimation.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.type;
2 |
3 | import android.animation.IntEvaluator;
4 | import android.animation.PropertyValuesHolder;
5 | import android.animation.ValueAnimator;
6 | import androidx.annotation.NonNull;
7 | import android.view.animation.AccelerateDecelerateInterpolator;
8 | import com.rd.animation.controller.ValueController;
9 | import com.rd.animation.data.type.SwapAnimationValue;
10 |
11 | public class SwapAnimation extends BaseAnimation {
12 |
13 | private static final String ANIMATION_COORDINATE = "ANIMATION_COORDINATE";
14 | private static final String ANIMATION_COORDINATE_REVERSE = "ANIMATION_COORDINATE_REVERSE";
15 | private static final int COORDINATE_NONE = -1;
16 |
17 | private int coordinateStart = COORDINATE_NONE;
18 | private int coordinateEnd = COORDINATE_NONE;
19 |
20 | private SwapAnimationValue value;
21 |
22 | public SwapAnimation(@NonNull ValueController.UpdateListener listener) {
23 | super(listener);
24 | value = new SwapAnimationValue();
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 SwapAnimation 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 SwapAnimation with(int coordinateStart, int coordinateEnd) {
58 | if (animator != null && hasChanges(coordinateStart, coordinateEnd)) {
59 | this.coordinateStart = coordinateStart;
60 | this.coordinateEnd = coordinateEnd;
61 |
62 | PropertyValuesHolder holder = createColorPropertyHolder(ANIMATION_COORDINATE, coordinateStart, coordinateEnd);
63 | PropertyValuesHolder holderReverse = createColorPropertyHolder(ANIMATION_COORDINATE_REVERSE, coordinateEnd, coordinateStart);
64 | animator.setValues(holder, holderReverse);
65 | }
66 |
67 | return this;
68 | }
69 |
70 | private PropertyValuesHolder createColorPropertyHolder(String propertyName, int startValue, int endValue) {
71 | PropertyValuesHolder holder = PropertyValuesHolder.ofInt(propertyName, startValue, endValue);
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 | int coordinateReverse = (int) animation.getAnimatedValue(ANIMATION_COORDINATE_REVERSE);
80 |
81 | value.setCoordinate(coordinate);
82 | value.setCoordinateReverse(coordinateReverse);
83 |
84 | if (listener != null) {
85 | listener.onValueUpdated(value);
86 | }
87 | }
88 |
89 | @SuppressWarnings("RedundantIfStatement")
90 | private boolean hasChanges(int coordinateStart, int coordinateEnd) {
91 | if (this.coordinateStart != coordinateStart) {
92 | return true;
93 | }
94 |
95 | if (this.coordinateEnd != coordinateEnd) {
96 | return true;
97 | }
98 |
99 | return false;
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/type/ThinWormAnimation.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.type;
2 |
3 | import android.animation.ValueAnimator;
4 | import androidx.annotation.NonNull;
5 | import android.view.animation.AccelerateDecelerateInterpolator;
6 | import com.rd.animation.controller.ValueController;
7 | import com.rd.animation.data.type.ThinWormAnimationValue;
8 |
9 | public class ThinWormAnimation extends WormAnimation {
10 |
11 | private ThinWormAnimationValue value;
12 |
13 | public ThinWormAnimation(@NonNull ValueController.UpdateListener listener) {
14 | super(listener);
15 | value = new ThinWormAnimationValue();
16 | }
17 |
18 | @Override
19 | public ThinWormAnimation duration(long duration) {
20 | super.duration(duration);
21 | return this;
22 | }
23 |
24 | @Override
25 | public WormAnimation with(int coordinateStart, int coordinateEnd, int radius, boolean isRightSide) {
26 | if (hasChanges(coordinateStart, coordinateEnd, radius, isRightSide)) {
27 | animator = createAnimator();
28 |
29 | this.coordinateStart = coordinateStart;
30 | this.coordinateEnd = coordinateEnd;
31 |
32 | this.radius = radius;
33 | this.isRightSide = isRightSide;
34 |
35 | int height = radius * 2;
36 | rectLeftEdge = coordinateStart - radius;
37 | rectRightEdge = coordinateStart + radius;
38 |
39 | value.setRectStart(rectLeftEdge);
40 | value.setRectEnd(rectRightEdge);
41 | value.setHeight(height);
42 |
43 | RectValues rec = createRectValues(isRightSide);
44 | long sizeDuration = (long) (animationDuration * 0.8);
45 | long reverseDelay = (long) (animationDuration * 0.2);
46 |
47 | long heightDuration = (long) (animationDuration * 0.5);
48 | long reverseHeightDelay = (long) (animationDuration * 0.5);
49 |
50 | ValueAnimator straightAnimator = createWormAnimator(rec.fromX, rec.toX, sizeDuration, false, value);
51 | ValueAnimator reverseAnimator = createWormAnimator(rec.reverseFromX, rec.reverseToX, sizeDuration, true, value);
52 | reverseAnimator.setStartDelay(reverseDelay);
53 |
54 | ValueAnimator straightHeightAnimator = createHeightAnimator(height, radius, heightDuration);
55 | ValueAnimator reverseHeightAnimator = createHeightAnimator(radius, height, heightDuration);
56 | reverseHeightAnimator.setStartDelay(reverseHeightDelay);
57 |
58 | animator.playTogether(straightAnimator, reverseAnimator, straightHeightAnimator, reverseHeightAnimator);
59 | }
60 | return this;
61 | }
62 |
63 | private ValueAnimator createHeightAnimator(int fromHeight, int toHeight, long duration) {
64 | ValueAnimator anim = ValueAnimator.ofInt(fromHeight, toHeight);
65 | anim.setInterpolator(new AccelerateDecelerateInterpolator());
66 | anim.setDuration(duration);
67 | anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
68 | @Override
69 | public void onAnimationUpdate(ValueAnimator animation) {
70 | onAnimateUpdated(animation);
71 | }
72 | });
73 |
74 | return anim;
75 | }
76 |
77 | private void onAnimateUpdated(@NonNull ValueAnimator animation) {
78 | value.setHeight((int) animation.getAnimatedValue());
79 |
80 | if (listener != null) {
81 | listener.onValueUpdated(value);
82 | }
83 | }
84 |
85 | @Override
86 | public ThinWormAnimation progress(float progress) {
87 | if (animator != null) {
88 | long progressDuration = (long) (progress * animationDuration);
89 | int size = animator.getChildAnimations().size();
90 |
91 | for (int i = 0; i < size; i++) {
92 | ValueAnimator anim = (ValueAnimator) animator.getChildAnimations().get(i);
93 |
94 | long setDuration = progressDuration - anim.getStartDelay();
95 | long duration = anim.getDuration();
96 |
97 | if (setDuration > duration) {
98 | setDuration = duration;
99 |
100 | } else if (setDuration < 0) {
101 | setDuration = 0;
102 | }
103 |
104 | if (i == size - 1 && setDuration <= 0) {
105 | continue;
106 | }
107 |
108 | if (anim.getValues() != null && anim.getValues().length > 0) {
109 | anim.setCurrentPlayTime(setDuration);
110 | }
111 | }
112 | }
113 |
114 | return this;
115 | }
116 | }
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/animation/type/WormAnimation.java:
--------------------------------------------------------------------------------
1 | package com.rd.animation.type;
2 |
3 | import android.animation.Animator;
4 | import android.animation.AnimatorSet;
5 | import android.animation.ValueAnimator;
6 | import androidx.annotation.NonNull;
7 | import android.view.animation.AccelerateDecelerateInterpolator;
8 | import com.rd.animation.controller.ValueController;
9 | import com.rd.animation.data.type.WormAnimationValue;
10 |
11 | public class WormAnimation extends BaseAnimation {
12 |
13 | int coordinateStart;
14 | int coordinateEnd;
15 |
16 | int radius;
17 | boolean isRightSide;
18 |
19 | int rectLeftEdge;
20 | int rectRightEdge;
21 |
22 | private WormAnimationValue value;
23 |
24 | public WormAnimation(@NonNull ValueController.UpdateListener listener) {
25 | super(listener);
26 | value = new WormAnimationValue();
27 | }
28 |
29 | @NonNull
30 | @Override
31 | public AnimatorSet createAnimator() {
32 | AnimatorSet animator = new AnimatorSet();
33 | animator.setInterpolator(new AccelerateDecelerateInterpolator());
34 |
35 | return animator;
36 | }
37 |
38 | @Override
39 | public WormAnimation duration(long duration) {
40 | super.duration(duration);
41 | return this;
42 | }
43 |
44 | public WormAnimation with(int coordinateStart, int coordinateEnd, int radius, boolean isRightSide) {
45 | if (hasChanges(coordinateStart, coordinateEnd, radius, isRightSide)) {
46 | animator = createAnimator();
47 |
48 | this.coordinateStart = coordinateStart;
49 | this.coordinateEnd = coordinateEnd;
50 |
51 | this.radius = radius;
52 | this.isRightSide = isRightSide;
53 |
54 | rectLeftEdge = coordinateStart - radius;
55 | rectRightEdge = coordinateStart + radius;
56 |
57 | value.setRectStart(rectLeftEdge);
58 | value.setRectEnd(rectRightEdge);
59 |
60 | RectValues rect = createRectValues(isRightSide);
61 | long duration = animationDuration / 2;
62 |
63 | ValueAnimator straightAnimator = createWormAnimator(rect.fromX, rect.toX, duration, false, value);
64 | ValueAnimator reverseAnimator = createWormAnimator(rect.reverseFromX, rect.reverseToX, duration, true, value);
65 | animator.playSequentially(straightAnimator, reverseAnimator);
66 | }
67 | return this;
68 | }
69 |
70 | @Override
71 | public WormAnimation progress(float progress) {
72 | if (animator == null) {
73 | return this;
74 | }
75 |
76 | long progressDuration = (long) (progress * animationDuration);
77 | for (Animator anim : animator.getChildAnimations()) {
78 | ValueAnimator animator = (ValueAnimator) anim;
79 | long duration = animator.getDuration();
80 | long setDuration = progressDuration;
81 |
82 | if (setDuration > duration) {
83 | setDuration = duration;
84 | }
85 |
86 | animator.setCurrentPlayTime(setDuration);
87 | progressDuration -= setDuration;
88 | }
89 |
90 | return this;
91 | }
92 |
93 | ValueAnimator createWormAnimator(
94 | int fromValue,
95 | int toValue,
96 | long duration,
97 | final boolean isReverse,
98 | final WormAnimationValue value) {
99 |
100 | ValueAnimator anim = ValueAnimator.ofInt(fromValue, toValue);
101 | anim.setInterpolator(new AccelerateDecelerateInterpolator());
102 | anim.setDuration(duration);
103 | anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
104 | @Override
105 | public void onAnimationUpdate(ValueAnimator animation) {
106 | onAnimateUpdated(value, animation, isReverse);
107 | }
108 | });
109 |
110 | return anim;
111 | }
112 |
113 | private void onAnimateUpdated(@NonNull WormAnimationValue value, @NonNull ValueAnimator animation, final boolean isReverse) {
114 | int rectEdge = (int) animation.getAnimatedValue();
115 |
116 | if (isRightSide) {
117 | if (!isReverse) {
118 | value.setRectEnd(rectEdge);
119 | } else {
120 | value.setRectStart(rectEdge);
121 | }
122 |
123 | } else {
124 | if (!isReverse) {
125 | value.setRectStart(rectEdge);
126 | } else {
127 | value.setRectEnd(rectEdge);
128 | }
129 | }
130 |
131 | if (listener != null) {
132 | listener.onValueUpdated(value);
133 | }
134 | }
135 |
136 | @SuppressWarnings("RedundantIfStatement")
137 | boolean hasChanges(int coordinateStart, int coordinateEnd, int radius, boolean isRightSide) {
138 | if (this.coordinateStart != coordinateStart) {
139 | return true;
140 | }
141 |
142 | if (this.coordinateEnd != coordinateEnd) {
143 | return true;
144 | }
145 |
146 | if (this.radius != radius) {
147 | return true;
148 | }
149 |
150 | if (this.isRightSide != isRightSide) {
151 | return true;
152 | }
153 |
154 | return false;
155 | }
156 |
157 | @NonNull
158 | RectValues createRectValues(boolean isRightSide) {
159 | int fromX;
160 | int toX;
161 |
162 | int reverseFromX;
163 | int reverseToX;
164 |
165 | if (isRightSide) {
166 | fromX = coordinateStart + radius;
167 | toX = coordinateEnd + radius;
168 |
169 | reverseFromX = coordinateStart - radius;
170 | reverseToX = coordinateEnd - radius;
171 |
172 | } else {
173 | fromX = coordinateStart - radius;
174 | toX = coordinateEnd - radius;
175 |
176 | reverseFromX = coordinateStart + radius;
177 | reverseToX = coordinateEnd + radius;
178 | }
179 |
180 | return new RectValues(fromX, toX, reverseFromX, reverseToX);
181 | }
182 |
183 | class RectValues {
184 |
185 | final int fromX;
186 | final int toX;
187 |
188 | final int reverseFromX;
189 | final int reverseToX;
190 |
191 | RectValues(int fromX, int toX, int reverseFromX, int reverseToX) {
192 | this.fromX = fromX;
193 | this.toX = toX;
194 |
195 | this.reverseFromX = reverseFromX;
196 | this.reverseToX = reverseToX;
197 | }
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/DrawManager.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import androidx.annotation.NonNull;
6 | import androidx.annotation.Nullable;
7 | import android.util.AttributeSet;
8 | import android.util.Pair;
9 | import android.view.MotionEvent;
10 | import com.rd.animation.data.Value;
11 | import com.rd.draw.controller.AttributeController;
12 | import com.rd.draw.controller.DrawController;
13 | import com.rd.draw.controller.MeasureController;
14 | import com.rd.draw.data.Indicator;
15 |
16 | public class DrawManager {
17 |
18 | private Indicator indicator;
19 | private DrawController drawController;
20 | private MeasureController measureController;
21 | private AttributeController attributeController;
22 |
23 | public DrawManager() {
24 | this.indicator = new Indicator();
25 | this.drawController = new DrawController(indicator);
26 | this.measureController = new MeasureController();
27 | this.attributeController = new AttributeController(indicator);
28 | }
29 |
30 | @NonNull
31 | public Indicator indicator() {
32 | if (indicator == null) {
33 | indicator = new Indicator();
34 | }
35 |
36 | return indicator;
37 | }
38 |
39 | public void setClickListener(@Nullable DrawController.ClickListener listener) {
40 | drawController.setClickListener(listener);
41 | }
42 |
43 | public void touch(@Nullable MotionEvent event) {
44 | drawController.touch(event);
45 | }
46 |
47 | public void updateValue(@Nullable Value value) {
48 | drawController.updateValue(value);
49 | }
50 |
51 | public void draw(@NonNull Canvas canvas) {
52 | drawController.draw(canvas);
53 | }
54 |
55 | public Pair measureViewSize(int widthMeasureSpec, int heightMeasureSpec) {
56 | return measureController.measureViewSize(indicator, widthMeasureSpec, heightMeasureSpec);
57 | }
58 |
59 | public void initAttributes(@NonNull Context context, @Nullable AttributeSet attrs) {
60 | attributeController.init(context, attrs);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/controller/AttributeController.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.controller;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Color;
6 | import androidx.annotation.NonNull;
7 | import androidx.annotation.Nullable;
8 | import android.util.AttributeSet;
9 | import android.view.View;
10 |
11 | import com.rd.animation.type.AnimationType;
12 | import com.rd.animation.type.BaseAnimation;
13 | import com.rd.animation.type.ColorAnimation;
14 | import com.rd.animation.type.FillAnimation;
15 | import com.rd.animation.type.ScaleAnimation;
16 | import com.rd.draw.data.Indicator;
17 | import com.rd.draw.data.Orientation;
18 | import com.rd.draw.data.RtlMode;
19 | import com.rd.pageindicatorview.R;
20 | import com.rd.utils.DensityUtils;
21 |
22 | public class AttributeController {
23 |
24 | private Indicator indicator;
25 |
26 | private static final int DEFAULT_IDLE_DURATION = 3000;
27 |
28 | public AttributeController(@NonNull Indicator indicator) {
29 | this.indicator = indicator;
30 | }
31 |
32 | public void init(@NonNull Context context, @Nullable AttributeSet attrs) {
33 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PageIndicatorView, 0, 0);
34 | initCountAttribute(typedArray);
35 | initColorAttribute(typedArray);
36 | initAnimationAttribute(typedArray);
37 | initSizeAttribute(typedArray);
38 | typedArray.recycle();
39 | }
40 |
41 | private void initCountAttribute(@NonNull TypedArray typedArray) {
42 | int viewPagerId = typedArray.getResourceId(R.styleable.PageIndicatorView_piv_viewPager, View.NO_ID);
43 | boolean autoVisibility = typedArray.getBoolean(R.styleable.PageIndicatorView_piv_autoVisibility, true);
44 | boolean dynamicCount = typedArray.getBoolean(R.styleable.PageIndicatorView_piv_dynamicCount, false);
45 | int count = typedArray.getInt(R.styleable.PageIndicatorView_piv_count, Indicator.COUNT_NONE);
46 |
47 | if (count == Indicator.COUNT_NONE) {
48 | count = Indicator.DEFAULT_COUNT;
49 | }
50 |
51 | int position = typedArray.getInt(R.styleable.PageIndicatorView_piv_select, 0);
52 | if (position < 0) {
53 | position = 0;
54 | } else if (count > 0 && position > count - 1) {
55 | position = count - 1;
56 | }
57 |
58 | indicator.setViewPagerId(viewPagerId);
59 | indicator.setAutoVisibility(autoVisibility);
60 | indicator.setDynamicCount(dynamicCount);
61 | indicator.setCount(count);
62 |
63 | indicator.setSelectedPosition(position);
64 | indicator.setSelectingPosition(position);
65 | indicator.setLastSelectedPosition(position);
66 | }
67 |
68 | private void initColorAttribute(@NonNull TypedArray typedArray) {
69 | int unselectedColor = typedArray.getColor(R.styleable.PageIndicatorView_piv_unselectedColor, Color.parseColor(ColorAnimation.DEFAULT_UNSELECTED_COLOR));
70 | int selectedColor = typedArray.getColor(R.styleable.PageIndicatorView_piv_selectedColor, Color.parseColor(ColorAnimation.DEFAULT_SELECTED_COLOR));
71 |
72 | indicator.setUnselectedColor(unselectedColor);
73 | indicator.setSelectedColor(selectedColor);
74 | }
75 |
76 | private void initAnimationAttribute(@NonNull TypedArray typedArray) {
77 | boolean interactiveAnimation = typedArray.getBoolean(R.styleable.PageIndicatorView_piv_interactiveAnimation, false);
78 | long animationDuration = (long) typedArray.getInt(R.styleable.PageIndicatorView_piv_animationDuration, BaseAnimation.DEFAULT_ANIMATION_TIME);
79 | if (animationDuration < 0) {
80 | animationDuration = 0;
81 | }
82 |
83 | int animIndex = typedArray.getInt(R.styleable.PageIndicatorView_piv_animationType, AnimationType.NONE.ordinal());
84 | AnimationType animationType = getAnimationType(animIndex);
85 |
86 | int rtlIndex = typedArray.getInt(R.styleable.PageIndicatorView_piv_rtl_mode, RtlMode.Off.ordinal());
87 | RtlMode rtlMode = getRtlMode(rtlIndex);
88 |
89 | boolean fadeOnIdle = typedArray.getBoolean(R.styleable.PageIndicatorView_piv_fadeOnIdle, false);
90 | long idleDuration = (long) typedArray.getInt(R.styleable.PageIndicatorView_piv_idleDuration, DEFAULT_IDLE_DURATION);
91 |
92 | indicator.setAnimationDuration(animationDuration);
93 | indicator.setInteractiveAnimation(interactiveAnimation);
94 | indicator.setAnimationType(animationType);
95 | indicator.setRtlMode(rtlMode);
96 | indicator.setFadeOnIdle(fadeOnIdle);
97 | indicator.setIdleDuration(idleDuration);
98 | }
99 |
100 | private void initSizeAttribute(@NonNull TypedArray typedArray) {
101 | int orientationIndex = typedArray.getInt(R.styleable.PageIndicatorView_piv_orientation, Orientation.HORIZONTAL.ordinal());
102 | Orientation orientation;
103 |
104 | if (orientationIndex == 0) {
105 | orientation = Orientation.HORIZONTAL;
106 | } else {
107 | orientation = Orientation.VERTICAL;
108 | }
109 |
110 | int radius = (int) typedArray.getDimension(R.styleable.PageIndicatorView_piv_radius, DensityUtils.dpToPx(Indicator.DEFAULT_RADIUS_DP));
111 | if (radius < 0) {
112 | radius = 0;
113 | }
114 |
115 | int padding = (int) typedArray.getDimension(R.styleable.PageIndicatorView_piv_padding, DensityUtils.dpToPx(Indicator.DEFAULT_PADDING_DP));
116 | if (padding < 0) {
117 | padding = 0;
118 | }
119 |
120 | float scaleFactor = typedArray.getFloat(R.styleable.PageIndicatorView_piv_scaleFactor, ScaleAnimation.DEFAULT_SCALE_FACTOR);
121 | if (scaleFactor < ScaleAnimation.MIN_SCALE_FACTOR) {
122 | scaleFactor = ScaleAnimation.MIN_SCALE_FACTOR;
123 |
124 | } else if (scaleFactor > ScaleAnimation.MAX_SCALE_FACTOR) {
125 | scaleFactor = ScaleAnimation.MAX_SCALE_FACTOR;
126 | }
127 |
128 | int stroke = (int) typedArray.getDimension(R.styleable.PageIndicatorView_piv_strokeWidth, DensityUtils.dpToPx(FillAnimation.DEFAULT_STROKE_DP));
129 | if (stroke > radius) {
130 | stroke = radius;
131 | }
132 |
133 | if (indicator.getAnimationType() != AnimationType.FILL) {
134 | stroke = 0;
135 | }
136 |
137 | indicator.setRadius(radius);
138 | indicator.setOrientation(orientation);
139 | indicator.setPadding(padding);
140 | indicator.setScaleFactor(scaleFactor);
141 | indicator.setStroke(stroke);
142 | }
143 |
144 | private AnimationType getAnimationType(int index) {
145 | switch (index) {
146 | case 0:
147 | return AnimationType.NONE;
148 | case 1:
149 | return AnimationType.COLOR;
150 | case 2:
151 | return AnimationType.SCALE;
152 | case 3:
153 | return AnimationType.WORM;
154 | case 4:
155 | return AnimationType.SLIDE;
156 | case 5:
157 | return AnimationType.FILL;
158 | case 6:
159 | return AnimationType.THIN_WORM;
160 | case 7:
161 | return AnimationType.DROP;
162 | case 8:
163 | return AnimationType.SWAP;
164 | case 9:
165 | return AnimationType.SCALE_DOWN;
166 | }
167 |
168 | return AnimationType.NONE;
169 | }
170 |
171 | private RtlMode getRtlMode(int index) {
172 | switch (index) {
173 | case 0:
174 | return RtlMode.On;
175 | case 1:
176 | return RtlMode.Off;
177 | case 2:
178 | return RtlMode.Auto;
179 | }
180 |
181 | return RtlMode.Auto;
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/controller/DrawController.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.controller;
2 |
3 | import android.graphics.Canvas;
4 | import androidx.annotation.NonNull;
5 | import androidx.annotation.Nullable;
6 | import android.view.MotionEvent;
7 | import com.rd.animation.data.Value;
8 | import com.rd.animation.type.AnimationType;
9 | import com.rd.draw.data.Indicator;
10 | import com.rd.draw.drawer.Drawer;
11 | import com.rd.utils.CoordinatesUtils;
12 |
13 | public class DrawController {
14 |
15 | private Value value;
16 | private Drawer drawer;
17 | private Indicator indicator;
18 | private ClickListener listener;
19 |
20 | public interface ClickListener {
21 |
22 | void onIndicatorClicked(int position);
23 | }
24 |
25 | public DrawController(@NonNull Indicator indicator) {
26 | this.indicator = indicator;
27 | this.drawer = new Drawer(indicator);
28 | }
29 |
30 | public void updateValue(@Nullable Value value) {
31 | this.value = value;
32 | }
33 |
34 | public void setClickListener(@Nullable ClickListener listener) {
35 | this.listener = listener;
36 | }
37 |
38 | public void touch(@Nullable MotionEvent event) {
39 | if (event == null) {
40 | return;
41 | }
42 |
43 | switch (event.getAction()) {
44 | case MotionEvent.ACTION_UP:
45 | onIndicatorTouched(event.getX(), event.getY());
46 | break;
47 | default:
48 | }
49 | }
50 |
51 | private void onIndicatorTouched(float x, float y) {
52 | if (listener != null) {
53 | int position = CoordinatesUtils.getPosition(indicator, x, y);
54 | if (position >= 0) {
55 | listener.onIndicatorClicked(position);
56 | }
57 | }
58 | }
59 |
60 | public void draw(@NonNull Canvas canvas) {
61 | int count = indicator.getCount();
62 |
63 | for (int position = 0; position < count; position++) {
64 | int coordinateX = CoordinatesUtils.getXCoordinate(indicator, position);
65 | int coordinateY = CoordinatesUtils.getYCoordinate(indicator, position);
66 | drawIndicator(canvas, position, coordinateX, coordinateY);
67 | }
68 | }
69 |
70 | private void drawIndicator(
71 | @NonNull Canvas canvas,
72 | int position,
73 | int coordinateX,
74 | int coordinateY) {
75 |
76 | boolean interactiveAnimation = indicator.isInteractiveAnimation();
77 | int selectedPosition = indicator.getSelectedPosition();
78 | int selectingPosition = indicator.getSelectingPosition();
79 | int lastSelectedPosition = indicator.getLastSelectedPosition();
80 |
81 | boolean selectedItem = !interactiveAnimation && (position == selectedPosition || position == lastSelectedPosition);
82 | boolean selectingItem = interactiveAnimation && (position == selectedPosition || position == selectingPosition);
83 | boolean isSelectedItem = selectedItem | selectingItem;
84 | drawer.setup(position, coordinateX, coordinateY);
85 |
86 | if (value != null && isSelectedItem) {
87 | drawWithAnimation(canvas);
88 | } else {
89 | drawer.drawBasic(canvas, isSelectedItem);
90 | }
91 | }
92 |
93 | private void drawWithAnimation(@NonNull Canvas canvas) {
94 | AnimationType animationType = indicator.getAnimationType();
95 | switch (animationType) {
96 | case NONE:
97 | drawer.drawBasic(canvas, true);
98 | break;
99 |
100 | case COLOR:
101 | drawer.drawColor(canvas, value);
102 | break;
103 |
104 | case SCALE:
105 | drawer.drawScale(canvas, value);
106 | break;
107 |
108 | case WORM:
109 | drawer.drawWorm(canvas, value);
110 | break;
111 |
112 | case SLIDE:
113 | drawer.drawSlide(canvas, value);
114 | break;
115 |
116 | case FILL:
117 | drawer.drawFill(canvas, value);
118 | break;
119 |
120 | case THIN_WORM:
121 | drawer.drawThinWorm(canvas, value);
122 | break;
123 |
124 | case DROP:
125 | drawer.drawDrop(canvas, value);
126 | break;
127 |
128 | case SWAP:
129 | drawer.drawSwap(canvas, value);
130 | break;
131 |
132 | case SCALE_DOWN:
133 | drawer.drawScaleDown(canvas, value);
134 | break;
135 | }
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/controller/MeasureController.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.controller;
2 |
3 | import androidx.annotation.NonNull;
4 | import android.util.Pair;
5 | import android.view.View;
6 | import com.rd.animation.type.AnimationType;
7 | import com.rd.draw.data.Indicator;
8 | import com.rd.draw.data.Orientation;
9 |
10 | public class MeasureController {
11 |
12 | public Pair measureViewSize(@NonNull Indicator indicator, int widthMeasureSpec, int heightMeasureSpec) {
13 | int widthMode = View.MeasureSpec.getMode(widthMeasureSpec);
14 | int widthSize = View.MeasureSpec.getSize(widthMeasureSpec);
15 |
16 | int heightMode = View.MeasureSpec.getMode(heightMeasureSpec);
17 | int heightSize = View.MeasureSpec.getSize(heightMeasureSpec);
18 |
19 | int count = indicator.getCount();
20 | int radius = indicator.getRadius();
21 | int stroke = indicator.getStroke();
22 |
23 | int padding = indicator.getPadding();
24 | int paddingLeft = indicator.getPaddingLeft();
25 | int paddingTop = indicator.getPaddingTop();
26 | int paddingRight = indicator.getPaddingRight();
27 | int paddingBottom = indicator.getPaddingBottom();
28 |
29 | int circleDiameterPx = radius * 2;
30 | int desiredWidth = 0;
31 | int desiredHeight = 0;
32 |
33 | int width;
34 | int height;
35 |
36 | Orientation orientation = indicator.getOrientation();
37 | if (count != 0) {
38 | int diameterSum = circleDiameterPx * count;
39 | int strokeSum = (stroke * 2) * count;
40 |
41 | int paddingSum = padding * (count - 1);
42 | int w = diameterSum + strokeSum + paddingSum;
43 | int h = circleDiameterPx + stroke;
44 |
45 | if (orientation == Orientation.HORIZONTAL) {
46 | desiredWidth = w;
47 | desiredHeight = h;
48 |
49 | } else {
50 | desiredWidth = h;
51 | desiredHeight = w;
52 | }
53 | }
54 |
55 | if (indicator.getAnimationType() == AnimationType.DROP) {
56 | if (orientation == Orientation.HORIZONTAL) {
57 | desiredHeight *= 2;
58 | } else {
59 | desiredWidth *= 2;
60 | }
61 | }
62 |
63 | int horizontalPadding = paddingLeft + paddingRight;
64 | int verticalPadding = paddingTop + paddingBottom;
65 |
66 | if (orientation == Orientation.HORIZONTAL) {
67 | desiredWidth += horizontalPadding;
68 | desiredHeight += verticalPadding;
69 |
70 | } else {
71 | desiredWidth += horizontalPadding;
72 | desiredHeight += verticalPadding;
73 | }
74 |
75 | if (widthMode == View.MeasureSpec.EXACTLY) {
76 | width = widthSize;
77 | } else if (widthMode == View.MeasureSpec.AT_MOST) {
78 | width = Math.min(desiredWidth, widthSize);
79 | } else {
80 | width = desiredWidth;
81 | }
82 |
83 | if (heightMode == View.MeasureSpec.EXACTLY) {
84 | height = heightSize;
85 | } else if (heightMode == View.MeasureSpec.AT_MOST) {
86 | height = Math.min(desiredHeight, heightSize);
87 | } else {
88 | height = desiredHeight;
89 | }
90 |
91 | if (width < 0) {
92 | width = 0;
93 | }
94 |
95 | if (height < 0) {
96 | height = 0;
97 | }
98 |
99 | indicator.setWidth(width);
100 | indicator.setHeight(height);
101 |
102 | return new Pair<>(width, height);
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/data/Indicator.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.data;
2 |
3 | import androidx.annotation.NonNull;
4 | import android.view.View;
5 | import com.rd.animation.type.AnimationType;
6 |
7 | public class Indicator {
8 |
9 | public static final int DEFAULT_COUNT = 3;
10 | public static final int MIN_COUNT = 1;
11 | public static final int COUNT_NONE = -1;
12 |
13 | public static final int DEFAULT_RADIUS_DP = 6;
14 | public static final int DEFAULT_PADDING_DP = 8;
15 | public static final int IDLE_ANIMATION_DURATION = 250;
16 |
17 | private int height;
18 | private int width;
19 | private int radius;
20 |
21 | private int padding;
22 | private int paddingLeft;
23 | private int paddingTop;
24 | private int paddingRight;
25 | private int paddingBottom;
26 |
27 | private int stroke; //For "Fill" animation only
28 | private float scaleFactor; //For "Scale" animation only
29 |
30 | private int unselectedColor;
31 | private int selectedColor;
32 |
33 | private boolean interactiveAnimation;
34 | private boolean autoVisibility;
35 | private boolean dynamicCount;
36 |
37 | private boolean fadeOnIdle;
38 | private boolean isIdle;
39 | private long idleDuration;
40 |
41 | private long animationDuration;
42 | private int count = DEFAULT_COUNT;
43 |
44 | private int selectedPosition;
45 | private int selectingPosition;
46 | private int lastSelectedPosition;
47 |
48 | private int viewPagerId = View.NO_ID;
49 |
50 | private Orientation orientation;
51 | private AnimationType animationType;
52 | private RtlMode rtlMode;
53 |
54 | public int getHeight() {
55 | return height;
56 | }
57 |
58 | public void setHeight(int height) {
59 | this.height = height;
60 | }
61 |
62 | public int getWidth() {
63 | return width;
64 | }
65 |
66 | public void setWidth(int width) {
67 | this.width = width;
68 | }
69 |
70 | public int getRadius() {
71 | return radius;
72 | }
73 |
74 | public void setRadius(int radius) {
75 | this.radius = radius;
76 | }
77 |
78 | public int getPadding() {
79 | return padding;
80 | }
81 |
82 | public void setPadding(int padding) {
83 | this.padding = padding;
84 | }
85 |
86 | public int getPaddingLeft() {
87 | return paddingLeft;
88 | }
89 |
90 | public void setPaddingLeft(int paddingLeft) {
91 | this.paddingLeft = paddingLeft;
92 | }
93 |
94 | public int getPaddingTop() {
95 | return paddingTop;
96 | }
97 |
98 | public void setPaddingTop(int paddingTop) {
99 | this.paddingTop = paddingTop;
100 | }
101 |
102 | public int getPaddingRight() {
103 | return paddingRight;
104 | }
105 |
106 | public void setPaddingRight(int paddingRight) {
107 | this.paddingRight = paddingRight;
108 | }
109 |
110 | public int getPaddingBottom() {
111 | return paddingBottom;
112 | }
113 |
114 | public void setPaddingBottom(int paddingBottom) {
115 | this.paddingBottom = paddingBottom;
116 | }
117 |
118 | public int getStroke() {
119 | return stroke;
120 | }
121 |
122 | public void setStroke(int stroke) {
123 | this.stroke = stroke;
124 | }
125 |
126 | public float getScaleFactor() {
127 | return scaleFactor;
128 | }
129 |
130 | public void setScaleFactor(float scaleFactor) {
131 | this.scaleFactor = scaleFactor;
132 | }
133 |
134 | public int getUnselectedColor() {
135 | return unselectedColor;
136 | }
137 |
138 | public void setUnselectedColor(int unselectedColor) {
139 | this.unselectedColor = unselectedColor;
140 | }
141 |
142 | public int getSelectedColor() {
143 | return selectedColor;
144 | }
145 |
146 | public void setSelectedColor(int selectedColor) {
147 | this.selectedColor = selectedColor;
148 | }
149 |
150 | public boolean isInteractiveAnimation() {
151 | return interactiveAnimation;
152 | }
153 |
154 | public void setInteractiveAnimation(boolean interactiveAnimation) {
155 | this.interactiveAnimation = interactiveAnimation;
156 | }
157 |
158 | public boolean isAutoVisibility() {
159 | return autoVisibility;
160 | }
161 |
162 | public void setAutoVisibility(boolean autoVisibility) {
163 | this.autoVisibility = autoVisibility;
164 | }
165 |
166 | public boolean isDynamicCount() {
167 | return dynamicCount;
168 | }
169 |
170 | public void setDynamicCount(boolean dynamicCount) {
171 | this.dynamicCount = dynamicCount;
172 | }
173 |
174 | public boolean isFadeOnIdle() {
175 | return fadeOnIdle;
176 | }
177 |
178 | public void setFadeOnIdle(boolean fadeOnIdle) {
179 | this.fadeOnIdle = fadeOnIdle;
180 | }
181 |
182 | public boolean isIdle() {
183 | return isIdle;
184 | }
185 |
186 | public void setIdle(boolean idle) {
187 | isIdle = idle;
188 | }
189 |
190 | public long getIdleDuration() {
191 | return idleDuration;
192 | }
193 |
194 | public void setIdleDuration(long idleDuration) {
195 | this.idleDuration = idleDuration;
196 | }
197 |
198 | public long getAnimationDuration() {
199 | return animationDuration;
200 | }
201 |
202 | public void setAnimationDuration(long animationDuration) {
203 | this.animationDuration = animationDuration;
204 | }
205 |
206 | public int getCount() {
207 | return count;
208 | }
209 |
210 | public void setCount(int count) {
211 | this.count = count;
212 | }
213 |
214 | public int getSelectedPosition() {
215 | return selectedPosition;
216 | }
217 |
218 | public void setSelectedPosition(int selectedPosition) {
219 | this.selectedPosition = selectedPosition;
220 | }
221 |
222 | public int getSelectingPosition() {
223 | return selectingPosition;
224 | }
225 |
226 | public void setSelectingPosition(int selectingPosition) {
227 | this.selectingPosition = selectingPosition;
228 | }
229 |
230 | public int getLastSelectedPosition() {
231 | return lastSelectedPosition;
232 | }
233 |
234 | public void setLastSelectedPosition(int lastSelectedPosition) {
235 | this.lastSelectedPosition = lastSelectedPosition;
236 | }
237 |
238 | public int getViewPagerId() {
239 | return viewPagerId;
240 | }
241 |
242 | public void setViewPagerId(int viewPagerId) {
243 | this.viewPagerId = viewPagerId;
244 | }
245 |
246 | @NonNull
247 | public Orientation getOrientation() {
248 | if (orientation == null) {
249 | orientation = Orientation.HORIZONTAL;
250 | }
251 | return orientation;
252 | }
253 |
254 | public void setOrientation(Orientation orientation) {
255 | this.orientation = orientation;
256 | }
257 |
258 | @NonNull
259 | public AnimationType getAnimationType() {
260 | if (animationType == null) {
261 | animationType = AnimationType.NONE;
262 | }
263 | return animationType;
264 | }
265 |
266 | public void setAnimationType(AnimationType animationType) {
267 | this.animationType = animationType;
268 | }
269 |
270 | @NonNull
271 | public RtlMode getRtlMode() {
272 | if (rtlMode == null) {
273 | rtlMode = RtlMode.Off;
274 | }
275 | return rtlMode;
276 | }
277 |
278 | public void setRtlMode(RtlMode rtlMode) {
279 | this.rtlMode = rtlMode;
280 | }
281 | }
282 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/data/Orientation.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.data;
2 |
3 | public enum Orientation {HORIZONTAL, VERTICAL}
4 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/data/PositionSavedState.java:
--------------------------------------------------------------------------------
1 | package com.rd.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 Parcelable.Creator CREATOR = new Parcelable.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 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/data/RtlMode.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.data;
2 |
3 | public enum RtlMode {On, Off, Auto}
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/drawer/Drawer.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.drawer;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import androidx.annotation.NonNull;
6 | import com.rd.animation.data.Value;
7 | import com.rd.draw.data.Indicator;
8 | import com.rd.draw.drawer.type.*;
9 |
10 | public class Drawer {
11 |
12 | private BasicDrawer basicDrawer;
13 | private ColorDrawer colorDrawer;
14 | private ScaleDrawer scaleDrawer;
15 | private WormDrawer wormDrawer;
16 | private SlideDrawer slideDrawer;
17 | private FillDrawer fillDrawer;
18 | private ThinWormDrawer thinWormDrawer;
19 | private DropDrawer dropDrawer;
20 | private SwapDrawer swapDrawer;
21 | private ScaleDownDrawer scaleDownDrawer;
22 |
23 | private int position;
24 | private int coordinateX;
25 | private int coordinateY;
26 |
27 | public Drawer(@NonNull Indicator indicator) {
28 | Paint paint = new Paint();
29 | paint.setStyle(Paint.Style.FILL);
30 | paint.setAntiAlias(true);
31 |
32 | basicDrawer = new BasicDrawer(paint, indicator);
33 | colorDrawer = new ColorDrawer(paint, indicator);
34 | scaleDrawer = new ScaleDrawer(paint, indicator);
35 | wormDrawer = new WormDrawer(paint, indicator);
36 | slideDrawer = new SlideDrawer(paint, indicator);
37 | fillDrawer = new FillDrawer(paint, indicator);
38 | thinWormDrawer = new ThinWormDrawer(paint, indicator);
39 | dropDrawer = new DropDrawer(paint, indicator);
40 | swapDrawer = new SwapDrawer(paint, indicator);
41 | scaleDownDrawer = new ScaleDownDrawer(paint, indicator);
42 | }
43 |
44 | public void setup(int position, int coordinateX, int coordinateY) {
45 | this.position = position;
46 | this.coordinateX = coordinateX;
47 | this.coordinateY = coordinateY;
48 | }
49 |
50 | public void drawBasic(@NonNull Canvas canvas, boolean isSelectedItem) {
51 | if (colorDrawer != null) {
52 | basicDrawer.draw(canvas, position, isSelectedItem, coordinateX, coordinateY);
53 | }
54 | }
55 |
56 | public void drawColor(@NonNull Canvas canvas, @NonNull Value value) {
57 | if (colorDrawer != null) {
58 | colorDrawer.draw(canvas, value, position, coordinateX, coordinateY);
59 | }
60 | }
61 |
62 | public void drawScale(@NonNull Canvas canvas, @NonNull Value value) {
63 | if (scaleDrawer != null) {
64 | scaleDrawer.draw(canvas, value, position, coordinateX, coordinateY);
65 | }
66 | }
67 |
68 | public void drawWorm(@NonNull Canvas canvas, @NonNull Value value) {
69 | if (wormDrawer != null) {
70 | wormDrawer.draw(canvas, value, coordinateX, coordinateY);
71 | }
72 | }
73 |
74 | public void drawSlide(@NonNull Canvas canvas, @NonNull Value value) {
75 | if (slideDrawer != null) {
76 | slideDrawer.draw(canvas, value, coordinateX, coordinateY);
77 | }
78 | }
79 |
80 | public void drawFill(@NonNull Canvas canvas, @NonNull Value value) {
81 | if (fillDrawer != null) {
82 | fillDrawer.draw(canvas, value, position, coordinateX, coordinateY);
83 | }
84 | }
85 |
86 | public void drawThinWorm(@NonNull Canvas canvas, @NonNull Value value) {
87 | if (thinWormDrawer != null) {
88 | thinWormDrawer.draw(canvas, value, coordinateX, coordinateY);
89 | }
90 | }
91 |
92 | public void drawDrop(@NonNull Canvas canvas, @NonNull Value value) {
93 | if (dropDrawer != null) {
94 | dropDrawer.draw(canvas, value, coordinateX, coordinateY);
95 | }
96 | }
97 |
98 | public void drawSwap(@NonNull Canvas canvas, @NonNull Value value) {
99 | if (swapDrawer != null) {
100 | swapDrawer.draw(canvas, value, position, coordinateX, coordinateY);
101 | }
102 | }
103 |
104 | public void drawScaleDown(@NonNull Canvas canvas, @NonNull Value value) {
105 | if (scaleDownDrawer != null) {
106 | scaleDownDrawer.draw(canvas, value, position, coordinateX, coordinateY);
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/drawer/type/BaseDrawer.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.drawer.type;
2 |
3 | import android.graphics.Paint;
4 | import androidx.annotation.NonNull;
5 | import com.rd.draw.data.Indicator;
6 |
7 | class BaseDrawer {
8 |
9 | Paint paint;
10 | Indicator indicator;
11 |
12 | BaseDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
13 | this.paint = paint;
14 | this.indicator = indicator;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/drawer/type/BasicDrawer.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import androidx.annotation.NonNull;
6 | import com.rd.animation.type.AnimationType;
7 | import com.rd.draw.data.Indicator;
8 |
9 | public class BasicDrawer extends BaseDrawer {
10 |
11 | private Paint strokePaint;
12 |
13 | public BasicDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
14 | super(paint, indicator);
15 |
16 | strokePaint = new Paint();
17 | strokePaint.setStyle(Paint.Style.STROKE);
18 | strokePaint.setAntiAlias(true);
19 | strokePaint.setStrokeWidth(indicator.getStroke());
20 | }
21 |
22 | public void draw(
23 | @NonNull Canvas canvas,
24 | int position,
25 | boolean isSelectedItem,
26 | int coordinateX,
27 | int coordinateY) {
28 |
29 | float radius = indicator.getRadius();
30 | int strokePx = indicator.getStroke();
31 | float scaleFactor = indicator.getScaleFactor();
32 |
33 | int selectedColor = indicator.getSelectedColor();
34 | int unselectedColor = indicator.getUnselectedColor();
35 | int selectedPosition = indicator.getSelectedPosition();
36 | AnimationType animationType = indicator.getAnimationType();
37 |
38 | if (animationType == AnimationType.SCALE && !isSelectedItem) {
39 | radius *= scaleFactor;
40 |
41 | } else if (animationType == AnimationType.SCALE_DOWN && isSelectedItem) {
42 | radius *= scaleFactor;
43 | }
44 |
45 | int color = unselectedColor;
46 | if (position == selectedPosition) {
47 | color = selectedColor;
48 | }
49 |
50 | Paint paint;
51 | if (animationType == AnimationType.FILL && position != selectedPosition) {
52 | paint = strokePaint;
53 | paint.setStrokeWidth(strokePx);
54 | } else {
55 | paint = this.paint;
56 | }
57 |
58 | paint.setColor(color);
59 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/drawer/type/ColorDrawer.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import androidx.annotation.NonNull;
6 | import com.rd.animation.data.Value;
7 | import com.rd.animation.data.type.ColorAnimationValue;
8 | import com.rd.draw.data.Indicator;
9 |
10 | public class ColorDrawer extends BaseDrawer {
11 |
12 | public ColorDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
13 | super(paint, indicator);
14 | }
15 |
16 | public void draw(@NonNull Canvas canvas,
17 | @NonNull Value value,
18 | int position,
19 | int coordinateX,
20 | int coordinateY) {
21 |
22 | if (!(value instanceof ColorAnimationValue)) {
23 | return;
24 | }
25 |
26 | ColorAnimationValue v = (ColorAnimationValue) value;
27 | float radius = indicator.getRadius();
28 | int color = indicator.getSelectedColor();
29 |
30 | int selectedPosition = indicator.getSelectedPosition();
31 | int selectingPosition = indicator.getSelectingPosition();
32 | int lastSelectedPosition = indicator.getLastSelectedPosition();
33 |
34 | if (indicator.isInteractiveAnimation()) {
35 | if (position == selectingPosition) {
36 | color = v.getColor();
37 |
38 | } else if (position == selectedPosition) {
39 | color = v.getColorReverse();
40 | }
41 |
42 | } else {
43 | if (position == selectedPosition) {
44 | color = v.getColor();
45 |
46 | } else if (position == lastSelectedPosition) {
47 | color = v.getColorReverse();
48 | }
49 | }
50 |
51 | paint.setColor(color);
52 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/drawer/type/DropDrawer.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import androidx.annotation.NonNull;
6 | import com.rd.animation.data.Value;
7 | import com.rd.animation.data.type.DropAnimationValue;
8 | import com.rd.draw.data.Indicator;
9 | import com.rd.draw.data.Orientation;
10 |
11 | public class DropDrawer extends BaseDrawer {
12 |
13 | public DropDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
14 | super(paint, indicator);
15 | }
16 |
17 | public void draw(
18 | @NonNull Canvas canvas,
19 | @NonNull Value value,
20 | int coordinateX,
21 | int coordinateY) {
22 |
23 | if (!(value instanceof DropAnimationValue)) {
24 | return;
25 | }
26 |
27 | DropAnimationValue v = (DropAnimationValue) value;
28 | int unselectedColor = indicator.getUnselectedColor();
29 | int selectedColor = indicator.getSelectedColor();
30 | float radius = indicator.getRadius();
31 |
32 | paint.setColor(unselectedColor);
33 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
34 |
35 | paint.setColor(selectedColor);
36 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
37 | canvas.drawCircle(v.getWidth(), v.getHeight(), v.getRadius(), paint);
38 | } else {
39 | canvas.drawCircle(v.getHeight(), v.getWidth(), v.getRadius(), paint);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/drawer/type/FillDrawer.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import androidx.annotation.NonNull;
6 | import com.rd.animation.data.Value;
7 | import com.rd.animation.data.type.FillAnimationValue;
8 | import com.rd.draw.data.Indicator;
9 |
10 | public class FillDrawer extends BaseDrawer {
11 |
12 | private Paint strokePaint;
13 |
14 | public FillDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
15 | super(paint, indicator);
16 |
17 | strokePaint = new Paint();
18 | strokePaint.setStyle(Paint.Style.STROKE);
19 | strokePaint.setAntiAlias(true);
20 | }
21 |
22 | public void draw(
23 | @NonNull Canvas canvas,
24 | @NonNull Value value,
25 | int position,
26 | int coordinateX,
27 | int coordinateY) {
28 |
29 | if (!(value instanceof FillAnimationValue)) {
30 | return;
31 | }
32 |
33 | FillAnimationValue v = (FillAnimationValue) value;
34 | int color = indicator.getUnselectedColor();
35 | float radius = indicator.getRadius();
36 | int stroke = indicator.getStroke();
37 |
38 | int selectedPosition = indicator.getSelectedPosition();
39 | int selectingPosition = indicator.getSelectingPosition();
40 | int lastSelectedPosition = indicator.getLastSelectedPosition();
41 |
42 | if (indicator.isInteractiveAnimation()) {
43 | if (position == selectingPosition) {
44 | color = v.getColor();
45 | radius = v.getRadius();
46 | stroke = v.getStroke();
47 |
48 | } else if (position == selectedPosition) {
49 | color = v.getColorReverse();
50 | radius = v.getRadiusReverse();
51 | stroke = v.getStrokeReverse();
52 | }
53 |
54 | } else {
55 | if (position == selectedPosition) {
56 | color = v.getColor();
57 | radius = v.getRadius();
58 | stroke = v.getStroke();
59 |
60 | } else if (position == lastSelectedPosition) {
61 | color = v.getColorReverse();
62 | radius = v.getRadiusReverse();
63 | stroke = v.getStrokeReverse();
64 | }
65 | }
66 |
67 | strokePaint.setColor(color);
68 | strokePaint.setStrokeWidth(indicator.getStroke());
69 | canvas.drawCircle(coordinateX, coordinateY, indicator.getRadius(), strokePaint);
70 |
71 | strokePaint.setStrokeWidth(stroke);
72 | canvas.drawCircle(coordinateX, coordinateY, radius, strokePaint);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/drawer/type/ScaleDownDrawer.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import androidx.annotation.NonNull;
6 | import com.rd.animation.data.Value;
7 | import com.rd.animation.data.type.ScaleAnimationValue;
8 | import com.rd.draw.data.Indicator;
9 |
10 | public class ScaleDownDrawer extends BaseDrawer {
11 |
12 | public ScaleDownDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
13 | super(paint, indicator);
14 | }
15 |
16 | public void draw(
17 | @NonNull Canvas canvas,
18 | @NonNull Value value,
19 | int position,
20 | int coordinateX,
21 | int coordinateY) {
22 |
23 | if (!(value instanceof ScaleAnimationValue)) {
24 | return;
25 | }
26 |
27 | ScaleAnimationValue v = (ScaleAnimationValue) value;
28 | float radius = indicator.getRadius();
29 | int color = indicator.getSelectedColor();
30 |
31 | int selectedPosition = indicator.getSelectedPosition();
32 | int selectingPosition = indicator.getSelectingPosition();
33 | int lastSelectedPosition = indicator.getLastSelectedPosition();
34 |
35 | if (indicator.isInteractiveAnimation()) {
36 | if (position == selectingPosition) {
37 | radius = v.getRadius();
38 | color = v.getColor();
39 |
40 | } else if (position == selectedPosition) {
41 | radius = v.getRadiusReverse();
42 | color = v.getColorReverse();
43 | }
44 |
45 | } else {
46 | if (position == selectedPosition) {
47 | radius = v.getRadius();
48 | color = v.getColor();
49 |
50 | } else if (position == lastSelectedPosition) {
51 | radius = v.getRadiusReverse();
52 | color = v.getColorReverse();
53 | }
54 | }
55 |
56 | paint.setColor(color);
57 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/drawer/type/ScaleDrawer.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import androidx.annotation.NonNull;
6 | import com.rd.animation.data.Value;
7 | import com.rd.animation.data.type.ScaleAnimationValue;
8 | import com.rd.draw.data.Indicator;
9 |
10 | public class ScaleDrawer extends BaseDrawer {
11 |
12 | public ScaleDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
13 | super(paint, indicator);
14 | }
15 |
16 | public void draw(
17 | @NonNull Canvas canvas,
18 | @NonNull Value value,
19 | int position,
20 | int coordinateX,
21 | int coordinateY) {
22 |
23 | if (!(value instanceof ScaleAnimationValue)) {
24 | return;
25 | }
26 |
27 | ScaleAnimationValue v = (ScaleAnimationValue) value;
28 | float radius = indicator.getRadius();
29 | int color = indicator.getSelectedColor();
30 |
31 | int selectedPosition = indicator.getSelectedPosition();
32 | int selectingPosition = indicator.getSelectingPosition();
33 | int lastSelectedPosition = indicator.getLastSelectedPosition();
34 |
35 | if (indicator.isInteractiveAnimation()) {
36 | if (position == selectingPosition) {
37 | radius = v.getRadius();
38 | color = v.getColor();
39 |
40 | } else if (position == selectedPosition) {
41 | radius = v.getRadiusReverse();
42 | color = v.getColorReverse();
43 | }
44 |
45 | } else {
46 | if (position == selectedPosition) {
47 | radius = v.getRadius();
48 | color = v.getColor();
49 |
50 | } else if (position == lastSelectedPosition) {
51 | radius = v.getRadiusReverse();
52 | color = v.getColorReverse();
53 | }
54 | }
55 |
56 | paint.setColor(color);
57 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/drawer/type/SlideDrawer.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import androidx.annotation.NonNull;
6 | import com.rd.animation.data.Value;
7 | import com.rd.animation.data.type.SlideAnimationValue;
8 | import com.rd.draw.data.Indicator;
9 | import com.rd.draw.data.Orientation;
10 |
11 | public class SlideDrawer extends BaseDrawer {
12 |
13 | public SlideDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
14 | super(paint, indicator);
15 | }
16 |
17 | public void draw(
18 | @NonNull Canvas canvas,
19 | @NonNull Value value,
20 | int coordinateX,
21 | int coordinateY) {
22 |
23 | if (!(value instanceof SlideAnimationValue)) {
24 | return;
25 | }
26 |
27 | SlideAnimationValue v = (SlideAnimationValue) value;
28 | int coordinate = v.getCoordinate();
29 | int unselectedColor = indicator.getUnselectedColor();
30 | int selectedColor = indicator.getSelectedColor();
31 | int radius = indicator.getRadius();
32 |
33 | paint.setColor(unselectedColor);
34 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
35 |
36 | paint.setColor(selectedColor);
37 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
38 | canvas.drawCircle(coordinate, coordinateY, radius, paint);
39 | } else {
40 | canvas.drawCircle(coordinateX, coordinate, radius, paint);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/drawer/type/SwapDrawer.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import androidx.annotation.NonNull;
6 | import com.rd.animation.data.Value;
7 | import com.rd.animation.data.type.SwapAnimationValue;
8 | import com.rd.draw.data.Indicator;
9 | import com.rd.draw.data.Orientation;
10 |
11 | public class SwapDrawer extends BaseDrawer {
12 |
13 | public SwapDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
14 | super(paint, indicator);
15 | }
16 |
17 | public void draw(
18 | @NonNull Canvas canvas,
19 | @NonNull Value value,
20 | int position,
21 | int coordinateX,
22 | int coordinateY) {
23 |
24 | if (!(value instanceof SwapAnimationValue)) {
25 | return;
26 | }
27 |
28 | SwapAnimationValue v = (SwapAnimationValue) value;
29 | int selectedColor = indicator.getSelectedColor();
30 | int unselectedColor = indicator.getUnselectedColor();
31 | int radius = indicator.getRadius();
32 |
33 | int selectedPosition = indicator.getSelectedPosition();
34 | int selectingPosition = indicator.getSelectingPosition();
35 | int lastSelectedPosition = indicator.getLastSelectedPosition();
36 |
37 | int coordinate = v.getCoordinate();
38 | int color = unselectedColor;
39 |
40 | if (indicator.isInteractiveAnimation()) {
41 | if (position == selectingPosition) {
42 | coordinate = v.getCoordinate();
43 | color = selectedColor;
44 |
45 | } else if (position == selectedPosition) {
46 | coordinate = v.getCoordinateReverse();
47 | color = unselectedColor;
48 | }
49 |
50 | } else {
51 | if (position == lastSelectedPosition) {
52 | coordinate = v.getCoordinate();
53 | color = selectedColor;
54 |
55 | } else if (position == selectedPosition) {
56 | coordinate = v.getCoordinateReverse();
57 | color = unselectedColor;
58 | }
59 | }
60 |
61 | paint.setColor(color);
62 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
63 | canvas.drawCircle(coordinate, coordinateY, radius, paint);
64 | } else {
65 | canvas.drawCircle(coordinateX, coordinate, radius, paint);
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/drawer/type/ThinWormDrawer.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import androidx.annotation.NonNull;
6 | import com.rd.animation.data.Value;
7 | import com.rd.animation.data.type.ThinWormAnimationValue;
8 | import com.rd.draw.data.Indicator;
9 | import com.rd.draw.data.Orientation;
10 |
11 | public class ThinWormDrawer extends WormDrawer {
12 |
13 | public ThinWormDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
14 | super(paint, indicator);
15 | }
16 |
17 | public void draw(
18 | @NonNull Canvas canvas,
19 | @NonNull Value value,
20 | int coordinateX,
21 | int coordinateY) {
22 |
23 | if (!(value instanceof ThinWormAnimationValue)) {
24 | return;
25 | }
26 |
27 | ThinWormAnimationValue v = (ThinWormAnimationValue) value;
28 | int rectStart = v.getRectStart();
29 | int rectEnd = v.getRectEnd();
30 | int height = v.getHeight() / 2;
31 |
32 | int radius = indicator.getRadius();
33 | int unselectedColor = indicator.getUnselectedColor();
34 | int selectedColor = indicator.getSelectedColor();
35 |
36 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
37 | rect.left = rectStart;
38 | rect.right = rectEnd;
39 | rect.top = coordinateY - height;
40 | rect.bottom = coordinateY + height;
41 |
42 | } else {
43 | rect.left = coordinateX - height;
44 | rect.right = coordinateX + height;
45 | rect.top = rectStart;
46 | rect.bottom = rectEnd;
47 | }
48 |
49 | paint.setColor(unselectedColor);
50 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
51 |
52 | paint.setColor(selectedColor);
53 | canvas.drawRoundRect(rect, radius, radius, paint);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/draw/drawer/type/WormDrawer.java:
--------------------------------------------------------------------------------
1 | package com.rd.draw.drawer.type;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import android.graphics.RectF;
6 | import androidx.annotation.NonNull;
7 | import com.rd.animation.data.Value;
8 | import com.rd.animation.data.type.WormAnimationValue;
9 | import com.rd.draw.data.Indicator;
10 | import com.rd.draw.data.Orientation;
11 |
12 | public class WormDrawer extends BaseDrawer {
13 |
14 | public RectF rect;
15 |
16 | public WormDrawer(@NonNull Paint paint, @NonNull Indicator indicator) {
17 | super(paint, indicator);
18 | rect = new RectF();
19 | }
20 |
21 | public void draw(
22 | @NonNull Canvas canvas,
23 | @NonNull Value value,
24 | int coordinateX,
25 | int coordinateY) {
26 |
27 | if (!(value instanceof WormAnimationValue)) {
28 | return;
29 | }
30 |
31 | WormAnimationValue v = (WormAnimationValue) value;
32 | int rectStart = v.getRectStart();
33 | int rectEnd = v.getRectEnd();
34 |
35 | int radius = indicator.getRadius();
36 | int unselectedColor = indicator.getUnselectedColor();
37 | int selectedColor = indicator.getSelectedColor();
38 |
39 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
40 | rect.left = rectStart;
41 | rect.right = rectEnd;
42 | rect.top = coordinateY - radius;
43 | rect.bottom = coordinateY + radius;
44 |
45 | } else {
46 | rect.left = coordinateX - radius;
47 | rect.right = coordinateX + radius;
48 | rect.top = rectStart;
49 | rect.bottom = rectEnd;
50 | }
51 |
52 | paint.setColor(unselectedColor);
53 | canvas.drawCircle(coordinateX, coordinateY, radius, paint);
54 |
55 | paint.setColor(selectedColor);
56 | canvas.drawRoundRect(rect, radius, radius, paint);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/utils/CoordinatesUtils.java:
--------------------------------------------------------------------------------
1 | package com.rd.utils;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 | import android.util.Pair;
6 | import com.rd.animation.type.AnimationType;
7 | import com.rd.draw.data.Indicator;
8 | import com.rd.draw.data.Orientation;
9 |
10 | public class CoordinatesUtils {
11 |
12 | @SuppressWarnings("UnnecessaryLocalVariable")
13 | public static int getCoordinate(@Nullable Indicator indicator, int position) {
14 | if (indicator == null) {
15 | return 0;
16 | }
17 |
18 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
19 | return getXCoordinate(indicator, position);
20 | } else {
21 | return getYCoordinate(indicator, position);
22 | }
23 | }
24 |
25 | @SuppressWarnings("UnnecessaryLocalVariable")
26 | public static int getXCoordinate(@Nullable Indicator indicator, int position) {
27 | if (indicator == null) {
28 | return 0;
29 | }
30 |
31 | int coordinate;
32 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
33 | coordinate = getHorizontalCoordinate(indicator, position);
34 | } else {
35 | coordinate = getVerticalCoordinate(indicator);
36 | }
37 |
38 | coordinate += indicator.getPaddingLeft();
39 | return coordinate;
40 | }
41 |
42 | public static int getYCoordinate(@Nullable Indicator indicator, int position) {
43 | if (indicator == null) {
44 | return 0;
45 | }
46 |
47 | int coordinate;
48 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
49 | coordinate = getVerticalCoordinate(indicator);
50 | } else {
51 | coordinate = getHorizontalCoordinate(indicator, position);
52 | }
53 |
54 | coordinate += indicator.getPaddingTop();
55 | return coordinate;
56 | }
57 |
58 | @SuppressWarnings("SuspiciousNameCombination")
59 | public static int getPosition(@Nullable Indicator indicator, float x, float y) {
60 | if (indicator == null) {
61 | return -1;
62 | }
63 |
64 | float lengthCoordinate;
65 | float heightCoordinate;
66 |
67 | if (indicator.getOrientation() == Orientation.HORIZONTAL) {
68 | lengthCoordinate = x;
69 | heightCoordinate = y;
70 | } else {
71 | lengthCoordinate = y;
72 | heightCoordinate = x;
73 | }
74 |
75 | return getFitPosition(indicator, lengthCoordinate, heightCoordinate);
76 | }
77 |
78 | private static int getFitPosition(@NonNull Indicator indicator, float lengthCoordinate, float heightCoordinate) {
79 | int count = indicator.getCount();
80 | int radius = indicator.getRadius();
81 | int stroke = indicator.getStroke();
82 | int padding = indicator.getPadding();
83 |
84 | int height = indicator.getOrientation() == Orientation.HORIZONTAL ? indicator.getHeight() : indicator.getWidth();
85 | int length = 0;
86 |
87 | for (int i = 0; i < count; i++) {
88 | int indicatorPadding = i > 0 ? padding : padding / 2;
89 | int startValue = length;
90 |
91 | length += radius * 2 + (stroke / 2) + indicatorPadding;
92 | int endValue = length;
93 |
94 | boolean fitLength = lengthCoordinate >= startValue && lengthCoordinate <= endValue;
95 | boolean fitHeight = heightCoordinate >= 0 && heightCoordinate <= height;
96 |
97 | if (fitLength && fitHeight) {
98 | return i;
99 | }
100 | }
101 |
102 | return -1;
103 | }
104 |
105 | private static int getHorizontalCoordinate(@NonNull Indicator indicator, int position) {
106 | int count = indicator.getCount();
107 | int radius = indicator.getRadius();
108 | int stroke = indicator.getStroke();
109 | int padding = indicator.getPadding();
110 |
111 | int coordinate = 0;
112 | for (int i = 0; i < count; i++) {
113 | coordinate += radius + (stroke / 2);
114 |
115 | if (position == i) {
116 | return coordinate;
117 | }
118 |
119 | coordinate += radius + padding + (stroke / 2);
120 | }
121 |
122 | if (indicator.getAnimationType() == AnimationType.DROP) {
123 | coordinate += radius * 2;
124 | }
125 |
126 | return coordinate;
127 | }
128 |
129 | private static int getVerticalCoordinate(@NonNull Indicator indicator) {
130 | int radius = indicator.getRadius();
131 | int coordinate;
132 |
133 | if (indicator.getAnimationType() == AnimationType.DROP) {
134 | coordinate = radius * 3;
135 | } else {
136 | coordinate = radius;
137 | }
138 |
139 | return coordinate;
140 | }
141 |
142 | public static Pair getProgress(@NonNull Indicator indicator, int position, float positionOffset, boolean isRtl) {
143 | int count = indicator.getCount();
144 | int selectedPosition = indicator.getSelectedPosition();
145 |
146 | if (isRtl) {
147 | position = (count - 1) - position;
148 | }
149 |
150 | if (position < 0) {
151 | position = 0;
152 |
153 | } else if (position > count - 1) {
154 | position = count - 1;
155 | }
156 |
157 | boolean isRightOverScrolled = position > selectedPosition;
158 | boolean isLeftOverScrolled;
159 |
160 | if (isRtl) {
161 | isLeftOverScrolled = position - 1 < selectedPosition;
162 | } else {
163 | isLeftOverScrolled = position + 1 < selectedPosition;
164 | }
165 |
166 | if (isRightOverScrolled || isLeftOverScrolled) {
167 | selectedPosition = position;
168 | indicator.setSelectedPosition(selectedPosition);
169 | }
170 |
171 | boolean slideToRightSide = selectedPosition == position && positionOffset != 0;
172 | int selectingPosition;
173 | float selectingProgress;
174 |
175 | if (slideToRightSide) {
176 | selectingPosition = isRtl ? position - 1 : position + 1;
177 | selectingProgress = positionOffset;
178 |
179 | } else {
180 | selectingPosition = position;
181 | selectingProgress = 1 - positionOffset;
182 | }
183 |
184 | if (selectingProgress > 1) {
185 | selectingProgress = 1;
186 |
187 | } else if (selectingProgress < 0) {
188 | selectingProgress = 0;
189 | }
190 |
191 | return new Pair<>(selectingPosition, selectingProgress);
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/utils/DensityUtils.java:
--------------------------------------------------------------------------------
1 | package com.rd.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 |
--------------------------------------------------------------------------------
/pageindicatorview/src/main/java/com/rd/utils/IdUtils.java:
--------------------------------------------------------------------------------
1 | package com.rd.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 |
--------------------------------------------------------------------------------
/pageindicatorview/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 |
--------------------------------------------------------------------------------
/sample/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/sample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 28
5 | buildToolsVersion '28.0.3'
6 |
7 | defaultConfig {
8 | applicationId "com.rd.pageindicatorview"
9 | minSdkVersion 14
10 | targetSdkVersion 28
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | implementation fileTree(include: ['*.jar'], dir: 'libs')
24 | implementation 'androidx.appcompat:appcompat:1.0.1'
25 | implementation 'androidx.recyclerview:recyclerview:1.0.0'
26 | implementation project(':pageindicatorview')
27 | }
28 |
--------------------------------------------------------------------------------
/sample/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Work\IDE\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/rd/pageindicatorview/base/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.rd.pageindicatorview.base;
2 |
3 | import androidx.appcompat.app.ActionBar;
4 | import androidx.appcompat.app.AppCompatActivity;
5 | import androidx.appcompat.widget.Toolbar;
6 | import android.view.MenuItem;
7 | import com.rd.pageindicatorview.sample.R;
8 |
9 | public class BaseActivity extends AppCompatActivity {
10 |
11 | private ActionBar toolbar;
12 |
13 | @Override
14 | public boolean onOptionsItemSelected(MenuItem item) {
15 | switch (item.getItemId()) {
16 | case android.R.id.home:
17 | onBackPressed();
18 | break;
19 | }
20 | return super.onOptionsItemSelected(item);
21 | }
22 |
23 | public void initToolbar() {
24 | if (getSupportActionBar() == null) {
25 | setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
26 | }
27 |
28 | toolbar = getSupportActionBar();
29 | if (toolbar != null) {
30 | toolbar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE);
31 | }
32 | }
33 |
34 | public void displayBackButton(boolean display) {
35 | if (toolbar != null) {
36 | toolbar.setDisplayHomeAsUpEnabled(display);
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/sample/src/main/java/com/rd/pageindicatorview/customize/CustomizeActivity.java:
--------------------------------------------------------------------------------
1 | package com.rd.pageindicatorview.customize;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.graphics.PorterDuff;
6 | import android.os.Bundle;
7 | import androidx.annotation.NonNull;
8 | import androidx.annotation.Nullable;
9 | import android.view.View;
10 | import android.widget.*;
11 | import com.rd.pageindicatorview.base.BaseActivity;
12 | import com.rd.pageindicatorview.data.Customization;
13 | import com.rd.pageindicatorview.data.CustomizationConverter;
14 | import com.rd.pageindicatorview.sample.R;
15 |
16 | public class CustomizeActivity extends BaseActivity implements AdapterView.OnItemSelectedListener, CompoundButton.OnCheckedChangeListener {
17 |
18 | public static final String EXTRAS_CUSTOMIZATION = "EXTRAS_CUSTOMIZATION";
19 | public static final int EXTRAS_CUSTOMIZATION_REQUEST_CODE = 1000;
20 |
21 | private Customization customization;
22 |
23 | public static void start(@NonNull Activity activity, @NonNull Customization customization) {
24 | Intent intent = new Intent(activity, CustomizeActivity.class);
25 | intent.putExtra(EXTRAS_CUSTOMIZATION, customization);
26 | activity.startActivityForResult(intent, EXTRAS_CUSTOMIZATION_REQUEST_CODE);
27 | }
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.ac_customize);
33 |
34 | initToolbar();
35 | displayBackButton(true);
36 | initData();
37 | initViews();
38 | }
39 |
40 | @Override
41 | public void finish() {
42 | Intent intent = new Intent();
43 | intent.putExtra(EXTRAS_CUSTOMIZATION, customization);
44 | setResult(Activity.RESULT_OK, intent);
45 |
46 | super.finish();
47 | }
48 |
49 | @Override
50 | public void onItemSelected(AdapterView> parent, View view, int position, long id) {
51 | switch (parent.getId()) {
52 | case R.id.spinnerAnimationType:
53 | customization.setAnimationType(CustomizationConverter.getAnimationType(position));
54 | break;
55 |
56 | case R.id.spinnerOrientation:
57 | customization.setOrientation(CustomizationConverter.getOrientation(position));
58 | break;
59 |
60 | case R.id.spinnerRtl:
61 | customization.setRtlMode(CustomizationConverter.getRtlMode(position));
62 | break;
63 | }
64 | }
65 |
66 | @Override
67 | public void onNothingSelected(AdapterView> parent) {/*empty*/}
68 |
69 | @Override
70 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
71 | int id = buttonView.getId();
72 | switch (id) {
73 | case R.id.switchInteractiveAnimation:
74 | customization.setInteractiveAnimation(isChecked);
75 | break;
76 |
77 | case R.id.switchAutoVisibility:
78 | customization.setAutoVisibility(isChecked);
79 | break;
80 |
81 | case R.id.switchFadeOnIdle:
82 | customization.setFadeOnIdle(isChecked);
83 | break;
84 | }
85 | }
86 |
87 | private void initData() {
88 | Intent intent = getIntent();
89 | if (intent != null) {
90 | customization = intent.getParcelableExtra(EXTRAS_CUSTOMIZATION);
91 | } else {
92 | customization = new Customization();
93 | }
94 | }
95 |
96 | private void initViews() {
97 | Spinner spinnerAnimationType = findViewById(R.id.spinnerAnimationType);
98 | setSpinnerAdapter(spinnerAnimationType, R.array.animation_type);
99 | spinnerAnimationType.setOnItemSelectedListener(this);
100 | spinnerAnimationType.setSelection(customization.getAnimationType().ordinal());
101 |
102 | Spinner spinnerOrientation = findViewById(R.id.spinnerOrientation);
103 | setSpinnerAdapter(spinnerOrientation, R.array.orientation);
104 | spinnerOrientation.setOnItemSelectedListener(this);
105 | spinnerOrientation.setSelection(customization.getOrientation().ordinal());
106 |
107 | Spinner spinnerRtl = findViewById(R.id.spinnerRtl);
108 | setSpinnerAdapter(spinnerRtl, R.array.rtl);
109 | spinnerRtl.setOnItemSelectedListener(this);
110 | spinnerRtl.setSelection(customization.getRtlMode().ordinal());
111 |
112 | Switch switchInteractiveAnimation = findViewById(R.id.switchInteractiveAnimation);
113 | switchInteractiveAnimation.setOnCheckedChangeListener(this);
114 | switchInteractiveAnimation.setChecked(customization.isInteractiveAnimation());
115 |
116 | Switch switchAutoVisibility = findViewById(R.id.switchAutoVisibility);
117 | switchAutoVisibility.setOnCheckedChangeListener(this);
118 | switchAutoVisibility.setChecked(customization.isAutoVisibility());
119 |
120 | Switch switchFadeOnIdle = findViewById(R.id.switchFadeOnIdle);
121 | switchFadeOnIdle.setOnCheckedChangeListener(this);
122 | switchFadeOnIdle.setChecked(customization.isFadeOnIdle());
123 |
124 | }
125 |
126 | private void setSpinnerAdapter(@Nullable Spinner spinner, int textArrayId) {
127 | if (spinner != null) {
128 | ArrayAdapter adapter = ArrayAdapter.createFromResource(this, textArrayId, R.layout.item_spinner_selected);
129 | adapter.setDropDownViewResource(R.layout.item_spinner_drop_down);
130 | spinner.setAdapter(adapter);
131 | spinner.getBackground().setColorFilter(getResources().getColor(R.color.gray_500), PorterDuff.Mode.SRC_ATOP);
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/rd/pageindicatorview/data/Customization.java:
--------------------------------------------------------------------------------
1 | package com.rd.pageindicatorview.data;
2 |
3 | import android.os.Parcel;
4 | import android.os.Parcelable;
5 |
6 | import com.rd.animation.type.AnimationType;
7 | import com.rd.draw.data.Orientation;
8 | import com.rd.draw.data.RtlMode;
9 |
10 | public class Customization implements Parcelable {
11 |
12 | private AnimationType animationType = AnimationType.NONE;
13 | private Orientation orientation = Orientation.HORIZONTAL;
14 | private RtlMode rtlMode = RtlMode.Off;
15 |
16 | private boolean interactiveAnimation = false;
17 | private boolean autoVisibility = true;
18 | private boolean fadeOnIdle = false;
19 |
20 | public AnimationType getAnimationType() {
21 | return animationType;
22 | }
23 |
24 | public void setAnimationType(AnimationType animationType) {
25 | this.animationType = animationType;
26 | }
27 |
28 | public Orientation getOrientation() {
29 | return orientation;
30 | }
31 |
32 | public void setOrientation(Orientation orientation) {
33 | this.orientation = orientation;
34 | }
35 |
36 | public RtlMode getRtlMode() {
37 | return rtlMode;
38 | }
39 |
40 | public void setRtlMode(RtlMode rtlMode) {
41 | this.rtlMode = rtlMode;
42 | }
43 |
44 | public boolean isInteractiveAnimation() {
45 | return interactiveAnimation;
46 | }
47 |
48 | public void setInteractiveAnimation(boolean interactiveAnimation) {
49 | this.interactiveAnimation = interactiveAnimation;
50 | }
51 |
52 | public boolean isAutoVisibility() {
53 | return autoVisibility;
54 | }
55 |
56 | public void setAutoVisibility(boolean autoVisibility) {
57 | this.autoVisibility = autoVisibility;
58 | }
59 |
60 | public boolean isFadeOnIdle() {
61 | return fadeOnIdle;
62 | }
63 |
64 | public void setFadeOnIdle(boolean fadeOnIdle) {
65 | this.fadeOnIdle = fadeOnIdle;
66 | }
67 |
68 | @Override
69 | public boolean equals(Object o) {
70 | if (this == o) return true;
71 | if (o == null || getClass() != o.getClass()) return false;
72 |
73 | Customization that = (Customization) o;
74 |
75 | if (interactiveAnimation != that.interactiveAnimation) return false;
76 | if (autoVisibility != that.autoVisibility) return false;
77 | if (animationType != that.animationType) return false;
78 | if (orientation != that.orientation) return false;
79 | if (fadeOnIdle != that.fadeOnIdle) return false;
80 | return rtlMode == that.rtlMode;
81 |
82 | }
83 |
84 | @Override
85 | public int hashCode() {
86 | int result = animationType != null ? animationType.hashCode() : 0;
87 | result = 31 * result + (orientation != null ? orientation.hashCode() : 0);
88 | result = 31 * result + (rtlMode != null ? rtlMode.hashCode() : 0);
89 | result = 31 * result + (interactiveAnimation ? 1 : 0);
90 | result = 31 * result + (autoVisibility ? 1 : 0);
91 | result = 31 * result + (fadeOnIdle ? 1 : 0);
92 | return result;
93 | }
94 |
95 | @Override
96 | public int describeContents() {
97 | return 0;
98 | }
99 |
100 | @Override
101 | public void writeToParcel(Parcel dest, int flags) {
102 | dest.writeInt(this.animationType == null ? -1 : this.animationType.ordinal());
103 | dest.writeInt(this.orientation == null ? -1 : this.orientation.ordinal());
104 | dest.writeInt(this.rtlMode == null ? -1 : this.rtlMode.ordinal());
105 | dest.writeByte(this.interactiveAnimation ? (byte) 1 : (byte) 0);
106 | dest.writeByte(this.autoVisibility ? (byte) 1 : (byte) 0);
107 | dest.writeByte(this.fadeOnIdle ? (byte) 1 : (byte) 0);
108 | }
109 |
110 | public Customization() {
111 | }
112 |
113 | protected Customization(Parcel in) {
114 | int tmpAnimationType = in.readInt();
115 | this.animationType = tmpAnimationType == -1 ? null : AnimationType.values()[tmpAnimationType];
116 | int tmpOrientation = in.readInt();
117 | this.orientation = tmpOrientation == -1 ? null : Orientation.values()[tmpOrientation];
118 | int tmpRtlMode = in.readInt();
119 | this.rtlMode = tmpRtlMode == -1 ? null : RtlMode.values()[tmpRtlMode];
120 | this.interactiveAnimation = in.readByte() != 0;
121 | this.autoVisibility = in.readByte() != 0;
122 | this.fadeOnIdle = in.readByte() != 0;
123 | }
124 |
125 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
126 | @Override
127 | public Customization createFromParcel(Parcel source) {
128 | return new Customization(source);
129 | }
130 |
131 | @Override
132 | public Customization[] newArray(int size) {
133 | return new Customization[size];
134 | }
135 | };
136 | }
137 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/rd/pageindicatorview/data/CustomizationConverter.java:
--------------------------------------------------------------------------------
1 | package com.rd.pageindicatorview.data;
2 |
3 | import com.rd.animation.type.AnimationType;
4 | import com.rd.draw.data.Orientation;
5 | import com.rd.draw.data.RtlMode;
6 |
7 | public class CustomizationConverter {
8 |
9 | public static AnimationType getAnimationType(int position) {
10 | switch (position) {
11 | case 0:
12 | return AnimationType.NONE;
13 |
14 | case 1:
15 | return AnimationType.COLOR;
16 |
17 | case 2:
18 | return AnimationType.SCALE;
19 |
20 | case 3:
21 | return AnimationType.WORM;
22 |
23 | case 4:
24 | return AnimationType.SLIDE;
25 |
26 | case 5:
27 | return AnimationType.FILL;
28 |
29 | case 6:
30 | return AnimationType.THIN_WORM;
31 |
32 | case 7:
33 | return AnimationType.DROP;
34 |
35 | case 8:
36 | return AnimationType.SWAP;
37 |
38 | case 9:
39 | return AnimationType.SCALE_DOWN;
40 |
41 | default:
42 | return AnimationType.NONE;
43 | }
44 | }
45 |
46 | public static Orientation getOrientation(int position) {
47 | switch (position) {
48 | case 0:
49 | return Orientation.HORIZONTAL;
50 |
51 | case 1:
52 | return Orientation.VERTICAL;
53 |
54 | default:
55 | return Orientation.HORIZONTAL;
56 | }
57 | }
58 |
59 | public static RtlMode getRtlMode(int position) {
60 | switch (position) {
61 | case 0:
62 | return RtlMode.On;
63 |
64 | case 1:
65 | return RtlMode.Off;
66 |
67 | case 2:
68 | return RtlMode.Auto;
69 |
70 | default:
71 | return RtlMode.Off;
72 | }
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/rd/pageindicatorview/home/HomeActivity.java:
--------------------------------------------------------------------------------
1 | package com.rd.pageindicatorview.home;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import androidx.annotation.NonNull;
6 | import androidx.viewpager.widget.ViewPager;
7 | import android.view.Menu;
8 | import android.view.MenuItem;
9 | import android.view.View;
10 | import com.rd.PageIndicatorView;
11 | import com.rd.pageindicatorview.base.BaseActivity;
12 | import com.rd.pageindicatorview.customize.CustomizeActivity;
13 | import com.rd.pageindicatorview.data.Customization;
14 | import com.rd.pageindicatorview.sample.R;
15 |
16 | import java.util.ArrayList;
17 | import java.util.List;
18 |
19 |
20 | public class HomeActivity extends BaseActivity {
21 |
22 | private PageIndicatorView pageIndicatorView;
23 | private Customization customization;
24 |
25 | @Override
26 | protected void onCreate(Bundle savedInstanceState) {
27 | super.onCreate(savedInstanceState);
28 | setContentView(R.layout.ac_home);
29 | customization = new Customization();
30 |
31 | initToolbar();
32 | initViews();
33 | }
34 |
35 | @Override
36 | protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
37 | boolean customization = requestCode == CustomizeActivity.EXTRAS_CUSTOMIZATION_REQUEST_CODE && resultCode == RESULT_OK;
38 | if (customization && intent != null) {
39 | this.customization = intent.getParcelableExtra(CustomizeActivity.EXTRAS_CUSTOMIZATION);
40 | updateIndicator();
41 | }
42 | }
43 |
44 | @Override
45 | public boolean onCreateOptionsMenu(Menu menu) {
46 | getMenuInflater().inflate(R.menu.menu_customize, menu);
47 | return true;
48 | }
49 |
50 | @Override
51 | public boolean onOptionsItemSelected(MenuItem item) {
52 | switch (item.getItemId()) {
53 | case R.id.actionCustomize:
54 | CustomizeActivity.start(this, customization);
55 | return true;
56 |
57 | default:
58 | return super.onOptionsItemSelected(item);
59 | }
60 | }
61 |
62 | @SuppressWarnings("ConstantConditions")
63 | private void initViews() {
64 | HomeAdapter adapter = new HomeAdapter();
65 | adapter.setData(createPageList());
66 |
67 | final ViewPager pager = findViewById(R.id.viewPager);
68 | pager.setAdapter(adapter);
69 |
70 | pageIndicatorView = findViewById(R.id.pageIndicatorView);
71 | }
72 |
73 | @NonNull
74 | private List createPageList() {
75 | List pageList = new ArrayList<>();
76 | pageList.add(createPageView(R.color.google_red));
77 | pageList.add(createPageView(R.color.google_blue));
78 | pageList.add(createPageView(R.color.google_yellow));
79 | pageList.add(createPageView(R.color.google_green));
80 |
81 | return pageList;
82 | }
83 |
84 | @NonNull
85 | private View createPageView(int color) {
86 | View view = new View(this);
87 | view.setBackgroundColor(getResources().getColor(color));
88 |
89 | return view;
90 | }
91 |
92 | private void updateIndicator() {
93 | if (customization == null) {
94 | return;
95 | }
96 |
97 | pageIndicatorView.setAnimationType(customization.getAnimationType());
98 | pageIndicatorView.setOrientation(customization.getOrientation());
99 | pageIndicatorView.setRtlMode(customization.getRtlMode());
100 | pageIndicatorView.setInteractiveAnimation(customization.isInteractiveAnimation());
101 | pageIndicatorView.setAutoVisibility(customization.isAutoVisibility());
102 | pageIndicatorView.setFadeOnIdle(customization.isFadeOnIdle());
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/rd/pageindicatorview/home/HomeAdapter.java:
--------------------------------------------------------------------------------
1 | package com.rd.pageindicatorview.home;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 | import androidx.viewpager.widget.PagerAdapter;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import java.util.ArrayList;
10 | import java.util.List;
11 |
12 | class HomeAdapter extends PagerAdapter {
13 |
14 | private List viewList;
15 |
16 | HomeAdapter() {
17 | this.viewList = new ArrayList<>();
18 | }
19 |
20 | @Override
21 | public Object instantiateItem(ViewGroup collection, int position) {
22 | View view = viewList.get(position);
23 | collection.addView(view);
24 | return view;
25 | }
26 |
27 | @Override
28 | public void destroyItem(ViewGroup collection, int position, Object view) {
29 | collection.removeView((View) view);
30 | }
31 |
32 | @Override
33 | public int getCount() {
34 | return viewList.size();
35 | }
36 |
37 | @Override
38 | public boolean isViewFromObject(View view, Object object) {
39 | return view == object;
40 | }
41 |
42 | @Override
43 | public int getItemPosition(Object object) {
44 | return POSITION_NONE;
45 | }
46 |
47 | void setData(@Nullable List list) {
48 | this.viewList.clear();
49 | if (list != null && !list.isEmpty()) {
50 | this.viewList.addAll(list);
51 | }
52 |
53 | notifyDataSetChanged();
54 | }
55 |
56 | @NonNull
57 | List getData() {
58 | if (viewList == null) {
59 | viewList = new ArrayList<>();
60 | }
61 |
62 | return viewList;
63 | }
64 | }
--------------------------------------------------------------------------------
/sample/src/main/res/drawable-v21/selector_black_10_transparent.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 | -
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/sample/src/main/res/drawable/selector_black_10_transparent.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/ac_customize.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
19 |
20 |
24 |
25 |
31 |
32 |
39 |
40 |
45 |
46 |
47 |
51 |
52 |
56 |
57 |
63 |
64 |
71 |
72 |
77 |
78 |
79 |
83 |
84 |
90 |
91 |
98 |
99 |
104 |
105 |
106 |
107 |
111 |
112 |
121 |
122 |
126 |
127 |
136 |
137 |
141 |
142 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/ac_home.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
25 |
26 |
36 |
37 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_spinner_drop_down.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sample/src/main/res/layout/item_spinner_selected.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sample/src/main/res/menu/menu_customize.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/sample/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/sample/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/sample/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/romandanylyk/PageIndicatorView/b1bad589b506add6842cc44ef6f2ca7e561dfebd/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #00000000
5 |
6 | #000000
7 | - #1A000000
8 |
9 | #ffffff
10 |
11 | #FAFAFA
12 | #F5F5F5
13 | #EEEEEE
14 | #E0E0E0
15 | #BDBDBD
16 | #9E9E9E
17 | #757575
18 | #616161
19 | #424242
20 | #212121
21 |
22 | #E3F2FD
23 | #BBDEFB
24 | #90CAF9
25 | #64B5F6
26 | #42A5F5
27 | #2196F3
28 | #1E88E5
29 | #1976D2
30 | #1565C0
31 | #0D47A1
32 |
33 | #FFEBEE
34 | #FFCDD2
35 | #EF9A9A
36 | #E57373
37 | #EF5350
38 | #F44336
39 | #E53935
40 | #D32F2F
41 | #C62828
42 | #B71C1C
43 |
44 | #DBE6DA
45 | #BAD7B7
46 | #99C495
47 | #7AB273
48 | #66A55C
49 | #549948
50 | #4A8840
51 | #3F7736
52 | #35662D
53 | #35662D
54 |
55 | #ea5a4f
56 | #6099f5
57 | #edc855
58 | #5cb171
59 |
60 |
61 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | PageIndicatorView
3 | Interactive animation
4 | Auto visibility
5 | Animation type
6 | Orientation
7 | Customize
8 | Home
9 | Right to left mode
10 | Fade on idle
11 |
12 |
13 | - None
14 | - Color
15 | - Scale
16 | - Worm
17 | - Slide
18 | - Fill
19 | - Thin Worm
20 | - Drop
21 | - Swap
22 | - Scale Down
23 |
24 |
25 |
26 | - Horizontal
27 | - Vertical
28 |
29 |
30 |
31 | - On
32 | - Off
33 | - Auto
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/sample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
14 |
15 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':sample', ':pageindicatorview'
2 |
--------------------------------------------------------------------------------