2 |
7 |
8 |
14 |
15 |
21 |
22 |
34 |
35 |
47 |
48 |
58 |
59 |
63 |
64 |
74 |
75 |
85 |
86 |
94 |
102 |
112 |
121 |
131 |
132 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
22 |
23 |
29 |
30 |
39 |
40 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
66 |
67 |
72 |
73 |
74 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MartinRGB/MI_Style_Multitask_Prototype/f5391b9f792979c837875e0ba8e06ca3d69fe6f7/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MartinRGB/MI_Style_Multitask_Prototype/f5391b9f792979c837875e0ba8e06ca3d69fe6f7/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MartinRGB/MI_Style_Multitask_Prototype/f5391b9f792979c837875e0ba8e06ca3d69fe6f7/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MartinRGB/MI_Style_Multitask_Prototype/f5391b9f792979c837875e0ba8e06ca3d69fe6f7/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MartinRGB/MI_Style_Multitask_Prototype/f5391b9f792979c837875e0ba8e06ca3d69fe6f7/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MartinRGB/MI_Style_Multitask_Prototype/f5391b9f792979c837875e0ba8e06ca3d69fe6f7/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MartinRGB/MI_Style_Multitask_Prototype/f5391b9f792979c837875e0ba8e06ca3d69fe6f7/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MartinRGB/MI_Style_Multitask_Prototype/f5391b9f792979c837875e0ba8e06ca3d69fe6f7/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MartinRGB/MI_Style_Multitask_Prototype/f5391b9f792979c837875e0ba8e06ca3d69fe6f7/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MartinRGB/MI_Style_Multitask_Prototype/f5391b9f792979c837875e0ba8e06ca3d69fe6f7/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #717171
4 | #A2A2A2
5 | #464646
6 | #F4C828
7 |
8 | #78ffffff
9 | #1400bcd4
10 | #14000000
11 | #6400bcd4
12 |
13 | @android:color/holo_purple
14 | #ccaa66cc
15 | @android:color/holo_purple
16 | #EEEEEE
17 | #50000000
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 | 16dp
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | WaterfallLayout
3 | Waterfall
4 | LogoActivity
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
18 |
19 |
20 |
21 |
22 |
23 |
27 |
28 |
31 |
32 |
--------------------------------------------------------------------------------
/app/version.properties:
--------------------------------------------------------------------------------
1 | VERSION_CODE= 0056
--------------------------------------------------------------------------------
/art/art_real.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MartinRGB/MI_Style_Multitask_Prototype/f5391b9f792979c837875e0ba8e06ca3d69fe6f7/art/art_real.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 | jcenter()
6 | google()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.1.3'
10 |
11 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.6'
12 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
13 |
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | jcenter()
22 | // maven {
23 | // url 'https://maven.google.com'
24 | // // Alternative URL is 'https://dl.google.com/dl/android/maven2/'
25 | // }
26 | google()
27 | }
28 | }
29 |
30 | task clean(type: Delete) {
31 | delete rootProject.buildDir
32 | }
33 |
--------------------------------------------------------------------------------
/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 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MartinRGB/MI_Style_Multitask_Prototype/f5391b9f792979c837875e0ba8e06ca3d69fe6f7/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Aug 06 11:48:50 CST 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.4-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # 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 |
--------------------------------------------------------------------------------
/liboverscroll/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/liboverscroll/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion '27.0.3'
6 |
7 | defaultConfig {
8 | minSdkVersion 17
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | implementation 'com.android.support:recyclerview-v7:25.1.0'
23 |
24 | testImplementation 'junit:junit:4.12'
25 | testImplementation "org.mockito:mockito-core:1.9.5"
26 | testImplementation "org.robolectric:robolectric:3.0"
27 | }
28 |
29 |
30 | // Running from Gradle tab in IDE would create liboverscroll/build/lib/liboverscroll-sources.jar
31 | task sourcesJar(type: Jar) {
32 | from android.sourceSets.main.java.srcDirs
33 | classifier = 'sources'
34 | }
35 |
36 | task javadoc(type: Javadoc) {
37 | failOnError false
38 | source = android.sourceSets.main.java.srcDirs
39 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
40 | }
41 |
42 | // Running from Gradle tab in IDE would create liboverscroll/build/lib/liboverscroll-javadoc.jar
43 | task javadocJar(type: Jar, dependsOn: javadoc) {
44 | classifier = 'javadoc'
45 | from javadoc.destinationDir
46 | }
47 |
48 | artifacts {
49 | archives javadocJar
50 | archives sourcesJar
51 | }
52 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/java/me/everything/android/ui/overscroll/HorizontalOverScrollBounceEffectDecorator.java:
--------------------------------------------------------------------------------
1 | package me.everything.android.ui.overscroll;
2 |
3 | import android.view.MotionEvent;
4 | import android.view.View;
5 |
6 | import me.everything.android.ui.overscroll.adapters.IOverScrollDecoratorAdapter;
7 |
8 | /**
9 | * A concrete implementation of {@link OverScrollBounceEffectDecoratorBase} for a horizontal orientation.
10 | *
11 | * @author amit
12 | */
13 | public class HorizontalOverScrollBounceEffectDecorator extends OverScrollBounceEffectDecoratorBase {
14 |
15 | protected static class MotionAttributesHorizontal extends MotionAttributes {
16 |
17 | public boolean init(View view, MotionEvent event) {
18 |
19 | // We must have history available to calc the dx. Normally it's there - if it isn't temporarily,
20 | // we declare the event 'invalid' and expect it in consequent events.
21 | if (event.getHistorySize() == 0) {
22 | return false;
23 | }
24 |
25 | // Allow for counter-orientation-direction operations (e.g. item swiping) to run fluently.
26 | final float dy = event.getY(0) - event.getHistoricalY(0, 0);
27 | final float dx = event.getX(0) - event.getHistoricalX(0, 0);
28 | if (Math.abs(dx) < Math.abs(dy)) {
29 | return false;
30 | }
31 |
32 | mAbsOffset = view.getTranslationX();
33 | mDeltaOffset = dx;
34 | mDir = mDeltaOffset > 0;
35 |
36 | return true;
37 | }
38 | }
39 |
40 | protected static class AnimationAttributesHorizontal extends AnimationAttributes {
41 |
42 | public AnimationAttributesHorizontal() {
43 | mProperty = View.TRANSLATION_X;
44 | }
45 |
46 | @Override
47 | protected void init(View view) {
48 | mAbsOffset = view.getTranslationX();
49 | mMaxOffset = view.getWidth();
50 | }
51 | }
52 |
53 | /**
54 | * C'tor, creating the effect with default arguments:
55 | *
Touch-drag ratio in 'forward' direction will be set to DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD.
56 | *
Touch-drag ratio in 'backwards' direction will be set to DEFAULT_TOUCH_DRAG_MOVE_RATIO_BCK.
57 | *
Deceleration factor (for the bounce-back effect) will be set to DEFAULT_DECELERATE_FACTOR.
58 | *
59 | * @param viewAdapter The view's encapsulation.
60 | */
61 | public HorizontalOverScrollBounceEffectDecorator(IOverScrollDecoratorAdapter viewAdapter) {
62 | this(viewAdapter, DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD, DEFAULT_TOUCH_DRAG_MOVE_RATIO_BCK, DEFAULT_DECELERATE_FACTOR);
63 | }
64 |
65 | /**
66 | * C'tor, creating the effect with explicit arguments.
67 | * @param viewAdapter The view's encapsulation.
68 | * @param touchDragRatioFwd Ratio of touch distance to actual drag distance when in 'forward' direction.
69 | * @param touchDragRatioBck Ratio of touch distance to actual drag distance when in 'backward'
70 | * direction (opposite to initial one).
71 | * @param decelerateFactor Deceleration factor used when decelerating the motion to create the
72 | * bounce-back effect.
73 | */
74 | public HorizontalOverScrollBounceEffectDecorator(IOverScrollDecoratorAdapter viewAdapter,
75 | float touchDragRatioFwd, float touchDragRatioBck, float decelerateFactor) {
76 | super(viewAdapter, decelerateFactor, touchDragRatioFwd, touchDragRatioBck);
77 | }
78 |
79 | @Override
80 | protected MotionAttributes createMotionAttributes() {
81 | return new MotionAttributesHorizontal();
82 | }
83 |
84 | @Override
85 | protected AnimationAttributes createAnimationAttributes() {
86 | return new AnimationAttributesHorizontal();
87 | }
88 |
89 | @Override
90 | protected void translateView(View view, float offset) {
91 | view.setTranslationX(offset);
92 | }
93 |
94 | @Override
95 | protected void translateViewAndEvent(View view, float offset, MotionEvent event) {
96 | view.setTranslationX(offset);
97 | event.offsetLocation(offset - event.getX(0), 0f);
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollDecor.java:
--------------------------------------------------------------------------------
1 | package me.everything.android.ui.overscroll;
2 |
3 | import android.view.View;
4 |
5 | /**
6 | * @author amit
7 | */
8 | public interface IOverScrollDecor {
9 | View getView();
10 |
11 | void setOverScrollStateListener(IOverScrollStateListener listener);
12 | void setOverScrollUpdateListener(IOverScrollUpdateListener listener);
13 |
14 | /**
15 | * Get the current decorator's runtime state, i.e. one of the values specified by {@link IOverScrollState}.
16 | * @return The state.
17 | */
18 | int getCurrentState();
19 |
20 | /**
21 | * Detach the decorator from its associated view, thus disabling it entirely.
22 | *
23 | * It is best to call this only when over-scroll isn't currently in-effect - i.e. verify that
24 | * getCurrentState()==IOverScrollState.STATE_IDLE
as a precondition, or otherwise
25 | * use a state listener previously installed using
26 | * {@link #setOverScrollStateListener(IOverScrollStateListener)}.
27 | *
28 | * Note: Upon detachment completion, the view in question will return to the default
29 | * Android over-scroll configuration (i.e. {@link View.OVER_SCROLL_ALWAYS} mode). This can be
30 | * overridden by calling View.setOverScrollMode(mode)
immediately thereafter.
31 | */
32 | void detach();
33 | }
34 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollState.java:
--------------------------------------------------------------------------------
1 | package me.everything.android.ui.overscroll;
2 |
3 | /**
4 | * @author amit
5 | */
6 | public interface IOverScrollState {
7 |
8 | /** No over-scroll is in-effect. */
9 | int STATE_IDLE = 0;
10 |
11 | /** User is actively touch-dragging, thus enabling over-scroll at the view's start side. */
12 | int STATE_DRAG_START_SIDE = 1;
13 |
14 | /** User is actively touch-dragging, thus enabling over-scroll at the view's end side. */
15 | int STATE_DRAG_END_SIDE = 2;
16 |
17 | /** User has released their touch, thus throwing the view back into place via bounce-back animation. */
18 | int STATE_BOUNCE_BACK = 3;
19 | }
20 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollStateListener.java:
--------------------------------------------------------------------------------
1 | package me.everything.android.ui.overscroll;
2 |
3 | /**
4 | * A callback-listener enabling over-scroll effect clients to be notified of effect state transitions.
5 | *
Invoked whenever state is transitioned onto one of {@link IOverScrollState#STATE_IDLE},
6 | * {@link IOverScrollState#STATE_DRAG_START_SIDE}, {@link IOverScrollState#STATE_DRAG_END_SIDE}
7 | * or {@link IOverScrollState#STATE_BOUNCE_BACK}.
8 | *
9 | * @author amit
10 | *
11 | * @see IOverScrollUpdateListener
12 | */
13 | public interface IOverScrollStateListener {
14 |
15 | /**
16 | * The invoked callback.
17 | *
18 | * @param decor The associated over-scroll 'decorator'.
19 | * @param oldState The old over-scroll state; ID's specified by {@link IOverScrollState}, e.g.
20 | * {@link IOverScrollState#STATE_IDLE}.
21 | * @param newState The new over-scroll state; ID's specified by {@link IOverScrollState},
22 | * e.g. {@link IOverScrollState#STATE_IDLE}.
23 | */
24 | void onOverScrollStateChange(IOverScrollDecor decor, int oldState, int newState);
25 | }
26 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/java/me/everything/android/ui/overscroll/IOverScrollUpdateListener.java:
--------------------------------------------------------------------------------
1 | package me.everything.android.ui.overscroll;
2 |
3 | /**
4 | * A callback-listener enabling over-scroll effect clients to subscribe to real-time updates
5 | * of over-scrolling intensity, provided as the view-translation offset from pre-scroll position.
6 | *
7 | * @author amit
8 | *
9 | * @see IOverScrollStateListener
10 | */
11 | public interface IOverScrollUpdateListener {
12 |
13 | /**
14 | * The invoked callback.
15 | *
16 | * @param decor The associated over-scroll 'decorator'.
17 | * @param state One of: {@link IOverScrollState#STATE_IDLE}, {@link IOverScrollState#STATE_DRAG_START_SIDE},
18 | * {@link IOverScrollState#STATE_DRAG_START_SIDE} or {@link IOverScrollState#STATE_BOUNCE_BACK}.
19 | * @param offset The currently visible offset created due to over-scroll.
20 | */
21 | void onOverScrollUpdate(IOverScrollDecor decor, int state, float offset);
22 | }
23 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/java/me/everything/android/ui/overscroll/ListenerStubs.java:
--------------------------------------------------------------------------------
1 | package me.everything.android.ui.overscroll;
2 |
3 | /**
4 | * @author amit
5 | */
6 | public interface ListenerStubs {
7 |
8 | class OverScrollStateListenerStub implements IOverScrollStateListener {
9 | @Override
10 | public void onOverScrollStateChange(IOverScrollDecor decor, int oldState, int newState) { }
11 | }
12 |
13 | class OverScrollUpdateListenerStub implements IOverScrollUpdateListener {
14 | @Override
15 | public void onOverScrollUpdate(IOverScrollDecor decor, int state, float offset) { }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/java/me/everything/android/ui/overscroll/OverScrollDecoratorHelper.java:
--------------------------------------------------------------------------------
1 | package me.everything.android.ui.overscroll;
2 |
3 | import android.support.v4.view.ViewPager;
4 | import android.support.v7.widget.GridLayoutManager;
5 | import android.support.v7.widget.LinearLayoutManager;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.support.v7.widget.StaggeredGridLayoutManager;
8 | import android.view.View;
9 | import android.widget.GridView;
10 | import android.widget.HorizontalScrollView;
11 | import android.widget.ListView;
12 | import android.widget.ScrollView;
13 |
14 | import me.everything.android.ui.overscroll.adapters.AbsListViewOverScrollDecorAdapter;
15 | import me.everything.android.ui.overscroll.adapters.HorizontalScrollViewOverScrollDecorAdapter;
16 | import me.everything.android.ui.overscroll.adapters.RecyclerViewOverScrollDecorAdapter;
17 | import me.everything.android.ui.overscroll.adapters.ScrollViewOverScrollDecorAdapter;
18 | import me.everything.android.ui.overscroll.adapters.StaticOverScrollDecorAdapter;
19 | import me.everything.android.ui.overscroll.adapters.ViewPagerOverScrollDecorAdapter;
20 |
21 | /**
22 | * @author amit
23 | */
24 | public class OverScrollDecoratorHelper {
25 |
26 | public static final int ORIENTATION_VERTICAL = 0;
27 | public static final int ORIENTATION_HORIZONTAL = 1;
28 |
29 | /**
30 | * Set up the over-scroll effect over a specified {@link RecyclerView} view.
31 | *
Only recycler-views using native Android layout managers (i.e. {@link LinearLayoutManager},
32 | * {@link GridLayoutManager} and {@link StaggeredGridLayoutManager}) are currently supported
33 | * by this convenience method.
34 | *
35 | * @param recyclerView The view.
36 | * @param orientation Either {@link #ORIENTATION_HORIZONTAL} or {@link #ORIENTATION_VERTICAL}.
37 | *
38 | * @return The over-scroll effect 'decorator', enabling further effect configuration.
39 | */
40 | public static IOverScrollDecor setUpOverScroll(RecyclerView recyclerView, int orientation) {
41 | switch (orientation) {
42 | case ORIENTATION_HORIZONTAL:
43 | return new HorizontalOverScrollBounceEffectDecorator(new RecyclerViewOverScrollDecorAdapter(recyclerView));
44 | case ORIENTATION_VERTICAL:
45 | return new VerticalOverScrollBounceEffectDecorator(new RecyclerViewOverScrollDecorAdapter(recyclerView));
46 | default:
47 | throw new IllegalArgumentException("orientation");
48 | }
49 | }
50 |
51 | public static IOverScrollDecor setUpOverScroll(ListView listView) {
52 | return new VerticalOverScrollBounceEffectDecorator(new AbsListViewOverScrollDecorAdapter(listView));
53 | }
54 |
55 | public static IOverScrollDecor setUpOverScroll(GridView gridView) {
56 | return new VerticalOverScrollBounceEffectDecorator(new AbsListViewOverScrollDecorAdapter(gridView));
57 | }
58 |
59 | public static IOverScrollDecor setUpOverScroll(ScrollView scrollView) {
60 | return new VerticalOverScrollBounceEffectDecorator(new ScrollViewOverScrollDecorAdapter(scrollView));
61 | }
62 |
63 | public static IOverScrollDecor setUpOverScroll(HorizontalScrollView scrollView) {
64 | return new HorizontalOverScrollBounceEffectDecorator(new HorizontalScrollViewOverScrollDecorAdapter(scrollView));
65 | }
66 |
67 | /**
68 | * Set up the over-scroll over a generic view, assumed to always be over-scroll ready (e.g.
69 | * a plain text field, image view).
70 | *
71 | * @param view The view.
72 | * @param orientation One of {@link #ORIENTATION_HORIZONTAL} or {@link #ORIENTATION_VERTICAL}.
73 | *
74 | * @return The over-scroll effect 'decorator', enabling further effect configuration.
75 | */
76 | public static IOverScrollDecor setUpStaticOverScroll(View view, int orientation) {
77 | switch (orientation) {
78 | case ORIENTATION_HORIZONTAL:
79 | return new HorizontalOverScrollBounceEffectDecorator(new StaticOverScrollDecorAdapter(view));
80 |
81 | case ORIENTATION_VERTICAL:
82 | return new VerticalOverScrollBounceEffectDecorator(new StaticOverScrollDecorAdapter(view));
83 |
84 | default:
85 | throw new IllegalArgumentException("orientation");
86 | }
87 | }
88 |
89 | public static IOverScrollDecor setUpOverScroll(ViewPager viewPager) {
90 | return new HorizontalOverScrollBounceEffectDecorator(new ViewPagerOverScrollDecorAdapter(viewPager));
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/java/me/everything/android/ui/overscroll/VerticalOverScrollBounceEffectDecorator.java:
--------------------------------------------------------------------------------
1 | package me.everything.android.ui.overscroll;
2 |
3 | import android.view.MotionEvent;
4 | import android.view.View;
5 |
6 | import me.everything.android.ui.overscroll.adapters.IOverScrollDecoratorAdapter;
7 |
8 | /**
9 | * A concrete implementation of {@link OverScrollBounceEffectDecoratorBase} for a vertical orientation.
10 | *
11 | * @author amit
12 | */
13 | public class VerticalOverScrollBounceEffectDecorator extends OverScrollBounceEffectDecoratorBase {
14 |
15 | protected static class MotionAttributesVertical extends MotionAttributes {
16 |
17 | public boolean init(View view, MotionEvent event) {
18 |
19 | // We must have history available to calc the dx. Normally it's there - if it isn't temporarily,
20 | // we declare the event 'invalid' and expect it in consequent events.
21 | if (event.getHistorySize() == 0) {
22 | return false;
23 | }
24 |
25 | // Allow for counter-orientation-direction operations (e.g. item swiping) to run fluently.
26 | final float dy = event.getY(0) - event.getHistoricalY(0, 0);
27 | final float dx = event.getX(0) - event.getHistoricalX(0, 0);
28 | if (Math.abs(dx) > Math.abs(dy)) {
29 | return false;
30 | }
31 |
32 | mAbsOffset = view.getTranslationY();
33 | mDeltaOffset = dy;
34 | mDir = mDeltaOffset > 0;
35 |
36 | return true;
37 | }
38 | }
39 |
40 | protected static class AnimationAttributesVertical extends AnimationAttributes {
41 |
42 | public AnimationAttributesVertical() {
43 | mProperty = View.TRANSLATION_Y;
44 | }
45 |
46 | @Override
47 | protected void init(View view) {
48 | mAbsOffset = view.getTranslationY();
49 | mMaxOffset = view.getHeight();
50 | }
51 | }
52 |
53 | /**
54 | * C'tor, creating the effect with default arguments:
55 | *
Touch-drag ratio in 'forward' direction will be set to DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD.
56 | *
Touch-drag ratio in 'backwards' direction will be set to DEFAULT_TOUCH_DRAG_MOVE_RATIO_BCK.
57 | *
Deceleration factor (for the bounce-back effect) will be set to DEFAULT_DECELERATE_FACTOR.
58 | *
59 | * @param viewAdapter The view's encapsulation.
60 | */
61 | public VerticalOverScrollBounceEffectDecorator(IOverScrollDecoratorAdapter viewAdapter) {
62 | this(viewAdapter, DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD, DEFAULT_TOUCH_DRAG_MOVE_RATIO_BCK, DEFAULT_DECELERATE_FACTOR);
63 | }
64 |
65 | /**
66 | * C'tor, creating the effect with explicit arguments.
67 | * @param viewAdapter The view's encapsulation.
68 | * @param touchDragRatioFwd Ratio of touch distance to actual drag distance when in 'forward' direction.
69 | * @param touchDragRatioBck Ratio of touch distance to actual drag distance when in 'backward'
70 | * direction (opposite to initial one).
71 | * @param decelerateFactor Deceleration factor used when decelerating the motion to create the
72 | * bounce-back effect.
73 | */
74 | public VerticalOverScrollBounceEffectDecorator(IOverScrollDecoratorAdapter viewAdapter,
75 | float touchDragRatioFwd, float touchDragRatioBck, float decelerateFactor) {
76 | super(viewAdapter, decelerateFactor, touchDragRatioFwd, touchDragRatioBck);
77 | }
78 |
79 | @Override
80 | protected MotionAttributes createMotionAttributes() {
81 | return new MotionAttributesVertical();
82 | }
83 |
84 | @Override
85 | protected AnimationAttributes createAnimationAttributes() {
86 | return new AnimationAttributesVertical();
87 | }
88 |
89 | @Override
90 | protected void translateView(View view, float offset) {
91 | view.setTranslationY(offset);
92 | }
93 |
94 | @Override
95 | protected void translateViewAndEvent(View view, float offset, MotionEvent event) {
96 | view.setTranslationY(offset);
97 | event.offsetLocation(offset - event.getY(0), 0f);
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/AbsListViewOverScrollDecorAdapter.java:
--------------------------------------------------------------------------------
1 | package me.everything.android.ui.overscroll.adapters;
2 |
3 | import android.view.View;
4 | import android.widget.AbsListView;
5 |
6 | import me.everything.android.ui.overscroll.HorizontalOverScrollBounceEffectDecorator;
7 | import me.everything.android.ui.overscroll.VerticalOverScrollBounceEffectDecorator;
8 |
9 | /**
10 | * An adapter to enable over-scrolling over object of {@link AbsListView}, namely {@link
11 | * android.widget.ListView} and it's extensions, and {@link android.widget.GridView}.
12 | *
13 | * @author amit
14 | *
15 | * @see HorizontalOverScrollBounceEffectDecorator
16 | * @see VerticalOverScrollBounceEffectDecorator
17 | */
18 | public class AbsListViewOverScrollDecorAdapter implements IOverScrollDecoratorAdapter {
19 |
20 | protected final AbsListView mView;
21 |
22 | public AbsListViewOverScrollDecorAdapter(AbsListView view) {
23 | mView = view;
24 | }
25 |
26 | @Override
27 | public View getView() {
28 | return mView;
29 | }
30 |
31 | @Override
32 | public boolean isInAbsoluteStart() {
33 | return mView.getChildCount() > 0 && !canScrollListUp();
34 | }
35 |
36 | @Override
37 | public boolean isInAbsoluteEnd() {
38 | return mView.getChildCount() > 0 && !canScrollListDown();
39 | }
40 |
41 | public boolean canScrollListUp() {
42 | // Ported from AbsListView#canScrollList() which isn't compatible to all API levels
43 | final int firstTop = mView.getChildAt(0).getTop();
44 | final int firstPosition = mView.getFirstVisiblePosition();
45 | return firstPosition > 0 || firstTop < mView.getListPaddingTop();
46 | }
47 |
48 | public boolean canScrollListDown() {
49 | // Ported from AbsListView#canScrollList() which isn't compatible to all API levels
50 | final int childCount = mView.getChildCount();
51 | final int itemsCount = mView.getCount();
52 | final int firstPosition = mView.getFirstVisiblePosition();
53 | final int lastPosition = firstPosition + childCount;
54 | final int lastBottom = mView.getChildAt(childCount - 1).getBottom();
55 | return lastPosition < itemsCount || lastBottom > mView.getHeight() - mView.getListPaddingBottom();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/HorizontalScrollViewOverScrollDecorAdapter.java:
--------------------------------------------------------------------------------
1 | package me.everything.android.ui.overscroll.adapters;
2 |
3 | import android.view.View;
4 | import android.widget.HorizontalScrollView;
5 |
6 | import me.everything.android.ui.overscroll.HorizontalOverScrollBounceEffectDecorator;
7 | import me.everything.android.ui.overscroll.VerticalOverScrollBounceEffectDecorator;
8 |
9 | /**
10 | * An adapter that enables over-scrolling support over a {@link HorizontalScrollView}.
11 | *
Seeing that {@link HorizontalScrollView} only supports horizontal scrolling, this adapter
12 | * should only be used with a {@link HorizontalOverScrollBounceEffectDecorator}.
13 | *
14 | * @author amit
15 | *
16 | * @see HorizontalOverScrollBounceEffectDecorator
17 | * @see VerticalOverScrollBounceEffectDecorator
18 | */
19 | public class HorizontalScrollViewOverScrollDecorAdapter implements IOverScrollDecoratorAdapter {
20 |
21 | protected final HorizontalScrollView mView;
22 |
23 | public HorizontalScrollViewOverScrollDecorAdapter(HorizontalScrollView view) {
24 | mView = view;
25 | }
26 |
27 | @Override
28 | public View getView() {
29 | return mView;
30 | }
31 |
32 | @Override
33 | public boolean isInAbsoluteStart() {
34 | return !mView.canScrollHorizontally(-1);
35 | }
36 |
37 | @Override
38 | public boolean isInAbsoluteEnd() {
39 | return !mView.canScrollHorizontally(1);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/IOverScrollDecoratorAdapter.java:
--------------------------------------------------------------------------------
1 | package me.everything.android.ui.overscroll.adapters;
2 |
3 | import android.view.View;
4 |
5 | import me.everything.android.ui.overscroll.HorizontalOverScrollBounceEffectDecorator;
6 |
7 | /**
8 | * @author amitd
9 | *
10 | * @see HorizontalOverScrollBounceEffectDecorator
11 | */
12 | public interface IOverScrollDecoratorAdapter {
13 |
14 | View getView();
15 |
16 | /**
17 | * Is view in it's absolute start position - such that a negative over-scroll can potentially
18 | * be initiated. For example, in list-views, this is synonymous with the first item being
19 | * fully visible.
20 | *
21 | * @return Whether in absolute start position.
22 | */
23 | boolean isInAbsoluteStart();
24 |
25 | /**
26 | * Is view in it's absolute end position - such that an over-scroll can potentially
27 | * be initiated. For example, in list-views, this is synonymous with the last item being
28 | * fully visible.
29 | *
30 | * @return Whether in absolute end position.
31 | */
32 | boolean isInAbsoluteEnd();
33 | }
34 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/RecyclerViewOverScrollDecorAdapter.java:
--------------------------------------------------------------------------------
1 | package me.everything.android.ui.overscroll.adapters;
2 |
3 | import android.graphics.Canvas;
4 | import android.support.v7.widget.LinearLayoutManager;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.support.v7.widget.StaggeredGridLayoutManager;
7 | import android.support.v7.widget.helper.ItemTouchHelper;
8 | import android.view.View;
9 |
10 | import java.util.List;
11 |
12 | import me.everything.android.ui.overscroll.HorizontalOverScrollBounceEffectDecorator;
13 | import me.everything.android.ui.overscroll.VerticalOverScrollBounceEffectDecorator;
14 |
15 | /**
16 | * @author amitd
17 | *
18 | * @see HorizontalOverScrollBounceEffectDecorator
19 | * @see VerticalOverScrollBounceEffectDecorator
20 | */
21 | public class RecyclerViewOverScrollDecorAdapter implements IOverScrollDecoratorAdapter {
22 |
23 | /**
24 | * A delegation of the adapter implementation of this view that should provide the processing
25 | * of {@link #isInAbsoluteStart()} and {@link #isInAbsoluteEnd()}. Essentially needed simply
26 | * because the implementation depends on the layout manager implementation being used.
27 | */
28 | protected interface Impl {
29 | boolean isInAbsoluteStart();
30 | boolean isInAbsoluteEnd();
31 | }
32 |
33 | protected final RecyclerView mRecyclerView;
34 | protected final Impl mImpl;
35 |
36 | protected boolean mIsItemTouchInEffect = false;
37 |
38 | public RecyclerViewOverScrollDecorAdapter(RecyclerView recyclerView) {
39 |
40 | mRecyclerView = recyclerView;
41 |
42 | final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
43 | if (layoutManager instanceof LinearLayoutManager ||
44 | layoutManager instanceof StaggeredGridLayoutManager)
45 | {
46 | final int orientation =
47 | (layoutManager instanceof LinearLayoutManager
48 | ? ((LinearLayoutManager) layoutManager).getOrientation()
49 | : ((StaggeredGridLayoutManager) layoutManager).getOrientation());
50 |
51 | if (orientation == LinearLayoutManager.HORIZONTAL) {
52 | mImpl = new ImplHorizLayout();
53 | } else {
54 | mImpl = new ImplVerticalLayout();
55 | }
56 | }
57 | else
58 | {
59 | throw new IllegalArgumentException("Recycler views with custom layout managers are not supported by this adapter out of the box." +
60 | "Try implementing and providing an explicit 'impl' parameter to the other c'tors, or otherwise create a custom adapter subclass of your own.");
61 | }
62 | }
63 |
64 | public RecyclerViewOverScrollDecorAdapter(RecyclerView recyclerView, Impl impl) {
65 | mRecyclerView = recyclerView;
66 | mImpl = impl;
67 | }
68 |
69 | public RecyclerViewOverScrollDecorAdapter(RecyclerView recyclerView, ItemTouchHelper.Callback itemTouchHelperCallback) {
70 | this(recyclerView);
71 | setUpTouchHelperCallback(itemTouchHelperCallback);
72 | }
73 |
74 | public RecyclerViewOverScrollDecorAdapter(RecyclerView recyclerView, Impl impl, ItemTouchHelper.Callback itemTouchHelperCallback) {
75 | this(recyclerView, impl);
76 | setUpTouchHelperCallback(itemTouchHelperCallback);
77 | }
78 |
79 | protected void setUpTouchHelperCallback(final ItemTouchHelper.Callback itemTouchHelperCallback) {
80 | new ItemTouchHelper(new ItemTouchHelperCallbackWrapper(itemTouchHelperCallback) {
81 | @Override
82 | public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
83 | mIsItemTouchInEffect = actionState != 0;
84 | super.onSelectedChanged(viewHolder, actionState);
85 | }
86 | }).attachToRecyclerView(mRecyclerView);
87 | }
88 |
89 | @Override
90 | public View getView() {
91 | return mRecyclerView;
92 | }
93 |
94 | @Override
95 | public boolean isInAbsoluteStart() {
96 | return !mIsItemTouchInEffect && mImpl.isInAbsoluteStart();
97 | }
98 |
99 | @Override
100 | public boolean isInAbsoluteEnd() {
101 | return !mIsItemTouchInEffect && mImpl.isInAbsoluteEnd();
102 | }
103 |
104 | protected class ImplHorizLayout implements Impl {
105 |
106 | @Override
107 | public boolean isInAbsoluteStart() {
108 | return !mRecyclerView.canScrollHorizontally(-1);
109 | }
110 |
111 | @Override
112 | public boolean isInAbsoluteEnd() {
113 | return !mRecyclerView.canScrollHorizontally(1);
114 | }
115 | }
116 |
117 | protected class ImplVerticalLayout implements Impl {
118 |
119 | @Override
120 | public boolean isInAbsoluteStart() {
121 | return !mRecyclerView.canScrollVertically(-1);
122 | }
123 |
124 | @Override
125 | public boolean isInAbsoluteEnd() {
126 | return !mRecyclerView.canScrollVertically(1);
127 | }
128 | }
129 |
130 | private static class ItemTouchHelperCallbackWrapper extends ItemTouchHelper.Callback {
131 |
132 | final ItemTouchHelper.Callback mCallback;
133 |
134 | private ItemTouchHelperCallbackWrapper(ItemTouchHelper.Callback callback) {
135 | mCallback = callback;
136 | }
137 |
138 | @Override
139 | public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
140 | return mCallback.getMovementFlags(recyclerView, viewHolder);
141 | }
142 |
143 | @Override
144 | public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
145 | return mCallback.onMove(recyclerView, viewHolder, target);
146 | }
147 |
148 | @Override
149 | public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
150 | mCallback.onSwiped(viewHolder, direction);
151 | }
152 |
153 | @Override
154 | public int convertToAbsoluteDirection(int flags, int layoutDirection) {
155 | return mCallback.convertToAbsoluteDirection(flags, layoutDirection);
156 | }
157 |
158 | @Override
159 | public boolean canDropOver(RecyclerView recyclerView, RecyclerView.ViewHolder current, RecyclerView.ViewHolder target) {
160 | return mCallback.canDropOver(recyclerView, current, target);
161 | }
162 |
163 | @Override
164 | public boolean isLongPressDragEnabled() {
165 | return mCallback.isLongPressDragEnabled();
166 | }
167 |
168 | @Override
169 | public boolean isItemViewSwipeEnabled() {
170 | return mCallback.isItemViewSwipeEnabled();
171 | }
172 |
173 | @Override
174 | public int getBoundingBoxMargin() {
175 | return mCallback.getBoundingBoxMargin();
176 | }
177 |
178 | @Override
179 | public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) {
180 | return mCallback.getSwipeThreshold(viewHolder);
181 | }
182 |
183 | @Override
184 | public float getMoveThreshold(RecyclerView.ViewHolder viewHolder) {
185 | return mCallback.getMoveThreshold(viewHolder);
186 | }
187 |
188 | @Override
189 | public RecyclerView.ViewHolder chooseDropTarget(RecyclerView.ViewHolder selected, List dropTargets, int curX, int curY) {
190 | return mCallback.chooseDropTarget(selected, dropTargets, curX, curY);
191 | }
192 |
193 | @Override
194 | public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
195 | mCallback.onSelectedChanged(viewHolder, actionState);
196 | }
197 |
198 | @Override
199 | public void onMoved(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, int fromPos, RecyclerView.ViewHolder target, int toPos, int x, int y) {
200 | mCallback.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y);
201 | }
202 |
203 | @Override
204 | public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
205 | mCallback.clearView(recyclerView, viewHolder);
206 | }
207 |
208 | @Override
209 | public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
210 | mCallback.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
211 | }
212 |
213 | @Override
214 | public void onChildDrawOver(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
215 | mCallback.onChildDrawOver(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
216 | }
217 |
218 | @Override
219 | public long getAnimationDuration(RecyclerView recyclerView, int animationType, float animateDx, float animateDy) {
220 | return mCallback.getAnimationDuration(recyclerView, animationType, animateDx, animateDy);
221 | }
222 |
223 | @Override
224 | public int interpolateOutOfBoundsScroll(RecyclerView recyclerView, int viewSize, int viewSizeOutOfBounds, int totalSize, long msSinceStartScroll) {
225 | return mCallback.interpolateOutOfBoundsScroll(recyclerView, viewSize, viewSizeOutOfBounds, totalSize, msSinceStartScroll);
226 | }
227 | }
228 | }
229 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/ScrollViewOverScrollDecorAdapter.java:
--------------------------------------------------------------------------------
1 | package me.everything.android.ui.overscroll.adapters;
2 |
3 | import android.view.View;
4 | import android.widget.ScrollView;
5 |
6 | import me.everything.android.ui.overscroll.HorizontalOverScrollBounceEffectDecorator;
7 | import me.everything.android.ui.overscroll.VerticalOverScrollBounceEffectDecorator;
8 |
9 | /**
10 | * An adapter that enables over-scrolling over a {@link ScrollView}.
11 | *
Seeing that {@link ScrollView} only supports vertical scrolling, this adapter
12 | * should only be used with a {@link VerticalOverScrollBounceEffectDecorator}. For horizontal
13 | * over-scrolling, use {@link HorizontalScrollViewOverScrollDecorAdapter} in conjunction with
14 | * a {@link android.widget.HorizontalScrollView}.
15 | *
16 | * @author amit
17 | *
18 | * @see HorizontalOverScrollBounceEffectDecorator
19 | * @see VerticalOverScrollBounceEffectDecorator
20 | */
21 | public class ScrollViewOverScrollDecorAdapter implements IOverScrollDecoratorAdapter {
22 |
23 | protected final ScrollView mView;
24 |
25 | public ScrollViewOverScrollDecorAdapter(ScrollView view) {
26 | mView = view;
27 | }
28 |
29 | @Override
30 | public View getView() {
31 | return mView;
32 | }
33 |
34 | @Override
35 | public boolean isInAbsoluteStart() {
36 | return !mView.canScrollVertically(-1);
37 | }
38 |
39 | @Override
40 | public boolean isInAbsoluteEnd() {
41 | return !mView.canScrollVertically(1);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/StaticOverScrollDecorAdapter.java:
--------------------------------------------------------------------------------
1 | package me.everything.android.ui.overscroll.adapters;
2 |
3 | import android.view.View;
4 |
5 | import me.everything.android.ui.overscroll.HorizontalOverScrollBounceEffectDecorator;
6 | import me.everything.android.ui.overscroll.VerticalOverScrollBounceEffectDecorator;
7 |
8 | /**
9 | * A static adapter for views that are ALWAYS over-scroll-able (e.g. image view).
10 | *
11 | * @author amit
12 | *
13 | * @see HorizontalOverScrollBounceEffectDecorator
14 | * @see VerticalOverScrollBounceEffectDecorator
15 | */
16 | public class StaticOverScrollDecorAdapter implements IOverScrollDecoratorAdapter {
17 |
18 | protected final View mView;
19 |
20 | public StaticOverScrollDecorAdapter(View view) {
21 | mView = view;
22 | }
23 |
24 | @Override
25 | public View getView() {
26 | return mView;
27 | }
28 |
29 | @Override
30 | public boolean isInAbsoluteStart() {
31 | return true;
32 | }
33 |
34 | @Override
35 | public boolean isInAbsoluteEnd() {
36 | return true;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/liboverscroll/src/main/java/me/everything/android/ui/overscroll/adapters/ViewPagerOverScrollDecorAdapter.java:
--------------------------------------------------------------------------------
1 | package me.everything.android.ui.overscroll.adapters;
2 |
3 | import android.support.v4.view.ViewPager;
4 | import android.view.View;
5 |
6 | import me.everything.android.ui.overscroll.HorizontalOverScrollBounceEffectDecorator;
7 |
8 | /**
9 | * Created by Bruce too
10 | * Enhance by amit
11 | * On 2016/6/16
12 | * At 14:51
13 | * An adapter to enable over-scrolling over object of {@link ViewPager}
14 | *
15 | * @see HorizontalOverScrollBounceEffectDecorator
16 | */
17 | public class ViewPagerOverScrollDecorAdapter implements IOverScrollDecoratorAdapter, ViewPager.OnPageChangeListener {
18 |
19 | protected final ViewPager mViewPager;
20 |
21 | protected int mLastPagerPosition = 0;
22 | protected float mLastPagerScrollOffset;
23 |
24 | public ViewPagerOverScrollDecorAdapter(ViewPager viewPager) {
25 | this.mViewPager = viewPager;
26 |
27 | mViewPager.addOnPageChangeListener(this);
28 |
29 | mLastPagerPosition = mViewPager.getCurrentItem();
30 | mLastPagerScrollOffset = 0f;
31 | }
32 |
33 | @Override
34 | public View getView() {
35 | return mViewPager;
36 | }
37 |
38 | @Override
39 | public boolean isInAbsoluteStart() {
40 |
41 | return mLastPagerPosition == 0 &&
42 | mLastPagerScrollOffset == 0f;
43 | }
44 |
45 | @Override
46 | public boolean isInAbsoluteEnd() {
47 |
48 | return mLastPagerPosition == mViewPager.getAdapter().getCount()-1 &&
49 | mLastPagerScrollOffset == 0f;
50 | }
51 |
52 | @Override
53 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
54 | mLastPagerPosition = position;
55 | mLastPagerScrollOffset = positionOffset;
56 | }
57 |
58 | @Override
59 | public void onPageSelected(int position) {
60 |
61 | }
62 |
63 | @Override
64 | public void onPageScrollStateChanged(int state) {
65 |
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/recyclerviewhelper/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/recyclerviewhelper/.settings/org.eclipse.buildship.core.prefs:
--------------------------------------------------------------------------------
1 | #Thu Jun 29 09:47:32 PDT 2017
2 | connection.project.dir=..
3 |
--------------------------------------------------------------------------------
/recyclerviewhelper/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Nishant Srivastava
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | apply plugin: 'com.android.library'
18 |
19 | android {
20 | compileSdkVersion 26
21 | buildToolsVersion '27.0.3'
22 |
23 | defaultConfig {
24 | minSdkVersion 17
25 | targetSdkVersion 26
26 | versionCode 1
27 | versionName "1.0"
28 | }
29 | buildTypes {
30 | release {
31 | minifyEnabled false
32 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
33 | }
34 | }
35 | }
36 |
37 | dependencies {
38 | implementation fileTree(dir: 'libs', include: ['*.jar'])
39 | testImplementation 'junit:junit:4.12'
40 | compileOnly "com.android.support:appcompat-v7:25.1.0"
41 | compileOnly "com.android.support:recyclerview-v7:25.1.0"
42 | }
43 |
44 | if (project.hasProperty('publish') && project.getProperty('publish')) {
45 | // Bintray Params
46 | ext {
47 | bintrayRepo = 'maven'
48 | bintrayName = rootProject.ext.libBintrayName
49 |
50 | publishedGroupId = GROUP
51 | libraryName = rootProject.ext.libModuleName
52 | artifact = rootProject.ext.libModuleName // Has to be same as your library module name
53 |
54 | libraryDescription = rootProject.ext.libModuleDesc
55 |
56 | // Your github repo link
57 | siteUrl = rootProject.ext.libPomUrl
58 | gitUrl = rootProject.ext.libPomUrl + '.git'
59 | githubRepository = rootProject.ext.libGithubRepo
60 |
61 | libraryVersion = rootProject.ext.libVersionName
62 |
63 | developerId = POM_DEVELOPER_ID
64 | developerName = POM_DEVELOPER_NAME
65 | developerEmail = POM_DEVELOPER_EMAILID
66 |
67 | licenseName = POM_LICENCE_NAME
68 | licenseUrl = POM_LICENCE_URL
69 | allLicenses = [POM_ALL_LICENCES]
70 | }
71 |
72 | // Place it at the end of the file
73 | apply from: 'https://raw.githubusercontent.com/nisrulz/JCenter/master/installv1.gradle'
74 | apply from: 'https://raw.githubusercontent.com/nisrulz/JCenter/master/bintrayv1.gradle'
75 |
76 |
77 | javadoc {
78 | failOnError = false
79 | }
80 | }
--------------------------------------------------------------------------------
/recyclerviewhelper/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 /Users/nishant/android_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 |
--------------------------------------------------------------------------------
/recyclerviewhelper/src/androidTest/java/github/nisrulz/recyclerviewhelper/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Nishant Srivastava
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package github.nisrulz.recyclerviewhelper;
18 |
19 | import android.app.Application;
20 | import android.test.ApplicationTestCase;
21 |
22 | /**
23 | * Testing Fundamentals
24 | */
25 | public class ApplicationTest extends ApplicationTestCase {
26 | public ApplicationTest() {
27 | super(Application.class);
28 | }
29 | }
--------------------------------------------------------------------------------
/recyclerviewhelper/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/recyclerviewhelper/src/main/java/github/nisrulz/recyclerviewhelper/RVHAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Nishant Srivastava
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package github.nisrulz.recyclerviewhelper;
18 |
19 | /**
20 | * Interface to notify a RecyclerView.Adapter of moving and dismissal event
21 | */
22 | public interface RVHAdapter {
23 |
24 | /**
25 | * Called when an item has been dragged far enough to trigger a move. This is called every time
26 | * an item is shifted, and not at the end of a "drop" event.
27 | *
28 | * Implementations should call RecyclerView.Adapter notifyItemMoved(int, int) after
29 | * adjusting the underlying data to reflect this move.
30 | *
31 | * @param fromPosition
32 | * The start position of the moved item.
33 | * @param toPosition
34 | * Then resolved position of the moved item.
35 | * @return True if the item was moved to the new adapter position.
36 | */
37 | boolean onItemMove(int fromPosition, int toPosition);
38 |
39 | /**
40 | * Called when an item has been dismissed by a swipe.
41 | *
42 | * Implementations should call RecyclerView.Adapter notifyItemRemoved(int) after
43 | * adjusting the underlying data to reflect this removal.
44 | *
45 | * @param position
46 | * The position of the item dismissed.
47 | * @param direction
48 | * the direction
49 | */
50 | void onItemDismiss(int position, int direction);
51 | void onItemSwipeDrag(float dX,float dY,int position);
52 | void onItemLongPress(float dX,float dY,int position);
53 | }
54 |
--------------------------------------------------------------------------------
/recyclerviewhelper/src/main/java/github/nisrulz/recyclerviewhelper/RVHItemClickListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Nishant Srivastava
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package github.nisrulz.recyclerviewhelper;
18 |
19 | import android.content.Context;
20 | import android.support.v7.widget.RecyclerView;
21 | import android.util.Log;
22 | import android.view.GestureDetector;
23 | import android.view.MotionEvent;
24 | import android.view.View;
25 |
26 | /**
27 | * The type Rvh item click listener.
28 | */
29 | public class RVHItemClickListener implements RecyclerView.OnItemTouchListener {
30 | private final OnItemClickListener mListener;
31 | /**
32 | * The M gesture detector.
33 | */
34 | private final GestureDetector mGestureDetector;
35 |
36 | /**
37 | * Instantiates a new Rvh item click listener.
38 | *
39 | * @param context
40 | * the context
41 | * @param listener
42 | * the listener
43 | */
44 | public RVHItemClickListener(Context context, OnItemClickListener listener) {
45 | mListener = listener;
46 | mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
47 | @Override
48 | public boolean onSingleTapUp(MotionEvent e) {
49 | return true;
50 | }
51 |
52 | @Override
53 | public boolean onDown(MotionEvent e) {
54 | return true;
55 | }
56 |
57 | @Override
58 | public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
59 |
60 | return true;
61 | }
62 |
63 | @Override
64 | public void onShowPress(MotionEvent e) {
65 | //Log.e("On Show Press","ShowPress");
66 | mListener.onItemShowPress(longPressView,longPressPos,e.getX(),e.getY());
67 | mListener.detectShowPress(true,longPressPos);
68 | //手指触摸屏幕,并且尚未松开或拖动。与onDown的区别是,onShowPress强调没用松开和没有拖动
69 | }
70 |
71 | @Override
72 | public void onLongPress(MotionEvent e){
73 | mListener.onItemLongPress(longPressView,longPressPos,e.getX(),e.getY());
74 | }
75 |
76 |
77 | });
78 | }
79 |
80 | private View longPressView;
81 | private int longPressPos;
82 |
83 | @Override
84 | public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
85 | View childView = view.findChildViewUnder(e.getX(), e.getY());
86 | // if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e) && childView !=view.getChildAt(0)) {
87 | //
88 | //
89 | // if(e.getAction() == MotionEvent.ACTION_UP){
90 | // Log.e("Here","Here");
91 | // mListener.onItemTouchUp(childView, view.getChildAdapterPosition(childView),e.getX(),e.getY());
92 | // }
93 | // else if (e.getAction() == MotionEvent.ACTION_DOWN){
94 | // longPressView = childView;
95 | // longPressPos = view.getChildAdapterPosition(childView);
96 | // mListener.onItemTouchDown(childView, view.getChildAdapterPosition(childView),e.getX(),e.getY());
97 | // }
98 | // return true;
99 | //
100 | // }
101 |
102 | if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e) ) {
103 |
104 |
105 | if(e.getAction() == MotionEvent.ACTION_UP){
106 | Log.e("RVHClickListenr","UP");
107 | mListener.detectShowPress(false,longPressPos);
108 | mListener.onItemTouchUp(childView, view.getChildAdapterPosition(childView),e.getX(),e.getY());
109 | return false;
110 | }
111 | else if (e.getAction() == MotionEvent.ACTION_DOWN){
112 | Log.e("RVHClickListenr","Down");
113 | longPressView = childView;
114 | longPressPos = view.getChildAdapterPosition(childView);
115 | mListener.onItemTouchDown(childView, view.getChildAdapterPosition(childView),e.getX(),e.getY());
116 | //让事件继续传递,从 rv 到 adapter 的 item里面
117 | return false;
118 | }
119 |
120 | else if (e.getAction() == MotionEvent.ACTION_MOVE){
121 | //Log.e("RVHClickListenr","MOVE");
122 | //让事件继续传递,从 rv 到 adapter 的 item里面
123 | mListener.onItemTouchMove(childView, view.getChildAdapterPosition(childView),e.getX(),e.getY());
124 | return false;
125 | }
126 | else if (e.getAction() == MotionEvent.ACTION_CANCEL){
127 | //Log.e("RVHClickListenr","CANCEL");
128 | //让事件继续传递,从 rv 到 adapter 的 item里面
129 | return false;
130 | }
131 |
132 | }
133 |
134 | return false;
135 | }
136 |
137 | @Override
138 | public void onTouchEvent(RecyclerView view, MotionEvent e) {
139 | // Do nothing
140 | }
141 |
142 | @Override
143 | public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
144 | // Do nothings
145 | }
146 |
147 | /**
148 | * The interface On item click listener.
149 | */
150 | public interface OnItemClickListener {
151 | /**
152 | * On item click.
153 | *
154 | * @param view
155 | * the view
156 | * @param position
157 | * the position
158 | */
159 | void onItemTouchUp(View view, int position,float dX,float dY);
160 | void onItemTouchDown(View view, int position,float dX,float dY);
161 | void onItemTouchMove(View view, int position,float dX,float dY);
162 | void onItemLongPress(View view,int position,float dX,float dY);
163 | void onItemShowPress(View view,int position,float dX,float dY);
164 | void onOutsideTouch(float dX,float dY);
165 | void detectShowPress(boolean boo,int position);
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/recyclerviewhelper/src/main/java/github/nisrulz/recyclerviewhelper/RVHItemDividerDecoration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Nishant Srivastava
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package github.nisrulz.recyclerviewhelper;
18 |
19 | import android.content.Context;
20 | import android.content.res.TypedArray;
21 | import android.graphics.Canvas;
22 | import android.graphics.Rect;
23 | import android.graphics.drawable.Drawable;
24 | import android.support.v7.widget.LinearLayoutManager;
25 | import android.support.v7.widget.RecyclerView;
26 | import android.view.View;
27 |
28 | /**
29 | * The type Rvh item divider decoration.
30 | */
31 | public class RVHItemDividerDecoration extends RecyclerView.ItemDecoration {
32 |
33 | /**
34 | * The constant HORIZONTAL_LIST.
35 | */
36 | public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
37 | /**
38 | * The constant VERTICAL_LIST.
39 | */
40 | public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
41 | private static final int[] ATTRS = new int[] {
42 | android.R.attr.listDivider
43 | };
44 | private final Drawable mDivider;
45 |
46 | private int mOrientation;
47 |
48 | /**
49 | * Instantiates a new Rvh item divider decoration.
50 | *
51 | * @param context
52 | * the context
53 | * @param orientation
54 | * the orientation
55 | */
56 | public RVHItemDividerDecoration(Context context, int orientation) {
57 | final TypedArray a = context.obtainStyledAttributes(ATTRS);
58 | mDivider = a.getDrawable(0);
59 | a.recycle();
60 | setOrientation(orientation);
61 | }
62 |
63 | /**
64 | * Sets orientation.
65 | *
66 | * @param orientation
67 | * the orientation
68 | */
69 | public void setOrientation(int orientation) {
70 | if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
71 | throw new IllegalArgumentException("invalid orientation");
72 | }
73 | mOrientation = orientation;
74 | }
75 |
76 | @Override
77 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
78 | super.onDraw(c, parent, state);
79 |
80 | if (mOrientation == VERTICAL_LIST) {
81 | drawVertical(c, parent);
82 | } else {
83 | drawHorizontal(c, parent);
84 | }
85 | }
86 |
87 | /**
88 | * Draw vertical.
89 | *
90 | * @param c
91 | * the c
92 | * @param parent
93 | * the parent
94 | */
95 | private void drawVertical(Canvas c, RecyclerView parent) {
96 | final int left = parent.getPaddingLeft();
97 | final int right = parent.getWidth() - parent.getPaddingRight();
98 |
99 | final int childCount = parent.getChildCount();
100 | for (int i = 0; i < childCount; i++) {
101 | final View child = parent.getChildAt(i);
102 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
103 | final int top = child.getBottom() + params.bottomMargin + Math.round(child.getTranslationY());
104 | final int bottom = top + mDivider.getIntrinsicHeight();
105 | mDivider.setBounds(left, top, right, bottom);
106 | mDivider.draw(c);
107 | }
108 | }
109 |
110 | /**
111 | * Draw horizontal.
112 | *
113 | * @param c
114 | * the c
115 | * @param parent
116 | * the parent
117 | */
118 | private void drawHorizontal(Canvas c, RecyclerView parent) {
119 | final int top = parent.getPaddingTop();
120 | final int bottom = parent.getHeight() - parent.getPaddingBottom();
121 |
122 | final int childCount = parent.getChildCount();
123 | for (int i = 0; i < childCount; i++) {
124 | final View child = parent.getChildAt(i);
125 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
126 | final int left = child.getRight() + params.rightMargin + Math.round(child.getTranslationX());
127 | final int right = left + mDivider.getIntrinsicHeight();
128 | mDivider.setBounds(left, top, right, bottom);
129 | mDivider.draw(c);
130 | }
131 | }
132 |
133 | @Override
134 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
135 | RecyclerView.State state) {
136 | super.getItemOffsets(outRect, view, parent, state);
137 |
138 | if (mOrientation == VERTICAL_LIST) {
139 | outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
140 | } else {
141 | outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
142 | }
143 | }
144 | }
--------------------------------------------------------------------------------
/recyclerviewhelper/src/main/java/github/nisrulz/recyclerviewhelper/RVHItemTouchHelperCallback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Nishant Srivastava
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package github.nisrulz.recyclerviewhelper;
18 |
19 | import android.graphics.Canvas;
20 | import android.support.v7.widget.RecyclerView;
21 | import android.util.Log;
22 |
23 | import static android.support.v7.widget.helper.ItemTouchHelper.ACTION_STATE_IDLE;
24 | import static android.support.v7.widget.helper.ItemTouchHelper.ACTION_STATE_SWIPE;
25 | import static android.support.v7.widget.helper.ItemTouchHelper.Callback;
26 | import static android.support.v7.widget.helper.ItemTouchHelper.DOWN;
27 | import static android.support.v7.widget.helper.ItemTouchHelper.END;
28 | import static android.support.v7.widget.helper.ItemTouchHelper.START;
29 | import static android.support.v7.widget.helper.ItemTouchHelper.UP;
30 |
31 | /**
32 | * The type Rvh item touch helper callback.
33 | */
34 | public class RVHItemTouchHelperCallback extends Callback {
35 |
36 | @Deprecated
37 | private final RVHAdapter mAdapter;
38 |
39 | private final boolean isLongPressDragEnabled;
40 | private final boolean isItemViewSwipeEnabledLeft;
41 | private final boolean isItemViewSwipeEnabledRight;
42 | public boolean disableSwipe;
43 | public int orginIndex;
44 |
45 | public RecyclerView referenceRV;
46 |
47 | /**
48 | * Instantiates a new Rvh item touch helper callback.
49 | *
50 | * @param adapter
51 | * the adapter
52 | * @param isLongPressDragEnabled
53 | * the is long press drag enabled
54 | * @param isItemViewSwipeEnabledLeft
55 | * the is item view swipe enabled left
56 | * @param isItemViewSwipeEnabledRight
57 | * the is item view swipe enabled right
58 | */
59 | public RVHItemTouchHelperCallback(RVHAdapter adapter, boolean isLongPressDragEnabled,
60 | boolean isItemViewSwipeEnabledLeft, boolean isItemViewSwipeEnabledRight) {
61 | mAdapter = adapter;
62 | this.isItemViewSwipeEnabledLeft = isItemViewSwipeEnabledLeft;
63 | this.isItemViewSwipeEnabledRight = isItemViewSwipeEnabledRight;
64 | this.isLongPressDragEnabled = isLongPressDragEnabled;
65 | }
66 |
67 | @Override
68 | public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
69 | final int dragFlags = UP | DOWN | START | END; // UP | DOWN
70 | final int swipeFlags;
71 | if (isItemViewSwipeEnabledLeft && isItemViewSwipeEnabledRight) {
72 | swipeFlags = START | END ; // START | END
73 | }
74 | else if (isItemViewSwipeEnabledRight) {
75 | swipeFlags = START;
76 | }
77 | else {
78 | swipeFlags = END;
79 | }
80 |
81 | return Callback.makeMovementFlags(dragFlags, swipeFlags);
82 | }
83 |
84 | @Override
85 | public boolean canDropOver(RecyclerView recyclerView, RecyclerView.ViewHolder current,
86 | RecyclerView.ViewHolder target) {
87 | return current.getItemViewType() == target.getItemViewType();
88 | }
89 |
90 | @Override
91 | public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source,
92 | RecyclerView.ViewHolder target) {
93 | // Notify the adapter of the move
94 | ((RVHAdapter) referenceRV.getAdapter()).onItemMove(source.getAdapterPosition(), target.getAdapterPosition());
95 | return true;
96 | }
97 |
98 | @Override
99 | public boolean isLongPressDragEnabled() {
100 | return isLongPressDragEnabled;
101 | }
102 |
103 | @Override
104 | public boolean isItemViewSwipeEnabled() {
105 |
106 | if(disableSwipe){
107 | return false;
108 | }
109 | else{
110 |
111 | return isItemViewSwipeEnabledLeft || isItemViewSwipeEnabledRight;
112 | }
113 | }
114 |
115 | @Override
116 | public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
117 | Log.e("Swipe","On Swipe!");
118 | ((RVHAdapter) referenceRV.getAdapter()).onItemDismiss(viewHolder.getAdapterPosition(), direction);
119 | }
120 |
121 | @Override
122 | public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
123 | // We only want the active item to change
124 | if (actionState != ACTION_STATE_IDLE && viewHolder instanceof RVHViewHolder) {
125 | // Let the view holder know that this item is being moved or dragged
126 | RVHViewHolder itemViewHolder = (RVHViewHolder) viewHolder;
127 | itemViewHolder.onItemSelected(actionState,viewHolder.getAdapterPosition());
128 | }
129 |
130 | super.onSelectedChanged(viewHolder, actionState);
131 | }
132 |
133 | @Override
134 | public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
135 | super.clearView(recyclerView, viewHolder);
136 |
137 | if (viewHolder instanceof RVHViewHolder) {
138 | // Tell the view holder it's time to restore the idle state
139 | RVHViewHolder itemViewHolder = (RVHViewHolder) viewHolder;
140 | itemViewHolder.onItemClear();
141 | }
142 | }
143 |
144 | @Override
145 | public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
146 | float dX, float dY, int actionState, boolean isCurrentlyActive) {
147 | if (actionState == ACTION_STATE_SWIPE ) {
148 | // Fade out the view as it is swiped out of the parent's bounds
149 |
150 | if(orginIndex !=0){
151 |
152 | viewHolder.itemView.setTranslationX(dX);
153 | viewHolder.itemView.setTranslationY(dY); //
154 | ((RVHAdapter) referenceRV.getAdapter()).onItemSwipeDrag(dX,dY,viewHolder.getAdapterPosition()); //
155 | }
156 |
157 |
158 | // viewHolder.itemView.setTranslationX(dX);
159 | // viewHolder.itemView.setTranslationY(dY); //
160 | // ((RVHAdapter) referenceRV.getAdapter()).onItemSwipeDrag(dX,dY,viewHolder.getAdapterPosition()); //
161 | }
162 | else {
163 | //super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
164 |
165 | if(orginIndex !=0){
166 | ((RVHAdapter) referenceRV.getAdapter()).onItemLongPress(dX,dY,viewHolder.getAdapterPosition());
167 | }
168 | //Log.e("Here","here");
169 | }
170 | }
171 |
172 | }
173 |
--------------------------------------------------------------------------------
/recyclerviewhelper/src/main/java/github/nisrulz/recyclerviewhelper/RVHViewHolder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Nishant Srivastava
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package github.nisrulz.recyclerviewhelper;
18 |
19 | /**
20 | * The interface Rvh view holder.
21 | */
22 | public interface RVHViewHolder {
23 |
24 | /**
25 | * Called when the ItemTouchHelper first registers an item as being moved or swiped.
26 | * Implementations should update the item view to indicate it's active state.
27 | *
28 | * @param actionstate
29 | * the actionstate
30 | */
31 | void onItemSelected(int actionstate,int position);
32 |
33 | /**
34 | * Called when the ItemTouchHelper has completed the move or swipe, and the active item
35 | * state should be cleared.
36 | */
37 | void onItemClear();
38 | }
39 |
--------------------------------------------------------------------------------
/recyclerviewhelper/src/test/java/github/nisrulz/recyclerviewhelper/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Nishant Srivastava
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package github.nisrulz.recyclerviewhelper;
18 |
19 | import org.junit.Test;
20 |
21 | import static org.junit.Assert.assertEquals;
22 |
23 | /**
24 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
25 | */
26 | public class ExampleUnitTest {
27 | @Test
28 | public void addition_isCorrect() throws Exception {
29 | assertEquals(4, 2 + 2);
30 | }
31 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':springylib',':liboverscroll',':supportrenderscriptblur',':recyclerviewhelper'
2 |
--------------------------------------------------------------------------------
/springylib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/springylib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 26
5 | buildToolsVersion '27.0.3'
6 |
7 | defaultConfig {
8 | minSdkVersion 15
9 | targetSdkVersion 26
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 |
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | }
23 |
24 | dependencies {
25 | implementation fileTree(dir: 'libs', include: ['*.jar'])
26 | androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
27 | exclude group: 'com.android.support', module: 'support-annotations'
28 | })
29 | implementation 'com.android.support:appcompat-v7:26.+'
30 | implementation 'com.android.support:recyclerview-v7:25.1.0'
31 | testImplementation 'junit:junit:4.12'
32 | implementation 'com.facebook.rebound:rebound:0.3.8'
33 | }
34 |
--------------------------------------------------------------------------------
/springylib/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 D:\Softwares\Study_Softwares\android-studio-document\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 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/springylib/src/androidTest/java/com/zach/salman/springylib/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.zach.salman.springylib;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.zach.salman.springylib.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/springylib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/springylib/src/main/java/com/zach/salman/springylib/SpringAnimationType.java:
--------------------------------------------------------------------------------
1 | package com.zach.salman.springylib;
2 |
3 | /**
4 | * Created by salman on 21/11/16.
5 | */
6 |
7 | public enum SpringAnimationType {
8 | TRANSLATEX,
9 | TRANSLATEY,
10 | ROTATEX,
11 | ROTATEY,
12 | SCALEXY,
13 | SCALEX,
14 | SCALEY,
15 | ALPHA,
16 | ROTATION
17 | }
18 |
--------------------------------------------------------------------------------
/springylib/src/main/java/com/zach/salman/springylib/SpringyAnimator.java:
--------------------------------------------------------------------------------
1 | package com.zach.salman.springylib;
2 |
3 | import android.view.View;
4 |
5 | import com.facebook.rebound.SimpleSpringListener;
6 | import com.facebook.rebound.Spring;
7 | import com.facebook.rebound.SpringConfig;
8 | import com.facebook.rebound.SpringSystem;
9 | import com.facebook.rebound.SpringUtil;
10 |
11 |
12 | /**
13 | * Created by salman on 17/11/16.
14 | */
15 |
16 | public class SpringyAnimator {
17 | private float startValue, endValue;
18 | private static final float DEFAULT_TENSION = 40;
19 | private static final float DEFAULT_FRACTION = 7;
20 | private double tension,fraction;
21 | private SpringSystem springSystem;
22 | private SpringAnimationType animationType;
23 | private SpringyListener springAnimatorListener;
24 | private int delay = 0;
25 |
26 |
27 | /**
28 | * Constructor for with Animation Type + Spring config + animation Values
29 | * * @param springConfig config class for the spring
30 | * @param type SpringyAnimationType instance for animation type
31 | * @param tension Spring tension for animation type
32 | * @param fraction Spring fraction value for animation
33 | * @param startValue where animation start from
34 | * @param endValue where animation ends to
35 | * **/
36 |
37 |
38 | public SpringyAnimator(SpringAnimationType type, double tension,
39 | double fraction, float startValue, float endValue) {
40 | this.tension = tension;
41 | this.fraction = fraction;
42 | this.startValue = startValue;
43 | this.endValue = endValue;
44 | springSystem = SpringSystem.create();
45 | animationType = type;
46 |
47 | }
48 |
49 |
50 |
51 | /**
52 | * Constructor for with Animation Type + default config for spring + animation Values
53 | * * @param springConfig config class for the spring
54 | * @param type SpringyAnimationType instance for animation type
55 | * @param startValue where animation start from
56 | * @param endValue where animation ends to
57 | * **/
58 | public SpringyAnimator(SpringAnimationType type, float startValue,
59 | float endValue) {
60 | this.tension = DEFAULT_TENSION;
61 | this.fraction = DEFAULT_FRACTION;
62 | this.startValue = startValue;
63 | this.endValue = endValue;
64 | springSystem = SpringSystem.create();
65 | animationType = type;
66 |
67 | }
68 |
69 |
70 |
71 |
72 | /**
73 | * @param delay int value for SpringyAnimation delay each item if we have multiple items in
74 | * animation raw.
75 | * **/
76 | public void setDelay(int delay) {
77 | this.delay = delay;
78 | }
79 |
80 | public void startSpring(final View view) {
81 | setInitValue(view);
82 | Runnable startAnimation = new Runnable() {
83 | @Override
84 | public void run() {
85 | Spring spring = springSystem.createSpring();
86 | spring.setSpringConfig(SpringConfig.fromOrigamiTensionAndFriction(tension, fraction));
87 | spring.addListener(new SimpleSpringListener() {
88 | @Override
89 | public void onSpringUpdate(Spring spring) {
90 | view.setVisibility(View.VISIBLE);
91 | final float value = (float) SpringUtil.mapValueFromRangeToRange(spring.getCurrentValue(), 0, 1, startValue, endValue);
92 | switch (animationType) {
93 | case TRANSLATEY:
94 | view.setTranslationY(value);
95 | break;
96 | case TRANSLATEX:
97 | view.setTranslationX(value);
98 | break;
99 | case ALPHA:
100 | view.setAlpha(value);
101 | break;
102 | case SCALEY:
103 | view.setScaleY(value);
104 | break;
105 | case SCALEX:
106 | view.setScaleX(value);
107 | break;
108 | case SCALEXY:
109 | view.setScaleY(value);
110 | view.setScaleX(value);
111 | break;
112 | case ROTATEY:
113 | view.setRotationY(value);
114 | break;
115 | case ROTATEX:
116 | view.setRotationX(value);
117 | break;
118 | case ROTATION:
119 | view.setRotation(value);
120 | break;
121 | }
122 | }
123 |
124 | @Override
125 | public void onSpringAtRest(Spring spring) {
126 | if (springAnimatorListener != null){
127 | springAnimatorListener.onSpringStop();
128 | }
129 | }
130 |
131 | @Override
132 | public void onSpringActivate(Spring spring) {
133 | if (springAnimatorListener != null){
134 | springAnimatorListener.onSpringStart();
135 | }
136 | }
137 |
138 | });
139 | spring.setEndValue(1);
140 | }
141 | };
142 | view.postDelayed(startAnimation, delay);
143 |
144 | }
145 |
146 | /**
147 | * @param view instance for set pre animation value
148 | * **/
149 | private void setInitValue(View view) {
150 | switch (animationType) {
151 | case TRANSLATEY:
152 | view.setTranslationY(startValue);
153 | break;
154 | case TRANSLATEX:
155 | view.setTranslationX(startValue);
156 | break;
157 | case ALPHA:
158 | view.setAlpha(startValue);
159 | break;
160 | case SCALEY:
161 | view.setScaleY(startValue);
162 | break;
163 | case SCALEX:
164 | view.setScaleX(startValue);
165 | break;
166 | case SCALEXY:
167 | view.setScaleY(startValue);
168 | view.setScaleX(startValue);
169 | break;
170 | case ROTATEY:
171 | view.setRotationY(startValue);
172 | break;
173 | case ROTATEX:
174 | view.setRotationX(startValue);
175 | break;
176 | case ROTATION:
177 | view.setRotation(startValue);
178 | break;
179 | }
180 | }
181 |
182 | /*
183 | * Springy Listener to track the Spring
184 | * */
185 | public void setSpringyListener(SpringyListener springyListener) {
186 | this.springAnimatorListener = springyListener;
187 | }
188 |
189 |
190 | }
191 |
--------------------------------------------------------------------------------
/springylib/src/main/java/com/zach/salman/springylib/SpringyListener.java:
--------------------------------------------------------------------------------
1 | package com.zach.salman.springylib;
2 |
3 | /**
4 | * Created by Salman_Zach on 11/25/2016.
5 | */
6 |
7 | public interface SpringyListener {
8 |
9 | /*
10 | * hits when Spring is Active
11 | * */
12 | void onSpringStart();
13 |
14 | /*
15 | * hits when Spring is inActive
16 | * */
17 |
18 | void onSpringStop();
19 | }
20 |
--------------------------------------------------------------------------------
/springylib/src/main/java/com/zach/salman/springylib/springyRecyclerView/SpringyAdapterAnimationType.java:
--------------------------------------------------------------------------------
1 | package com.zach.salman.springylib.springyRecyclerView;
2 |
3 | /**
4 | * Created by Zach on 7/1/2017.
5 | */
6 |
7 | public enum SpringyAdapterAnimationType {
8 | SLIDE_FROM_TOP,
9 | SLIDE_FROM_BOTTOM,
10 | SLIDE_FROM_RIGHT,
11 | SLIDE_FROM_LEFT,
12 | SPREAD,
13 | SCALE,
14 | NULL,
15 | DIVE
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/springylib/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SpringyLib
3 |
4 |
--------------------------------------------------------------------------------
/springylib/src/test/java/com/zach/salman/springylib/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.zach.salman.springylib;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/supportrenderscriptblur/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/supportrenderscriptblur/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | ext {
4 | PUBLISH_GROUP_ID = 'com.eightbitlab'
5 | PUBLISH_ARTIFACT_ID = 'supportrenderscriptblur'
6 | PUBLISH_VERSION = '1.0.0'
7 | }
8 |
9 | android {
10 | compileSdkVersion 25
11 | buildToolsVersion '27.0.3'
12 |
13 | defaultConfig {
14 | renderscriptTargetApi 25
15 | renderscriptSupportModeEnabled true
16 | minSdkVersion 14
17 | targetSdkVersion 25
18 | versionCode 1
19 | versionName "1.0"
20 |
21 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
22 | }
23 |
24 | buildTypes {
25 | release {
26 | minifyEnabled false
27 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
28 | }
29 | }
30 | }
31 |
32 | dependencies {
33 | implementation fileTree(dir: 'libs', include: ['*.jar'])
34 | implementation 'com.android.support:appcompat-v7:25.2.0'
35 | compileOnly 'com.eightbitlab:blurview:1.3.2'
36 | }
37 |
38 | apply plugin: 'maven'
39 |
40 | def groupId = project.PUBLISH_GROUP_ID
41 | def artifactId = project.PUBLISH_ARTIFACT_ID
42 | def version = project.PUBLISH_VERSION
43 |
44 | def localReleaseDest = "${buildDir}/release/${version}"
45 |
46 | task androidJavadocs(type: Javadoc) {
47 | failOnError = false
48 | source = android.sourceSets.main.java.srcDirs
49 | ext.androidJar = "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
50 | classpath += files(ext.androidJar)
51 | }
52 |
53 | task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
54 | classifier = 'javadoc'
55 | from androidJavadocs.destinationDir
56 | }
57 |
58 | task androidSourcesJar(type: Jar) {
59 | classifier = 'sources'
60 | from android.sourceSets.main.java.srcDirs
61 | }
62 |
63 | uploadArchives {
64 | repositories.mavenDeployer {
65 | pom.groupId = groupId
66 | pom.artifactId = artifactId
67 | pom.version = version
68 | // Add other pom properties here if you want (developer details / licenses)
69 | repository(url: "file://${localReleaseDest}")
70 | }
71 | }
72 |
73 | task zipRelease(type: Zip) {
74 | from localReleaseDest
75 | destinationDir buildDir
76 | archiveName "release-${version}.zip"
77 | }
78 |
79 | task generateRelease << {
80 | println "Release ${version} can be found at ${localReleaseDest}/"
81 | println "Release ${version} zipped can be found ${buildDir}/release-${version}.zip"
82 | }
83 |
84 | generateRelease.dependsOn(uploadArchives)
85 | generateRelease.dependsOn(zipRelease)
86 |
87 | artifacts {
88 | archives androidSourcesJar
89 | archives androidJavadocsJar
90 | }
--------------------------------------------------------------------------------
/supportrenderscriptblur/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/supportrenderscriptblur/src/main/java/com/eightbitlab/supportrenderscriptblur/SupportRenderScriptBlur.java:
--------------------------------------------------------------------------------
1 | package com.eightbitlab.supportrenderscriptblur;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.support.annotation.NonNull;
6 | import android.support.v8.renderscript.Allocation;
7 | import android.support.v8.renderscript.Element;
8 | import android.support.v8.renderscript.RenderScript;
9 | import android.support.v8.renderscript.ScriptIntrinsicBlur;
10 |
11 | import eightbitlab.com.blurview.BlurAlgorithm;
12 |
13 | /**
14 | * Blur using RenderScript, processed on GPU.
15 | * Uses Renderscript from support library
16 | */
17 | public final class SupportRenderScriptBlur implements BlurAlgorithm {
18 | private final RenderScript renderScript;
19 | private final ScriptIntrinsicBlur blurScript;
20 | private Allocation outAllocation;
21 |
22 | private int lastBitmapWidth = -1;
23 | private int lastBitmapHeight = -1;
24 |
25 | /**
26 | * @param context Context to create the {@link RenderScript}
27 | */
28 | public SupportRenderScriptBlur(Context context) {
29 | renderScript = RenderScript.create(context);
30 | blurScript = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript));
31 | }
32 |
33 | private boolean canReuseAllocation(Bitmap bitmap) {
34 | return bitmap.getHeight() == lastBitmapHeight && bitmap.getWidth() == lastBitmapWidth;
35 | }
36 |
37 | /**
38 | * @param bitmap bitmap to blur
39 | * @param blurRadius blur radius (1..25)
40 | * @return blurred bitmap
41 | */
42 | @Override
43 | public final Bitmap blur(Bitmap bitmap, float blurRadius) {
44 | //Allocation will use the same backing array of pixels as bitmap if created with USAGE_SHARED flag
45 | Allocation inAllocation = Allocation.createFromBitmap(renderScript, bitmap);
46 |
47 | if (!canReuseAllocation(bitmap)) {
48 | if (outAllocation != null) {
49 | outAllocation.destroy();
50 | }
51 | outAllocation = Allocation.createTyped(renderScript, inAllocation.getType());
52 | lastBitmapWidth = bitmap.getWidth();
53 | lastBitmapHeight = bitmap.getHeight();
54 | }
55 |
56 | blurScript.setRadius(blurRadius);
57 | blurScript.setInput(inAllocation);
58 | //do not use inAllocation in forEach. it will cause visual artifacts on blurred Bitmap
59 | blurScript.forEach(outAllocation);
60 | outAllocation.copyTo(bitmap);
61 |
62 | inAllocation.destroy();
63 | return bitmap;
64 | }
65 |
66 | @Override
67 | public final void destroy() {
68 | blurScript.destroy();
69 | renderScript.destroy();
70 | if (outAllocation != null) {
71 | outAllocation.destroy();
72 | }
73 | }
74 |
75 | @Override
76 | public boolean canModifyBitmap() {
77 | return true;
78 | }
79 |
80 | @NonNull
81 | @Override
82 | public Bitmap.Config getSupportedBitmapConfig() {
83 | return Bitmap.Config.ARGB_8888;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------