diff --git a/.project b/.project
deleted file mode 100644
index f77326c..0000000
--- a/.project
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
- android-auto-scroll-view-pager
-
-
-
-
-
- com.android.ide.eclipse.adt.ResourceManagerBuilder
-
-
-
-
- com.android.ide.eclipse.adt.PreCompilerBuilder
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- com.android.ide.eclipse.adt.ApkBuilder
-
-
-
-
-
- com.android.ide.eclipse.adt.AndroidNature
- org.eclipse.jdt.core.javanature
-
-
diff --git a/README.md b/README.md
index 12bff9f..19d1fc7 100644
--- a/README.md
+++ b/README.md
@@ -41,8 +41,10 @@ replace
- `setSlideBorderMode(int)` set how to process when sliding at the last or first item, default is `SLIDE_BORDER_MODE_NONE`.
- `setStopScrollWhenTouch(boolean)` set whether stop auto scroll when touching, default is true.
- `setBorderAnimation(boolean)` set whether animating when auto scroll at the last or first item, default is true.
-- You cannot combine with [ViewPagerIndicator](https://github.com/JakeWharton/Android-ViewPagerIndicator) if `setCycle(true)`.
-- If you want infinite loop, please see [AutoScrollViewPagerSingleDemo.java](https://github.com/Trinea/android-demo/blob/master/src/cn/trinea/android/demo/AutoScrollViewPagerDemo.java)
+- ~~You cannot combine with [ViewPagerIndicator](https://github.com/JakeWharton/Android-ViewPagerIndicator) if `setCycle(true)`.~~
+- Now,you can combine with [ViewPagerIndicator](https://github.com/JakeWharton/Android-ViewPagerIndicator) without any other operation.
+- ~~If you want infinite loop, please see [AutoScrollViewPagerSingleDemo.java](https://github.com/Trinea/android-demo/blob/master/src/cn/trinea/android/demo/AutoScrollViewPagerDemo.java)~~
+- Support infinite loop by default.
**More:** http://www.trinea.cn/android/auto-scroll-view-pager/
## Proguard
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..b8c8567
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,22 @@
+buildscript {
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.0.0'
+ }
+}
+
+def isReleaseBuild() {
+ return version.contains("SNAPSHOT") == false
+}
+
+allprojects {
+
+ repositories {
+ mavenCentral()
+ }
+}
+
+
diff --git a/demo/.gitignore b/demo/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/demo/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/demo/build.gradle b/demo/build.gradle
new file mode 100644
index 0000000..7fdad1b
--- /dev/null
+++ b/demo/build.gradle
@@ -0,0 +1,27 @@
+apply plugin: 'com.android.application'
+android {
+ compileSdkVersion 19
+ buildToolsVersion "20.0.0"
+
+ defaultConfig {
+ minSdkVersion 9
+ targetSdkVersion 19
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile 'com.android.support:appcompat-v7:19.1.0'
+ compile project(':library')
+}
+
+repositories {
+ mavenCentral()
+}
\ No newline at end of file
diff --git a/demo/demo.iml b/demo/demo.iml
new file mode 100644
index 0000000..1eaf5ec
--- /dev/null
+++ b/demo/demo.iml
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo/proguard-rules.pro b/demo/proguard-rules.pro
new file mode 100644
index 0000000..c1c73e5
--- /dev/null
+++ b/demo/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/panwenye/android_sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/demo/src/androidTest/java/com/android/demo/ApplicationTest.java b/demo/src/androidTest/java/com/android/demo/ApplicationTest.java
new file mode 100644
index 0000000..6fe5699
--- /dev/null
+++ b/demo/src/androidTest/java/com/android/demo/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.android.demo;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/demo/src/main/AndroidManifest.xml b/demo/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..6dc7026
--- /dev/null
+++ b/demo/src/main/AndroidManifest.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo/src/main/java/com/android/demo/MainActivity.java b/demo/src/main/java/com/android/demo/MainActivity.java
new file mode 100644
index 0000000..ad0221d
--- /dev/null
+++ b/demo/src/main/java/com/android/demo/MainActivity.java
@@ -0,0 +1,144 @@
+package com.android.demo;
+
+import android.support.v4.view.PagerAdapter;
+import android.support.v7.app.ActionBarActivity;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import cn.trinea.android.view.autoscrollviewpager.AutoScrollViewPager;
+
+
+public class MainActivity extends ActionBarActivity {
+ AutoScrollViewPager mViewPager;
+ BaseViewPagerAdapter mViewPagerAdapter;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ mViewPager = (AutoScrollViewPager) findViewById(R.id.home_banner_viewpager);
+ initViewPager();
+ }
+
+ private void initViewPager() {
+ mViewPagerAdapter = new BaseViewPagerAdapter();
+ //显示默认占位图片
+ mViewPagerAdapter.add(makeView(R.drawable.ic_launcher));
+ mViewPagerAdapter.add(makeView(R.drawable.ic_launcher));
+ mViewPagerAdapter.add(makeView(R.drawable.ic_launcher));
+ mViewPagerAdapter.add(makeView(R.drawable.ic_launcher));
+ mViewPagerAdapter.add(makeView(R.drawable.ic_launcher));
+
+ mViewPager.setAdapter(mViewPagerAdapter);
+ mViewPager.setInterval(1000);
+// mViewPager.setLoopScroll(false);
+ mViewPager.startAutoScroll();
+ }
+ public View makeView(int rid) {
+ ImageView imageView = new ImageView(this);
+ imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
+ imageView.setImageResource(rid);
+ imageView.setId(new Random().nextInt(Integer.MAX_VALUE));
+ return imageView;
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.menu_main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+
+ //noinspection SimplifiableIfStatement
+ if (id == R.id.action_settings) {
+ initViewPager();
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+ public class BaseViewPagerAdapter extends PagerAdapter {
+ ArrayList views = new ArrayList();
+
+ public BaseViewPagerAdapter() {
+
+ }
+
+ public void add(View view) {
+ views.add(view);
+ }
+
+ public View getItem(int position) {
+ if (position < views.size() && position >= 0) {
+ return views.get(position);
+ }
+ return null;
+ }
+
+ public void clear() {
+ views.clear();
+ notifyDataSetChanged();
+ }
+
+
+ @Override
+ public int getCount() {
+ return views.size();
+ }
+
+ @Override
+ public Object instantiateItem(ViewGroup container, int position) {
+ if (position >= 0 && position < views.size()) {
+ View view = views.get(position);
+
+ if (view != null) {
+ if(view.getId()>0){
+ if(container.findViewById(view.getId())==null){
+ container.addView(view);
+ }
+ }else {
+ boolean hasContained = false;
+ for (int i = 0; i < container.getChildCount(); i++) {
+ if(container.getChildAt(i)==view){
+ hasContained = true;
+ break;
+ }
+ }
+ if(!hasContained){
+ container.addView(view);
+ }
+ }
+ return view;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void destroyItem(ViewGroup container, int position, Object object) {
+ if (position >= 0 && position < views.size()) {
+ View view = views.get(position);
+ container.removeView(view);
+ }
+ }
+
+ @Override
+ public boolean isViewFromObject(View view, Object object) {
+ return view == object;
+ }
+ }
+
+}
diff --git a/demo/src/main/res/drawable-hdpi/ic_launcher.png b/demo/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
Binary files /dev/null and b/demo/src/main/res/drawable-hdpi/ic_launcher.png differ
diff --git a/demo/src/main/res/drawable-mdpi/ic_launcher.png b/demo/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
Binary files /dev/null and b/demo/src/main/res/drawable-mdpi/ic_launcher.png differ
diff --git a/demo/src/main/res/drawable-xhdpi/ic_launcher.png b/demo/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
Binary files /dev/null and b/demo/src/main/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/demo/src/main/res/drawable-xxhdpi/ic_launcher.png b/demo/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4df1894
Binary files /dev/null and b/demo/src/main/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/demo/src/main/res/layout/activity_main.xml b/demo/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..e48de76
--- /dev/null
+++ b/demo/src/main/res/layout/activity_main.xml
@@ -0,0 +1,22 @@
+
+ tools:context=".MainActivity" >
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demo/src/main/res/menu/menu_main.xml b/demo/src/main/res/menu/menu_main.xml
new file mode 100644
index 0000000..b1cb908
--- /dev/null
+++ b/demo/src/main/res/menu/menu_main.xml
@@ -0,0 +1,6 @@
+
diff --git a/demo/src/main/res/values-w820dp/dimens.xml b/demo/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..63fc816
--- /dev/null
+++ b/demo/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/demo/src/main/res/values/dimens.xml b/demo/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..47c8224
--- /dev/null
+++ b/demo/src/main/res/values/dimens.xml
@@ -0,0 +1,5 @@
+
+
+ 16dp
+ 16dp
+
diff --git a/demo/src/main/res/values/strings.xml b/demo/src/main/res/values/strings.xml
new file mode 100644
index 0000000..174b0ed
--- /dev/null
+++ b/demo/src/main/res/values/strings.xml
@@ -0,0 +1,8 @@
+
+
+
+ demo
+ Hello world!
+ Settings
+
+
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/AndroidManifest.xml b/library/AndroidManifest.xml
similarity index 100%
rename from AndroidManifest.xml
rename to library/AndroidManifest.xml
diff --git a/library/build.gradle b/library/build.gradle
new file mode 100644
index 0000000..8d820be
--- /dev/null
+++ b/library/build.gradle
@@ -0,0 +1,22 @@
+apply plugin: 'com.android.library'
+
+repositories {
+ mavenCentral()
+}
+android {
+ compileSdkVersion 19
+ buildToolsVersion '20.0.0'
+
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src']
+ res.srcDirs = ['res']
+ }
+ }
+}
+
+
+dependencies {
+ compile 'com.android.support:support-v4:19.1.0'
+}
diff --git a/library/library.iml b/library/library.iml
new file mode 100644
index 0000000..63813d3
--- /dev/null
+++ b/library/library.iml
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/src/android/support/v4/view/InfiniteLoopPagerAdapter.java b/library/src/android/support/v4/view/InfiniteLoopPagerAdapter.java
new file mode 100644
index 0000000..a7eaf0d
--- /dev/null
+++ b/library/src/android/support/v4/view/InfiniteLoopPagerAdapter.java
@@ -0,0 +1,97 @@
+package android.support.v4.view;
+
+import android.os.Parcelable;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Created by lsjwzh on 13-8-12.
+ */
+public class InfiniteLoopPagerAdapter extends PagerAdapter {
+ private static final String TAG = "InfiniteLoopPagerAdapter";
+ private static final boolean DEBUG = false;
+
+ private PagerAdapter mAdapter;
+
+ public InfiniteLoopPagerAdapter(PagerAdapter mAdapter) {
+ this.mAdapter = mAdapter;
+ }
+
+ @Override
+ public int getCount() {
+ // warning: scrolling to very high values (1,000,000+) results in
+ // strange drawing behaviour
+ return Integer.MAX_VALUE;
+ }
+
+ /**
+ * @return the {@link #getCount()} result of the wrapped mAdapter
+ */
+ public int getRealCount() {
+ return mAdapter.getCount();
+ }
+
+ public PagerAdapter getOriginalPageAdapter(){
+ return mAdapter;
+ }
+
+ @Override
+ public Object instantiateItem(ViewGroup container, int position) {
+ int virtualPosition = position % getRealCount();
+ debug("instantiateItem: real position: " + position);
+ debug("instantiateItem: virtual position: " + virtualPosition);
+
+ // only expose virtual position to the inner mAdapter
+ return mAdapter.instantiateItem(container, virtualPosition);
+ }
+
+ @Override
+ public void destroyItem(ViewGroup container, int position, Object object) {
+ int virtualPosition = position % getRealCount();
+ debug("destroyItem: real position: " + position);
+ debug("destroyItem: virtual position: " + virtualPosition);
+
+ // only expose virtual position to the inner mAdapter
+ mAdapter.destroyItem(container, virtualPosition, object);
+ }
+
+ /*
+ * Delegate rest of methods directly to the inner mAdapter.
+ */
+
+ @Override
+ public void finishUpdate(ViewGroup container) {
+ mAdapter.finishUpdate(container);
+ }
+
+ @Override
+ public boolean isViewFromObject(View view, Object object) {
+ return mAdapter.isViewFromObject(view, object);
+ }
+
+ @Override
+ public void restoreState(Parcelable bundle, ClassLoader classLoader) {
+ mAdapter.restoreState(bundle, classLoader);
+ }
+
+ @Override
+ public Parcelable saveState() {
+ return mAdapter.saveState();
+ }
+
+ @Override
+ public void startUpdate(ViewGroup container) {
+ mAdapter.startUpdate(container);
+ }
+
+ /*
+ * End delegation
+ */
+
+ private void debug(String message) {
+ if (DEBUG) {
+ Log.d(TAG, message);
+ }
+ }
+}
diff --git a/library/src/android/support/v4/view/LoopCompatibleViewPager.java b/library/src/android/support/v4/view/LoopCompatibleViewPager.java
new file mode 100644
index 0000000..d77631f
--- /dev/null
+++ b/library/src/android/support/v4/view/LoopCompatibleViewPager.java
@@ -0,0 +1,645 @@
+/*
+* Copyright (C) 2011 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package android.support.v4.view;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.view.View;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * override ViewPager's 'populate' medthod to prevent main thread from blocking
+ * Created by lsjwzh on 14-12-25.
+ */
+public class LoopCompatibleViewPager extends ViewPager {
+ private static final int DRAW_ORDER_DEFAULT = 0;
+ private static final ViewPositionComparator sPositionComparator = new ViewPositionComparator();
+ InfiniteLoopPagerAdapter mWrapperAdapter;
+ PagerAdapter mActualAdapter;
+ OnPageChangeListenerWrapper mWrapperOnPageChangeListener;
+ OnPageChangeListener mActualOnPageChangeListener;
+ boolean mIsLoopScroll = true;
+ Field mItems_Field;
+ private Field mCurItem_Field;
+ private Field mPopulatePending_Field;
+ private Field mExpectedAdapterCount_Field;
+ private Field mDrawingOrder_Field;
+ private Field mDrawingOrderedChildren_Field;
+ private Field mPageMargin_Field;
+ private Field mFirstOffset_Field;
+ private Field mLastOffset_Field;
+ private Field mNeedCalculatePageOffsets_Field;
+
+
+ public LoopCompatibleViewPager(Context context) {
+ super(context);
+ initFields();
+ }
+
+ public LoopCompatibleViewPager(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initFields();
+ }
+
+ void initFields() {
+ try {
+ mCurItem_Field = ViewPager.class.getDeclaredField("mCurItem");
+ if (mCurItem_Field != null) {
+ mCurItem_Field.setAccessible(true);
+ }
+ mPopulatePending_Field = ViewPager.class.getDeclaredField("mPopulatePending");
+ if (mPopulatePending_Field != null) {
+ mPopulatePending_Field.setAccessible(true);
+ }
+ mExpectedAdapterCount_Field = ViewPager.class.getDeclaredField("mExpectedAdapterCount");
+ if (mExpectedAdapterCount_Field != null) {
+ mExpectedAdapterCount_Field.setAccessible(true);
+ }
+ mItems_Field = ViewPager.class.getDeclaredField("mItems");
+ if (mItems_Field != null) {
+ mItems_Field.setAccessible(true);
+ }
+ mDrawingOrder_Field = ViewPager.class.getDeclaredField("mDrawingOrder");
+ if (mDrawingOrder_Field != null) {
+ mDrawingOrder_Field.setAccessible(true);
+ }
+ mDrawingOrderedChildren_Field = ViewPager.class.getDeclaredField("mDrawingOrderedChildren");
+ if (mDrawingOrderedChildren_Field != null) {
+ mDrawingOrderedChildren_Field.setAccessible(true);
+ }
+ mPageMargin_Field = ViewPager.class.getDeclaredField("mPageMargin");
+ if (mPageMargin_Field != null) {
+ mPageMargin_Field.setAccessible(true);
+ }
+ mFirstOffset_Field = ViewPager.class.getDeclaredField("mFirstOffset");
+ if (mFirstOffset_Field != null) {
+ mFirstOffset_Field.setAccessible(true);
+ }
+ mLastOffset_Field = ViewPager.class.getDeclaredField("mLastOffset");
+
+ if (mLastOffset_Field != null) {
+ mLastOffset_Field.setAccessible(true);
+ }
+ mNeedCalculatePageOffsets_Field = ViewPager.class.getDeclaredField("mNeedCalculatePageOffsets");
+ if (mNeedCalculatePageOffsets_Field != null) {
+ mNeedCalculatePageOffsets_Field.setAccessible(true);
+ }
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Retrieve the current adapter supplying pages.
+ *
+ * @return The currently registered PagerAdapter
+ */
+ public PagerAdapter getAdapter() {
+ return mActualAdapter;
+ }
+
+ protected InfiniteLoopPagerAdapter getWrapperAdapter(){
+ return mWrapperAdapter;
+ }
+
+ /**
+ * Set a PagerAdapter that will supply views for this pager as needed.
+ *
+ * @param adapter Adapter to use
+ */
+ public void setAdapter(PagerAdapter adapter) {
+ if(isLoopScroll()) {
+ mActualAdapter = adapter;
+ mWrapperAdapter = new InfiniteLoopPagerAdapter(adapter);
+ super.setAdapter(mWrapperAdapter);
+ getInnerItems().clear();
+ setInnerCurrentItem(mWrapperAdapter.getCount() / 2 - (mWrapperAdapter.getCount() / 2) % mWrapperAdapter.getRealCount() );
+ setCurrentItem(0);
+ }else {
+ mActualAdapter = adapter;
+ mWrapperAdapter = null;
+ super.setAdapter(mActualAdapter);
+ }
+ }
+
+ @Override
+ public void setOnPageChangeListener(OnPageChangeListener listener) {
+ mActualOnPageChangeListener = listener;
+ mWrapperOnPageChangeListener = new OnPageChangeListenerWrapper();
+ super.setOnPageChangeListener(mWrapperOnPageChangeListener);
+ }
+
+
+
+ /**
+ * Set the currently selected page. If the ViewPager has already been through its first
+ * layout with its current adapter there will be a smooth animated transition between
+ * the current item and the specified item.
+ *
+ * @param item Item index to select
+ */
+ public void setCurrentItem(int item) {
+ if(getWrapperAdapter()!=null) {
+ if (item < getWrapperAdapter().getRealCount()) {
+ item = getWrapperAdapter().getCount() / 2 - (getWrapperAdapter().getCount() / 2) % getWrapperAdapter().getRealCount() + item;
+ }
+ }
+ super.setCurrentItem(item);
+ }
+
+ /**
+ * Set the currently selected page.
+ *
+ * @param item Item index to select
+ * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately
+ */
+ public void setCurrentItem(int item, boolean smoothScroll) {
+ if(getWrapperAdapter()!=null) {
+ if (item < getWrapperAdapter().getRealCount()) {
+ item = getWrapperAdapter().getCount() / 2 - (getWrapperAdapter().getCount() / 2) % getWrapperAdapter().getRealCount() + item;
+ }
+ }
+ super.setCurrentItem(item, smoothScroll);
+ }
+
+ @Override
+ public int getCurrentItem() {
+ if(getWrapperAdapter()!=null) {
+ return super.getCurrentItem() % getWrapperAdapter().getRealCount();
+ }else {
+ return super.getCurrentItem();
+ }
+ }
+
+ public void setLoopScroll(boolean loopScroll){
+ if(mIsLoopScroll==loopScroll){
+ return;
+ }
+ mIsLoopScroll = loopScroll;
+ if(getWrapperAdapter()!=null) {
+ setAdapter(getWrapperAdapter().getOriginalPageAdapter());
+ }
+ }
+
+ public boolean isLoopScroll(){
+ return mIsLoopScroll;
+ }
+
+ @Override
+ void populate(int newCurrentItem) {
+ if(getWrapperAdapter()==null){
+ super.populate(newCurrentItem);
+ return;
+ }
+ ItemInfo oldCurInfo = null;
+ int focusDirection = View.FOCUS_FORWARD;
+ if (getInnerCurrentItem() != newCurrentItem) {
+ focusDirection = getInnerCurrentItem() < newCurrentItem ? View.FOCUS_RIGHT : View.FOCUS_LEFT;
+ oldCurInfo = infoForPosition(getInnerCurrentItem());
+ setInnerCurrentItem(newCurrentItem);
+ }
+
+ if (getWrapperAdapter() == null) {
+ sortChildDrawingOrder();
+ return;
+ }
+
+ // Bail now if we are waiting to populate. This is to hold off
+ // on creating views from the time the user releases their finger to
+ // fling to a new position until we have finished the scroll to
+ // that position, avoiding glitches from happening at that point.
+ if (getInnerPopulatePending()) {
+ sortChildDrawingOrder();
+ return;
+ }
+
+ // Also, don't populate until we are attached to a window. This is to
+ // avoid trying to populate before we have restored our view hierarchy
+ // state and conflicting with what is restored.
+ if (getWindowToken() == null) {
+ return;
+ }
+
+ getWrapperAdapter().startUpdate(this);
+
+ final int pageLimit = getOffscreenPageLimit();
+ final int startPos = Math.max(0, getInnerCurrentItem() - pageLimit);
+ final int N = getWrapperAdapter().getCount();
+ final int endPos = Math.min(N - 1, getInnerCurrentItem() + pageLimit);
+
+ if (N != getInnerExpectedAdapterCount()) {
+ String resName;
+ try {
+ resName = getResources().getResourceName(getId());
+ } catch (Resources.NotFoundException e) {
+ resName = Integer.toHexString(getId());
+ }
+ throw new IllegalStateException("The application's PagerAdapter changed the adapter's" +
+ " contents without calling PagerAdapter#notifyDataSetChanged!" +
+ " Expected adapter item count: " + getInnerExpectedAdapterCount() + ", found: " + N +
+ " Pager id: " + resName +
+ " Pager class: " + getClass() +
+ " Problematic adapter: " + getWrapperAdapter().getClass());
+ }
+
+ // Locate the currently focused item or add it if needed.
+ int curIndex = -1;
+ ItemInfo curItem = null;
+ for (curIndex = 0; curIndex < getInnerItems().size(); curIndex++) {
+ final ItemInfo ii = getInnerItems().get(curIndex);
+ if (ii.position >= getInnerCurrentItem()) {
+ if (ii.position == getInnerCurrentItem()) curItem = ii;
+ break;
+ }
+ }
+
+ if (curItem == null && N > 0) {
+ curItem = addNewItem(getInnerCurrentItem(), curIndex);
+ }
+
+ // Fill 3x the available width or up to the number of offscreen
+ // pages requested to either side, whichever is larger.
+ // If we have no current item we have no work to do.
+ if (curItem != null) {
+ float extraWidthLeft = 0.f;
+ int itemIndex = curIndex - 1;
+ ItemInfo ii = itemIndex >= 0 ? getInnerItems().get(itemIndex) : null;
+ final int clientWidth = getClientWidth();
+ final float leftWidthNeeded = clientWidth <= 0 ? 0 :
+ 2.f - curItem.widthFactor + (float) getPaddingLeft() / (float) clientWidth;
+ int checkStart = Math.max(0,getInnerCurrentItem()-getWrapperAdapter().getRealCount());//reduce execute times,when loop viewpager is available
+ for (int pos = getInnerCurrentItem() - 1; pos >= checkStart; pos--) {
+ if (extraWidthLeft >= leftWidthNeeded && pos < startPos) {
+ if (ii == null) {
+ break;
+ }
+ if (pos == ii.position && !ii.scrolling) {
+ getInnerItems().remove(itemIndex);
+ getWrapperAdapter().destroyItem(this, pos, ii.object);
+
+ itemIndex--;
+ curIndex--;
+ ii = itemIndex >= 0 ? getInnerItems().get(itemIndex) : null;
+ }
+ } else if (ii != null && pos == ii.position) {
+ extraWidthLeft += ii.widthFactor;
+ itemIndex--;
+ ii = itemIndex >= 0 ? getInnerItems().get(itemIndex) : null;
+ } else {
+ ii = addNewItem(pos, itemIndex + 1);
+ extraWidthLeft += ii.widthFactor;
+ curIndex++;
+ ii = itemIndex >= 0 ? getInnerItems().get(itemIndex) : null;
+ }
+ }
+
+ float extraWidthRight = curItem.widthFactor;
+ itemIndex = curIndex + 1;
+ if (extraWidthRight < 2.f) {
+ ii = itemIndex < getInnerItems().size() ? getInnerItems().get(itemIndex) : null;
+ final float rightWidthNeeded = clientWidth <= 0 ? 0 :
+ (float) getPaddingRight() / (float) clientWidth + 2.f;
+ int checkEnd = Math.min(N,getInnerCurrentItem()+getWrapperAdapter().getRealCount());//reduce execute times,when loop viewpager is available
+ for (int pos = getInnerCurrentItem() + 1; pos < checkEnd; pos++) {
+ if (extraWidthRight >= rightWidthNeeded && pos > endPos) {
+ if (ii == null) {
+ break;
+ }
+ if (pos == ii.position && !ii.scrolling) {
+ getInnerItems().remove(itemIndex);
+ getWrapperAdapter().destroyItem(this, pos, ii.object);
+ ii = itemIndex < getInnerItems().size() ? getInnerItems().get(itemIndex) : null;
+ }
+ } else if (ii != null && pos == ii.position) {
+ extraWidthRight += ii.widthFactor;
+ itemIndex++;
+ ii = itemIndex < getInnerItems().size() ? getInnerItems().get(itemIndex) : null;
+ } else {
+ ii = addNewItem(pos, itemIndex);
+ itemIndex++;
+ extraWidthRight += ii.widthFactor;
+ ii = itemIndex < getInnerItems().size() ? getInnerItems().get(itemIndex) : null;
+ }
+ }
+ }
+
+ calculatePageOffsets(curItem, curIndex, oldCurInfo);
+ }
+
+
+ getWrapperAdapter().setPrimaryItem(this, getInnerCurrentItem(), curItem != null ? curItem.object : null);
+
+ getWrapperAdapter().finishUpdate(this);
+
+ // Check width measurement of current pages and drawing sort order.
+ // Update LayoutParams as needed.
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ lp.childIndex = i;
+ if (!lp.isDecor && lp.widthFactor == 0.f) {
+ // 0 means requery the adapter for this, it doesn't have a valid width.
+ final ItemInfo ii = infoForChild(child);
+ if (ii != null) {
+ lp.widthFactor = ii.widthFactor;
+ lp.position = ii.position;
+ }
+ }
+ }
+ sortChildDrawingOrder();
+
+ if (hasFocus()) {
+ View currentFocused = findFocus();
+ ItemInfo ii = currentFocused != null ? infoForAnyChild(currentFocused) : null;
+ if (ii == null || ii.position != getInnerCurrentItem()) {
+ for (int i=0; i 0 ? (float) getInnerPageMargin() / width : 0;
+ // Fix up offsets for later layout.
+ if (oldCurInfo != null) {
+ final int oldCurPosition = oldCurInfo.position;
+ // Base offsets off of oldCurInfo.
+ if (oldCurPosition < curItem.position) {
+ int itemIndex = 0;
+ ItemInfo ii = null;
+ float offset = oldCurInfo.offset + oldCurInfo.widthFactor + marginOffset;
+ for (int pos = oldCurPosition + 1;
+ pos <= curItem.position && itemIndex < getInnerItems().size(); pos++) {
+ ii = getInnerItems().get(itemIndex);
+ while (pos > ii.position && itemIndex < getInnerItems().size() - 1) {
+ itemIndex++;
+ ii = getInnerItems().get(itemIndex);
+ }
+ while (pos < ii.position) {
+ // We don't have an item populated for this,
+ // ask the adapter for an offset.
+ offset += getWrapperAdapter().getPageWidth(pos) + marginOffset;
+ pos++;
+ }
+ ii.offset = offset;
+ offset += ii.widthFactor + marginOffset;
+ }
+ } else if (oldCurPosition > curItem.position) {
+ int itemIndex = getInnerItems().size() - 1;
+ ItemInfo ii = null;
+ float offset = oldCurInfo.offset;
+ for (int pos = oldCurPosition - 1;
+ pos >= curItem.position && itemIndex >= 0; pos--) {
+ ii = getInnerItems().get(itemIndex);
+ while (pos < ii.position && itemIndex > 0) {
+ itemIndex--;
+ ii = getInnerItems().get(itemIndex);
+ }
+ while (pos > ii.position) {
+ // We don't have an item populated for this,
+ // ask the adapter for an offset.
+ offset -= getWrapperAdapter().getPageWidth(pos) + marginOffset;
+ pos--;
+ }
+ offset -= ii.widthFactor + marginOffset;
+ ii.offset = offset;
+ }
+ }
+ }
+
+ // Base all offsets off of curItem.
+ final int itemCount = getInnerItems().size();
+ float offset = curItem.offset;
+ int pos = curItem.position - 1;
+ try {
+ mFirstOffset_Field.set(this, curItem.position == 0 ? curItem.offset : -Float.MAX_VALUE);
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ try {
+ mLastOffset_Field.set(this, curItem.position == N - 1 ?
+ curItem.offset + curItem.widthFactor - 1 : Float.MAX_VALUE);
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ // Previous pages
+ for (int i = curIndex - 1; i >= 0; i--, pos--) {
+ final ItemInfo ii = getInnerItems().get(i);
+ while (pos > ii.position) {
+ offset -= getWrapperAdapter().getPageWidth(pos--) + marginOffset;
+ }
+ offset -= ii.widthFactor + marginOffset;
+ ii.offset = offset;
+ if (ii.position == 0) {
+ try {
+ mFirstOffset_Field.set(this, offset);
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ offset = curItem.offset + curItem.widthFactor + marginOffset;
+ pos = curItem.position + 1;
+ // Next pages
+ for (int i = curIndex + 1; i < itemCount; i++, pos++) {
+ final ItemInfo ii = getInnerItems().get(i);
+ while (pos < ii.position) {
+ offset += getWrapperAdapter().getPageWidth(pos++) + marginOffset;
+ }
+ if (ii.position == N - 1) {
+ try {
+ mLastOffset_Field.set(this, offset + ii.widthFactor - 1);
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+ ii.offset = offset;
+ offset += ii.widthFactor + marginOffset;
+ }
+
+ try {
+ mNeedCalculatePageOffsets_Field.set(this, false);
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public int getInnerCurrentItem() {
+ return super.getCurrentItem();
+ }
+
+ private void setInnerCurrentItem(int newCurrentItem) {
+ try {
+ mCurItem_Field.set(this, newCurrentItem);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private int getInnerExpectedAdapterCount() {
+ try {
+ return mExpectedAdapterCount_Field.getInt(this);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return 0;
+ }
+ }
+
+ private boolean getInnerPopulatePending() {
+ try {
+ return mPopulatePending_Field.getBoolean(this);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+
+ private void setInnerDrawingOrderedChildren() {
+ try {
+ mDrawingOrderedChildren_Field.set(this, new ArrayList());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private ArrayList getInnerDrawingOrderedChildren() {
+ try {
+ return (ArrayList) mDrawingOrderedChildren_Field.get(this);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return new ArrayList();
+ }
+ }
+
+ private int getInnerDrawingOrder() {
+ try {
+ return mDrawingOrder_Field.getInt(this);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return 0;
+ }
+ }
+
+
+ private float getInnerLastOffset() {
+ try {
+ return mLastOffset_Field.getFloat(this);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return 0;
+ }
+ }
+
+ private float getInnerFirstOffset() {
+ try {
+ return mFirstOffset_Field.getFloat(this);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return 0;
+ }
+ }
+
+ private int getInnerPageMargin() {
+ try {
+ return mPageMargin_Field.getInt(this);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return 0;
+ }
+ }
+
+ private ArrayList getInnerItems() {
+ try {
+ return (ArrayList) mItems_Field.get(this);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return new ArrayList();
+ }
+ }
+
+
+ private int getClientWidth() {
+ return getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
+ }
+
+ private class OnPageChangeListenerWrapper implements OnPageChangeListener {
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ if(mActualOnPageChangeListener!=null) {
+ if (getWrapperAdapter() == null) {
+ mActualOnPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
+ } else {
+ mActualOnPageChangeListener.onPageScrolled(position % getWrapperAdapter().getRealCount(), positionOffset, positionOffsetPixels);
+ }
+ }
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ if(mActualOnPageChangeListener!=null) {
+ if (getWrapperAdapter() == null) {
+ mActualOnPageChangeListener.onPageSelected(position);
+ } else {
+ mActualOnPageChangeListener.onPageSelected(position % getWrapperAdapter().getRealCount());
+ }
+ }
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ if(mActualOnPageChangeListener!=null){
+ if (getWrapperAdapter() == null) {
+ mActualOnPageChangeListener.onPageScrollStateChanged(state);
+ } else {
+ mActualOnPageChangeListener.onPageScrollStateChanged(state);
+ }
+ }
+ }
+ }
+}
diff --git a/src/cn/trinea/android/view/autoscrollviewpager/AutoScrollViewPager.java b/library/src/cn/trinea/android/view/autoscrollviewpager/AutoScrollViewPager.java
similarity index 96%
rename from src/cn/trinea/android/view/autoscrollviewpager/AutoScrollViewPager.java
rename to library/src/cn/trinea/android/view/autoscrollviewpager/AutoScrollViewPager.java
index 0cff375..c131fbe 100644
--- a/src/cn/trinea/android/view/autoscrollviewpager/AutoScrollViewPager.java
+++ b/library/src/cn/trinea/android/view/autoscrollviewpager/AutoScrollViewPager.java
@@ -5,6 +5,7 @@
import android.content.Context;
import android.os.Handler;
import android.os.Message;
+import android.support.v4.view.LoopCompatibleViewPager;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
@@ -31,7 +32,7 @@
*
* @author Trinea 2013-12-30
*/
-public class AutoScrollViewPager extends ViewPager {
+public class AutoScrollViewPager extends LoopCompatibleViewPager {
public static final int DEFAULT_INTERVAL = 1500;
@@ -152,8 +153,8 @@ private void setViewPagerScroller() {
* scroll only once
*/
public void scrollOnce() {
- PagerAdapter adapter = getAdapter();
- int currentItem = getCurrentItem();
+ PagerAdapter adapter = getWrapperAdapter()==null?getAdapter():getWrapperAdapter();
+ int currentItem = getInnerCurrentItem();
int totalCount;
if (adapter == null || (totalCount = adapter.getCount()) <= 1) {
return;
@@ -198,8 +199,8 @@ public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
downX = touchX;
}
- int currentItem = getCurrentItem();
- PagerAdapter adapter = getAdapter();
+ int currentItem = getInnerCurrentItem();
+ PagerAdapter adapter = getWrapperAdapter()==null?getAdapter():getWrapperAdapter();
int pageCount = adapter == null ? 0 : adapter.getCount();
/**
* current index is first one and slide to right or current index is last one and slide to left.
diff --git a/src/cn/trinea/android/view/autoscrollviewpager/CustomDurationScroller.java b/library/src/cn/trinea/android/view/autoscrollviewpager/CustomDurationScroller.java
similarity index 100%
rename from src/cn/trinea/android/view/autoscrollviewpager/CustomDurationScroller.java
rename to library/src/cn/trinea/android/view/autoscrollviewpager/CustomDurationScroller.java
diff --git a/libs/android-support-v4.jar b/libs/android-support-v4.jar
deleted file mode 100644
index 65ebaf8..0000000
Binary files a/libs/android-support-v4.jar and /dev/null differ
diff --git a/pom.xml b/pom.xml
index 1306a3c..9151a1f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,12 +61,12 @@
com.google.android
support-v4
- r6
+ r19
- src
+ library/src
test
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..2150f22
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+include ':library', ':demo'