diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..34a6d05
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,62 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+/.idea
+
+# Built application files
+*.apk
+*.ap_
+
+# Files for the Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+
+# Gradle files
+.gradle/
+build/
+
+# Local configuration file (sdk path, etc)
+local.properties
+.classpath
+.project
+.settings/
+
+# Proguard folder generated by Eclipse
+proguard/
+
+#Log Files
+*.log
+
+# OS X
+.DS_Store
+
+*.class
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.war
+*.ear
+*.iml
+
+# IDEA Files
+.idea/
+.settings/
+out/
+
+# MAVEN COMPILE Files
+target/
+
+project.properties
\ No newline at end of file
diff --git a/ATTRIBUTES-ch.md b/ATTRIBUTES-ch.md
new file mode 100644
index 0000000..adb2c0e
--- /dev/null
+++ b/ATTRIBUTES-ch.md
@@ -0,0 +1,122 @@
+[Englis API](ATTRIBUTES.md)
+### initIndicator
+
+初始化indicator,支持链式调用set属性,focusColor, normalColor是必设属性,否则indicator不会显示。
+#### 接口
+```
+IUltraIndicatorBuilder initIndicator();
+```
+---
+### setFocusColor setNormalColor
+设置indicator 图标颜色。
+`focusColor` 被选中的indicator颜色
+`normalColor` 未被选中的indicator颜色
+#### 接口
+```
+IUltraIndicatorBuilder setFocusColor(int focusColor);
+IUltraIndicatorBuilder setNormalColor(int normalColor);
+```
+```
+ultraViewPager.getIndicator()
+ .setFocusColor(Color.GREEN)
+ .setNormalColor(Color.WHITE)
+ .setRadius((int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics()));
+```
+
+![color](pics/20151203-0.png)
+---
+### setFocusResId setNormalResId
+设置indicator 图片资源。
+`focusResId` 被选中的indicator icon Id
+`normalResId` 未被选中的indicator icon Id
+#### 接口
+```
+IUltraIndicatorBuilder setFocusResId(int focusResId);
+IUltraIndicatorBuilder setNormalResId(int normalResId);
+```
+```
+ultraViewPager.getIndicator()
+.setFocusResId(R.mipmap.tm_biz_lifemaster_indicator_selected)
+.setNormalResId(R.mipmap.tm_biz_lifemaster_indicator_normal);
+```
+![icon](pics/20151203-1.png)
+---
+### setIndicatorPadding
+
+`indicatorPadding` indicator的item之间的间距,默认是item的宽度
+
+#### 接口
+```
+IUltraIndicatorBuilder setIndicatorPadding(int indicatorPadding);
+```
+---
+### build
+设置完indicator属性后, 需调用`build`完成创建。
+
+#### 接口
+```
+void build();
+```
+---
+### setMultiScreen
+开启一屏多显模式,child view的宽度不占满全屏。
+#### 接口
+```
+void setMultiScreen(float ratio)
+```
+
+```
+ultraViewPager.setMultiScreen(0.5f);
+ultraViewPager.setItemRatio(1.0f);
+ultraViewPager.setAutoMeasureHeight(true);
+```
+
+
+
+---
+### setAutoMeasureHeight
+使能该功能,UltraViewPager的高度会自动调整到child view的高度。`setRadio` 和 `setAutoMeasureHeight` 不应该同时使用。
+#### 接口
+```
+void setAutoMeasureHeight(boolean enable)
+```
+
+```
+ultraViewPager.setMultiScreen(1.0f);//single screen
+ultraViewPager.setItemRatio(1.0f);//the aspect ratio of child view equals to 1.0f
+ultraViewPager.setAutoMeasureHeight(false);
+```
+
+
+```
+ultraViewPager.setMultiScreen(1.0f);
+ultraViewPager.setItemRatio(1.0f);
+ultraViewPager.setAutoMeasureHeight(true);
+```
+
+
+---
+### setItemRatio
+设置后会以此宽高比调整child view的高度。
+#### 接口
+
+```
+void setItemRatio(double ratio)
+```
+
+---
+
+### setRatio
+以设定的宽高比来绘制UltraViewPager。`setRatio`优先级高于`setItemRatio`.
+#### 接口
+```
+void setRatio(float ratio)
+```
+```
+ultraViewPager.setMultiScreen(1.0f);//single screen
+ultraViewPager.setRatio(2.0f);//the aspect ratio of viewpager equals to 2.0f
+ultraViewPager.setAutoMeasureHeight(true);
+```
+
+
+
diff --git a/ATTRIBUTES.md b/ATTRIBUTES.md
new file mode 100644
index 0000000..19ec202
--- /dev/null
+++ b/ATTRIBUTES.md
@@ -0,0 +1,129 @@
+[中文API](ATTRIBUTES-ch.md)
+### initIndicator
+Constructs a indicator with no options. This indicator supports calling set-method in chained mode. The arrtibutes of `focusColor` and `normalColor` are necessary, or the indicator won't be shown.
+
+#### API
+```
+IUltraIndicatorBuilder initIndicator();
+```
+---
+### setFocusColor setNormalColor
+Fill indicator with color.
+
+`focusColor` Set focused color for indicator.
+`normalColor` Set normal color for indicator.
+
+#### API
+```
+IUltraIndicatorBuilder setFocusColor(int focusColor);
+IUltraIndicatorBuilder setNormalColor(int normalColor);
+```
+
+```
+ultraViewPager.getIndicator()
+ .setFocusColor(Color.GREEN)
+ .setNormalColor(Color.WHITE)
+ .setRadius((int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics()));
+```
+
+![color](pics/20151203-0.png)
+
+---
+### setFocusResId setNormalResId
+Fill indicator with bitmap or icon.
+`focusResId` Set focused resource ID for indicator.
+`normalResId` Set normal resource ID for indicator.
+
+#### API
+```
+IUltraIndicatorBuilder setFocusResId(int focusResId);
+IUltraIndicatorBuilder setNormalResId(int normalResId);
+```
+```
+ultraViewPager.getIndicator()
+.setFocusResId(R.mipmap.tm_biz_lifemaster_indicator_selected)
+.setNormalResId(R.mipmap.tm_biz_lifemaster_indicator_normal);
+```
+![icon](pics/20151203-1.png)
+---
+### setIndicatorPadding
+
+`indicatorPadding` sets spacing between indicator items,the default value is item's height.
+
+
+#### API
+```
+IUltraIndicatorBuilder setIndicatorPadding(int indicatorPadding);
+```
+
+
+---
+### build
+After setting the indicator feature, call `build()` to complete.
+
+#### API
+```
+void build();
+```
+---
+### setMultiScreen
+set multi-screen feature, the width of the child view won't occupy full screen.
+#### API
+```
+void setMultiScreen(float ratio)
+```
+
+```
+ultraViewPager.setMultiScreen(0.5f);
+ultraViewPager.setItemRatio(1.0f);
+ultraViewPager.setAutoMeasureHeight(true);
+```
+
+
+---
+### setAutoMeasureHeight
+When enabled, the height of the UltraViewPager will be automatically adjusted to the height of child view.
+Do not use `setRadio` and `setAutoMeasureHeight` at the same time.
+#### API
+```
+void setAutoMeasureHeight(boolean enable)
+```
+
+```
+ultraViewPager.setMultiScreen(1.0f);//single screen
+ultraViewPager.setItemRatio(1.0f);//the aspect ratio of child view equals to 1.0f
+ultraViewPager.setAutoMeasureHeight(false);
+```
+
+
+```
+ultraViewPager.setMultiScreen(1.0f);
+ultraViewPager.setItemRatio(1.0f);
+ultraViewPager.setAutoMeasureHeight(true);
+```
+
+
+---
+### setItemRatio
+Adjust the height of child view with aspect `ratio`.
+#### API
+
+```
+void setItemRatio(double ratio)
+```
+
+---
+### setRatio
+Draw UltraViewPager with the aspect `ratio`. The priority of `setRatio` is higher than `setItemRatio`
+#### API
+```
+void setRatio(float ratio)
+```
+```
+ultraViewPager.setMultiScreen(1.0f);//single screen
+ultraViewPager.setRatio(2.0f);//the aspect ratio of viewpager equals to 2.0f
+ultraViewPager.setAutoMeasureHeight(true);
+```
+
+
+
diff --git a/README-ch.md b/README-ch.md
new file mode 100644
index 0000000..0cdcad9
--- /dev/null
+++ b/README-ch.md
@@ -0,0 +1,110 @@
+### UltraViewPager
+[English Document](README.md)
+
+#### 简介
+UltraViewPager是一个封装多种特性的ViewPager,主要是为多页面切换场景提供统一解决方案。
+
+![Example0](pics/example0.gif)
+![Example1](pics/example1.gif)
+![Example0](pics/example2.gif)
+![Example1](pics/example3.gif)
+
+#### 主要功能
+
+* 支持横向滑动/纵向滑动
+* 支持一屏内显示多页
+* 支持循环滚动
+* 支持定时滚动,计时器使用Handler实现
+* 支持设置ViewPager的最大宽高
+* setRatio按比例显示UltraviewPager
+* 内置indicator,只需简单设置几个属性就可以完成展示,支持圆点和Icon;
+* 内置两种页面切换动效
+
+以上特性支持同时使用;
+
+#### 设计思路
+UltraViewPager继承自RelativeLayout,将ViewPager和indicator置于其中,同时UltraViewPager提供了一些ViewPager常用方法的代理,这样在日常使用上保持和ViewPager无差异,如果需要调用ViewPager的所有方法,可通过getViewPager()方法拿到真正的ViewPager进行操作.
+
+竖向滑动是通过在ViewPager的onInterceptTouchEvent和onTouchEvent中交换横竖向的event location,同时设置特殊PageTransformer实现,详见源码.
+
+#### 使用方法
+版本请参考mvn repository上的最新版本(目前最新版本是1.0.22),最新的 aar 都会发布到 jcenter 和 MavenCentral 上,确保配置了这两个仓库源,然后引入aar依赖:
+
+```
+//gradle
+compile ('com.alibaba.android:ultraviewpager:1.0.22@aar') {
+ transitive = true
+}
+
+```
+
+或者maven
+
+```
+//pom.xml in maven
+
+ com.alibaba.android
+ ultraviewpager
+ 1.0.22
+ aar
+
+
+```
+
+在layout中使用UltraViewPager:
+activity_pager.xml
+
+```xml
+
+
+```
+
+可以参考以下步骤使用UltraViewPager:
+
+```
+UltraViewPager ultraViewPager = (UltraViewPager)findViewById(R.id.ultra_viewpager);
+ultraViewPager.setScrollMode(UltraViewPager.ScrollMode.HORIZONTAL);
+//UltraPagerAdapter 绑定子view到UltraViewPager
+PagerAdapter adapter = new UltraPagerAdapter(false);
+ultraViewPager.setAdapter(adapter);
+
+//内置indicator初始化
+ultraViewPager.initIndicator();
+//设置indicator样式
+ultraViewPager.getIndicator()
+ .setOrientation(UltraViewPager.Orientation.HORIZONTAL)
+ .setFocusColor(Color.GREEN)
+ .setNormalColor(Color.WHITE)
+ .setRadius((int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics()));
+//设置indicator对齐方式
+ultraViewPager.getIndicator().setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
+//构造indicator,绑定到UltraViewPager
+ultraViewPager.getIndicator().build();
+
+//设定页面循环播放
+ultraViewPager.setInfiniteLoop(true);
+//设定页面自动切换 间隔2秒
+ultraViewPager.setAutoScroll(2000);
+
+```
+Api接口详情请参考[文档](ATTRIBUTES-ch.md)
+
+#### DEMO
+
+[Demo工程](https://github.com/alibaba/vlayout/tree/master/examples)
+
+
+#### 开源许可证
+
+UltraViewPager遵循MIT开源许可证协议。
+
+
+
+
+
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..855873c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,113 @@
+### UltraViewPager
+
+[中文文档](README-ch.md)
+
+Project`UltraViewPager` is a ViewPager extension that encapsulates multiple features, mainly to provide a unified solution for multi-page switching scenarios.
+
+![Example0](pics/example0.gif)
+![Example1](pics/example1.gif)
+![Example0](pics/example2.gif)
+![Example1](pics/example3.gif)
+
+
+#### Main Feature
+
+* support horizontal scrolling and vertical scrolling
+* support multi views in one viewpager
+* support switching views circularly. For example, if there are 3 views to display in a ViewPager, it should switch back to the first view after the third view.
+* support auto-scrolling feature,implemented timer with Handler.
+* support setting max-height and max-width for this ViewPager.
+* support setting the aspect ratio for UltraViewPager.
+* UltraViewPager has a built-in indicator. support circle and icon style.
+* built-in two kind of page tansition animation.
+
+you can combine multiple features at the same time.
+
+#### Design
+UltraViewPager is a super extension for ViewPager.
+It's actually a RelativeLayout in order to display ViewPager and Indicator.UltraViewPager offers some common method delegate for ViewPager, you can also invoke more method by call getViewPager() and get the actual ViewPager.
+
+In order to achieve vertical scroll, through exchanging MotionEvent in onInterceptTouchEvent and onTouchEvent.For more details, you can read the source code.
+
+#### Usage
+
+Please find the latest version(1.0.0 so far) in maven repository. The newest version has been upload to jcenter and MavenCantral, make sure you have added at least one of these repositories.
+
+Using Gradle:
+
+```
+//gradle
+compile ('com.alibaba.android:ultraviewpager:1.0.0@aar') {
+ transitive = true
+}
+```
+or grab via Maven:
+
+```
+//pom.xml in maven
+
+ com.alibaba.android
+ ultraviewpager
+ 1.0.0
+ aar
+
+
+```
+
+Create your own layout using a UltraViewPager:
+
+activity_pager.xml
+
+```xml
+
+
+```
+
+You can follow my tutorial below on how to use UltraViewPager:
+
+```
+UltraViewPager ultraViewPager = (UltraViewPager)findViewById(R.id.ultra_viewpager);
+ultraViewPager.setScrollMode(UltraViewPager.ScrollMode.HORIZONTAL);
+//initialize UltraPagerAdapter,and add child view to UltraViewPager
+PagerAdapter adapter = new UltraPagerAdapter(false);
+ultraViewPager.setAdapter(adapter);
+
+//initialize built-in indicator
+ultraViewPager.initIndicator();
+//set style of indicators
+ultraViewPager.getIndicator()
+ .setOrientation(UltraViewPager.Orientation.HORIZONTAL)
+ .setFocusColor(Color.GREEN)
+ .setNormalColor(Color.WHITE)
+ .setRadius((int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics()));
+//set the alignment
+ultraViewPager.getIndicator().setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
+//construct built-in indicator, and add it to UltraViewPager
+ultraViewPager.getIndicator().build();
+
+//set an infinite loop
+ultraViewPager.setInfiniteLoop(true);
+//enable auto-scroll mode
+ultraViewPager.setAutoScroll(2000);
+
+```
+For other API reference,see [this](ATTRIBUTES.md) to read more.
+
+#### DEMO
+
+[Demo工程](https://github.com/alibaba/vlayout/tree/master/examples)
+
+
+#### LICENSE
+`UltraViewPager` is available under the MIT license.
+
+
+
+
+
+
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..ff35bf9
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,52 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ mavenCentral()
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.3.0'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ maven{url'https://oss.sonatype.org/content/repositories/snapshots/'}
+ mavenCentral()
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/deploy.gradle b/deploy.gradle
new file mode 100644
index 0000000..a33af8b
--- /dev/null
+++ b/deploy.gradle
@@ -0,0 +1,106 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+apply plugin: 'maven'
+
+afterEvaluate { project ->
+ // add this statement
+ // androidJavadoc.classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
+ // androidJavadoc.classpath += project.android.libraryVariants.toList().first().javaCompile.classpath
+ // androidJavadoc.classpath += files(project.getConfigurations().getByName('compile').asList())
+
+ task androidJavadoc(type: Javadoc) {
+ source = android.sourceSets.main.java.srcDirs
+
+ classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
+ classpath += files(project.getConfigurations().getByName('compile').asList())
+ classpath += files(android.bootClasspath)
+
+ options {
+ encoding "UTF-8"
+ charSet 'UTF-8'
+ author true
+ version true
+ links "http://d.android.com/reference/"
+ links "http://docs.oracle.com/javase/7/docs/api"
+ }
+
+ include '**/*.java'
+ exclude '**/BuildConfig.java'
+ exclude '**/R.java'
+ exclude '**/pom.xml'
+ exclude '**/proguard_annotations.pro'
+
+
+ failOnError false
+ }
+
+ task androidJavadocJar(type: Jar) {
+ classifier = 'javadoc'
+ from androidJavadoc.destinationDir
+ }
+
+ task androidSourcesJar(type: Jar) {
+ classifier = 'sources'
+ from android.sourceSets.main.java.srcDirs
+ }
+
+ android.libraryVariants.all { variant ->
+ def name = variant.name.capitalize()
+ task "jar${name}"(type: Jar, dependsOn: variant.javaCompile) {
+ from variant.javaCompile.destinationDir
+ }
+ }
+
+
+
+ artifacts.add('archives', androidJavadocJar)
+ artifacts.add('archives', androidSourcesJar)
+
+ def configurePom = { pom ->
+ // repository(url: "${System.env.HOME}/.m2/repository")
+ def packageVersion = VERSION_NAME
+
+ if (!project.hasProperty('doRelease')) {
+ packageVersion = packageVersion + '-SNAPSHOT'
+ }
+
+ pom.project {
+ pom.groupId = GROUP
+ pom.artifactId = ARTIFACT
+ pom.version = packageVersion
+ pom.packaging = PACKAGING_TYPE
+ }
+ }
+
+ task installArchives(type: Upload) {
+ configuration = configurations.archives
+ repositories.mavenDeployer {
+ repository url: "file://${System.properties['user.home']}/.m2/repository"
+ configurePom pom
+ }
+ }
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..c53e726
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,53 @@
+#
+#
+# MIT License
+#
+# Copyright (c) 2017 Alibaba Group
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+#
+
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+
+GROUP=com.alibaba.android
+ARTIFACT=ultraviewpager
+VERSION=10
+VERSION_NAME=1.0.22
+PACKAGING_TYPE=aar
+systemProp.compileSdkVersion=23
+systemProp.targetSdkVersion=23
+systemProp.buildToolsVersion=23.0.2
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..05ef575
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..33d5c89
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,33 @@
+#
+#
+# MIT License
+#
+# Copyright (c) 2017 Alibaba Group
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+#
+
+#Wed Oct 21 11:34:03 PDT 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-all.zip
+
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..9d82f78
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,160 @@
+#!/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
+
+# 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\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+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"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # 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/pics/20151203-0.png b/pics/20151203-0.png
new file mode 100644
index 0000000..04a92ef
Binary files /dev/null and b/pics/20151203-0.png differ
diff --git a/pics/20151203-1.png b/pics/20151203-1.png
new file mode 100644
index 0000000..f610f4c
Binary files /dev/null and b/pics/20151203-1.png differ
diff --git a/pics/20151203-2.png b/pics/20151203-2.png
new file mode 100644
index 0000000..df27fd0
Binary files /dev/null and b/pics/20151203-2.png differ
diff --git a/pics/api0.png b/pics/api0.png
new file mode 100644
index 0000000..5de56e0
Binary files /dev/null and b/pics/api0.png differ
diff --git a/pics/api1.png b/pics/api1.png
new file mode 100644
index 0000000..5ecf5e3
Binary files /dev/null and b/pics/api1.png differ
diff --git a/pics/api2.png b/pics/api2.png
new file mode 100644
index 0000000..a95f276
Binary files /dev/null and b/pics/api2.png differ
diff --git a/pics/api3.png b/pics/api3.png
new file mode 100644
index 0000000..5534b81
Binary files /dev/null and b/pics/api3.png differ
diff --git a/pics/demo_0.png b/pics/demo_0.png
new file mode 100644
index 0000000..d17e350
Binary files /dev/null and b/pics/demo_0.png differ
diff --git a/pics/demo_1.png b/pics/demo_1.png
new file mode 100644
index 0000000..5e7e7e3
Binary files /dev/null and b/pics/demo_1.png differ
diff --git a/pics/example0.gif b/pics/example0.gif
new file mode 100644
index 0000000..622dfb8
Binary files /dev/null and b/pics/example0.gif differ
diff --git a/pics/example1.gif b/pics/example1.gif
new file mode 100644
index 0000000..e3e0fd2
Binary files /dev/null and b/pics/example1.gif differ
diff --git a/pics/example2.gif b/pics/example2.gif
new file mode 100644
index 0000000..ec308f7
Binary files /dev/null and b/pics/example2.gif differ
diff --git a/pics/example3.gif b/pics/example3.gif
new file mode 100644
index 0000000..ae07687
Binary files /dev/null and b/pics/example3.gif differ
diff --git a/readme.html b/readme.html
new file mode 100644
index 0000000..1fec454
--- /dev/null
+++ b/readme.html
@@ -0,0 +1,397 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sample/.gitignore b/sample/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/sample/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/sample/build.gradle b/sample/build.gradle
new file mode 100644
index 0000000..5504f75
--- /dev/null
+++ b/sample/build.gradle
@@ -0,0 +1,51 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion "23.0.2"
+
+ defaultConfig {
+ minSdkVersion 14
+ targetSdkVersion 23
+ 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 project(':ultraviewpager')
+
+}
diff --git a/sample/proguard-rules.pro b/sample/proguard-rules.pro
new file mode 100644
index 0000000..4ad4192
--- /dev/null
+++ b/sample/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/mikeafc/Library/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/sample/src/androidTest/java/com/tmall/ultraviewpager/ApplicationTest.java b/sample/src/androidTest/java/com/tmall/ultraviewpager/ApplicationTest.java
new file mode 100644
index 0000000..c03d45b
--- /dev/null
+++ b/sample/src/androidTest/java/com/tmall/ultraviewpager/ApplicationTest.java
@@ -0,0 +1,39 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager;
+
+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/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..d7c16cc
--- /dev/null
+++ b/sample/src/main/AndroidManifest.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sample/src/main/assets/ultraviewpager_config.xml b/sample/src/main/assets/ultraviewpager_config.xml
new file mode 100644
index 0000000..7b82def
--- /dev/null
+++ b/sample/src/main/assets/ultraviewpager_config.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+ com.tmall.ultraviewpager
+ com.tmall.ultraviewpager
+ UltraViewPager
+ 简单高效的 ViewPager!
+ 智闲
+ 2015-12-04
+ Views
+
+
+
\ No newline at end of file
diff --git a/sample/src/main/java/com/tmall/ultraviewpager/sample/PagerActivity.java b/sample/src/main/java/com/tmall/ultraviewpager/sample/PagerActivity.java
new file mode 100644
index 0000000..0405410
--- /dev/null
+++ b/sample/src/main/java/com/tmall/ultraviewpager/sample/PagerActivity.java
@@ -0,0 +1,295 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager.sample;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.support.v4.view.PagerAdapter;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.RelativeLayout;
+import android.widget.Spinner;
+
+import com.tmall.ultraviewpager.UltraViewPager;
+import com.tmall.ultraviewpager.transformer.UltraDepthScaleTransformer;
+import com.tmall.ultraviewpager.transformer.UltraScaleTransformer;
+
+
+public class PagerActivity extends Activity implements AdapterView.OnItemSelectedListener, CompoundButton.OnCheckedChangeListener, View.OnClickListener {
+ private UltraViewPager ultraViewPager;
+ private PagerAdapter adapter;
+
+ private Spinner indicatorStyle;
+ private Spinner indicatorGravityHor;
+ private Spinner indicatorGravityVer;
+
+ private Button indicatorBuildBtn;
+
+ private CheckBox loopCheckBox;
+ private CheckBox autoScrollCheckBox;
+
+ private int gravity_hor;
+ private int gravity_ver;
+ private UltraViewPager.Orientation gravity_indicator;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_pager);
+
+ int style = getIntent().getIntExtra("style", 1);
+ ultraViewPager = (UltraViewPager) findViewById(R.id.ultra_viewpager);
+
+ switch (style){
+ case 1:
+ setTitle("Horizontal Demo");
+ break;
+ case 2:
+ setTitle("Vertical Demo");
+ break;
+ case 3:
+ setTitle("MultiScreen_H Demo");
+ break;
+ case 4:
+ setTitle("MultiScreen_V Demo");
+ break;
+ case 5:
+ setTitle("ScaleTransformer Demo");
+ break;
+ case 6:
+ setTitle("DepthTransformer Demo");
+ break;
+ default:
+ break;
+ }
+
+// defaultUltraViewPager();
+
+ switch (style) {
+ case 1:
+ ultraViewPager.setScrollMode(UltraViewPager.ScrollMode.HORIZONTAL);
+ adapter = new UltraPagerAdapter(false);
+ ultraViewPager.setAdapter(adapter);
+ gravity_indicator = UltraViewPager.Orientation.HORIZONTAL;
+ break;
+ case 2:
+ ultraViewPager.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ ultraViewPager.setScrollMode(UltraViewPager.ScrollMode.VERTICAL);
+ adapter = new UltraPagerAdapter(false);
+ ultraViewPager.setAdapter(adapter);
+ gravity_indicator = UltraViewPager.Orientation.VERTICAL;
+ break;
+ case 3:
+ case 5:
+ case 6:
+ ultraViewPager.setScrollMode(UltraViewPager.ScrollMode.HORIZONTAL);
+ adapter = new UltraPagerAdapter(true);
+ ultraViewPager.setAdapter(adapter);
+ ultraViewPager.setMultiScreen(0.6f);
+ ultraViewPager.setItemRatio(1.0f);
+// ultraViewPager.setRatio(2.0f);
+// ultraViewPager.setMaxHeight(800);
+ ultraViewPager.setAutoMeasureHeight(true);
+ gravity_indicator = UltraViewPager.Orientation.HORIZONTAL;
+ if (style == 5) {
+ ultraViewPager.setPageTransformer(false, new UltraScaleTransformer());
+ }
+ if (style == 6) {
+ ultraViewPager.setPageTransformer(false, new UltraDepthScaleTransformer());
+ }
+ break;
+ case 4:
+ ultraViewPager.setScrollMode(UltraViewPager.ScrollMode.VERTICAL);
+ ultraViewPager.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ adapter = new UltraPagerAdapter(true);
+ ultraViewPager.setAdapter(adapter);
+ ultraViewPager.setMultiScreen(1.0f);
+ ultraViewPager.setAutoMeasureHeight(true);
+ gravity_indicator = UltraViewPager.Orientation.VERTICAL;
+ break;
+ }
+
+ initUI();
+ }
+
+ private void initUI() {
+ indicatorStyle = (Spinner) findViewById(R.id.indicator);
+ indicatorGravityHor = (Spinner) findViewById(R.id.indicator_gravity_hor);
+ indicatorGravityVer = (Spinner) findViewById(R.id.indicator_gravity_ver);
+
+ ArrayAdapter indicatorAdapter = ArrayAdapter.createFromResource(this, R.array.indicator_style, android.R.layout.simple_spinner_item);
+ indicatorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ indicatorStyle.setAdapter(indicatorAdapter);
+
+ ArrayAdapter indicatorGraHorAdapter = ArrayAdapter.createFromResource(this, R.array.indicator_gravity_hor, android.R.layout.simple_spinner_item);
+ indicatorGraHorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ indicatorGravityHor.setAdapter(indicatorGraHorAdapter);
+
+ ArrayAdapter indicatorGraVerAdapter = ArrayAdapter.createFromResource(this, R.array.indicator_gravity_ver, android.R.layout.simple_spinner_item);
+ indicatorGraVerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ indicatorGravityVer.setAdapter(indicatorGraVerAdapter);
+
+ indicatorStyle.setOnItemSelectedListener(this);
+ indicatorGravityHor.setOnItemSelectedListener(this);
+ indicatorGravityVer.setOnItemSelectedListener(this);
+
+ loopCheckBox = (CheckBox) findViewById(R.id.loop);
+ loopCheckBox.setOnCheckedChangeListener(this);
+
+ autoScrollCheckBox = (CheckBox) findViewById(R.id.autoscroll);
+ autoScrollCheckBox.setOnCheckedChangeListener(this);
+
+ indicatorBuildBtn = (Button) findViewById(R.id.indicator_build);
+ indicatorBuildBtn.setOnClickListener(this);
+ }
+
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ if (ultraViewPager.getIndicator() == null) {
+ ultraViewPager.initIndicator();
+ ultraViewPager.getIndicator().setOrientation(gravity_indicator);
+ }
+ if (parent == indicatorStyle) {
+ switch (position) {
+ case 0:
+ ultraViewPager.disableIndicator();
+ break;
+ case 1:
+ ultraViewPager.getIndicator().setFocusResId(0).setNormalResId(0);
+ ultraViewPager.getIndicator().setFocusColor(Color.GREEN).setNormalColor(Color.WHITE)
+ .setRadius((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics()));
+ break;
+ case 2:
+ ultraViewPager.getIndicator().setFocusResId(R.mipmap.tm_biz_lifemaster_indicator_selected)
+ .setNormalResId(R.mipmap.tm_biz_lifemaster_indicator_normal);
+ break;
+ case 3:
+ break;
+ }
+ }
+ if (parent == indicatorGravityHor) {
+ switch (position) {
+ case 0:
+ gravity_hor = Gravity.LEFT;
+ break;
+ case 1:
+ gravity_hor = Gravity.RIGHT;
+ break;
+ case 2:
+ gravity_hor = Gravity.CENTER_HORIZONTAL;
+ break;
+ }
+ if (ultraViewPager.getIndicator() != null) {
+ if (gravity_ver != 0) {
+ ultraViewPager.getIndicator().setGravity(gravity_hor | gravity_ver);
+ } else {
+ ultraViewPager.getIndicator().setGravity(gravity_hor);
+ }
+ }
+ }
+ if (parent == indicatorGravityVer) {
+ switch (position) {
+ case 0:
+ gravity_ver = Gravity.TOP;
+ break;
+ case 1:
+ gravity_ver = Gravity.BOTTOM;
+ break;
+ case 2:
+ gravity_ver = Gravity.CENTER_VERTICAL;
+ break;
+ }
+ if (ultraViewPager.getIndicator() != null) {
+ if (gravity_hor != 0) {
+ ultraViewPager.getIndicator().setGravity(gravity_hor | gravity_ver);
+ } else {
+ ultraViewPager.getIndicator().setGravity(gravity_ver);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+
+ }
+
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (buttonView == loopCheckBox) {
+ ultraViewPager.setInfiniteLoop(isChecked);
+ }
+ if (buttonView == autoScrollCheckBox) {
+ if (isChecked)
+ ultraViewPager.setAutoScroll(2000);
+ else
+ ultraViewPager.disableAutoScroll();
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ ultraViewPager.getIndicator().build();
+ }
+
+ /**
+ *
+ */
+ private void defaultUltraViewPager(){
+ UltraViewPager ultraViewPager = (UltraViewPager)findViewById(R.id.ultra_viewpager);
+ ultraViewPager.setScrollMode(UltraViewPager.ScrollMode.HORIZONTAL);
+ //initialize UltraPagerAdapter,and add child view to UltraViewPager
+ PagerAdapter adapter = new UltraPagerAdapter(false);
+ ultraViewPager.setAdapter(adapter);
+
+ //initialize built-in indicator
+ ultraViewPager.initIndicator();
+ //set style of indicators
+ ultraViewPager.getIndicator()
+ .setOrientation(UltraViewPager.Orientation.HORIZONTAL)
+ .setFocusColor(Color.GREEN)
+ .setNormalColor(Color.WHITE)
+ .setRadius((int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics()));
+ //set the alignment
+ ultraViewPager.getIndicator().setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
+ //construct built-in indicator, and add it to UltraViewPager
+ ultraViewPager.getIndicator().build();
+
+ //set an infinite loop
+ ultraViewPager.setInfiniteLoop(true);
+ //enable auto-scroll mode
+ ultraViewPager.setAutoScroll(2000);
+ }
+}
diff --git a/sample/src/main/java/com/tmall/ultraviewpager/sample/UPVDemoActivity.java b/sample/src/main/java/com/tmall/ultraviewpager/sample/UPVDemoActivity.java
new file mode 100644
index 0000000..6f529af
--- /dev/null
+++ b/sample/src/main/java/com/tmall/ultraviewpager/sample/UPVDemoActivity.java
@@ -0,0 +1,75 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager.sample;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+
+public class UPVDemoActivity extends Activity {
+ private Intent intent;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_upvdemo);
+
+ intent = new Intent();
+ intent.setClass(this, PagerActivity.class);
+ }
+
+ public void clickHorizontal(View view) {
+ intent.putExtra("style", 1);
+ startActivity(intent);
+ }
+
+ public void clickVertical(View view) {
+ intent.putExtra("style", 2);
+ startActivity(intent);
+ }
+
+ public void clickMultiScrHorizontal(View view) {
+ intent.putExtra("style", 3);
+ startActivity(intent);
+ }
+
+ public void clickMultiScrVertical(View view) {
+ intent.putExtra("style", 4);
+ startActivity(intent);
+ }
+
+ public void clickScaleTransformer(View view) {
+ intent.putExtra("style", 5);
+ startActivity(intent);
+ }
+
+ public void clickDepthTransformer(View view) {
+ intent.putExtra("style", 6);
+ startActivity(intent);
+ }
+}
diff --git a/sample/src/main/java/com/tmall/ultraviewpager/sample/UltraPagerAdapter.java b/sample/src/main/java/com/tmall/ultraviewpager/sample/UltraPagerAdapter.java
new file mode 100644
index 0000000..50eccc3
--- /dev/null
+++ b/sample/src/main/java/com/tmall/ultraviewpager/sample/UltraPagerAdapter.java
@@ -0,0 +1,92 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager.sample;
+
+import android.graphics.Color;
+import android.support.v4.view.PagerAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * Created by mikeafc on 15/11/26.
+ */
+public class UltraPagerAdapter extends PagerAdapter {
+ private boolean isMultiScr;
+
+ public UltraPagerAdapter(boolean isMultiScr) {
+ this.isMultiScr = isMultiScr;
+ }
+
+ @Override
+ public int getCount() {
+ return 5;
+ }
+
+ @Override
+ public boolean isViewFromObject(View view, Object object) {
+ return view == object;
+ }
+
+ @Override
+ public Object instantiateItem(ViewGroup container, int position) {
+ LinearLayout linearLayout = (LinearLayout) LayoutInflater.from(container.getContext()).inflate(R.layout.layout_child, null);
+ //new LinearLayout(container.getContext());
+ TextView textView = (TextView) linearLayout.findViewById(R.id.pager_textview);
+ textView.setText(position + "");
+ linearLayout.setId(R.id.item_id);
+ switch (position) {
+ case 0:
+ linearLayout.setBackgroundColor(Color.parseColor("#2196F3"));
+ break;
+ case 1:
+ linearLayout.setBackgroundColor(Color.parseColor("#673AB7"));
+ break;
+ case 2:
+ linearLayout.setBackgroundColor(Color.parseColor("#009688"));
+ break;
+ case 3:
+ linearLayout.setBackgroundColor(Color.parseColor("#607D8B"));
+ break;
+ case 4:
+ linearLayout.setBackgroundColor(Color.parseColor("#F44336"));
+ break;
+ }
+ container.addView(linearLayout);
+// linearLayout.getLayoutParams().width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 180, container.getContext().getResources().getDisplayMetrics());
+// linearLayout.getLayoutParams().height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 400, container.getContext().getResources().getDisplayMetrics());
+ return linearLayout;
+ }
+
+ @Override
+ public void destroyItem(ViewGroup container, int position, Object object) {
+ LinearLayout view = (LinearLayout) object;
+ container.removeView(view);
+ }
+}
diff --git a/sample/src/main/res/layout/activity_pager.xml b/sample/src/main/res/layout/activity_pager.xml
new file mode 100644
index 0000000..79b5525
--- /dev/null
+++ b/sample/src/main/res/layout/activity_pager.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sample/src/main/res/layout/activity_upvdemo.xml b/sample/src/main/res/layout/activity_upvdemo.xml
new file mode 100644
index 0000000..973d114
--- /dev/null
+++ b/sample/src/main/res/layout/activity_upvdemo.xml
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sample/src/main/res/layout/layout_child.xml b/sample/src/main/res/layout/layout_child.xml
new file mode 100644
index 0000000..60687b7
--- /dev/null
+++ b/sample/src/main/res/layout/layout_child.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
diff --git a/sample/src/main/res/mipmap-hdpi/ic_launcher.png b/sample/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
Binary files /dev/null and b/sample/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/sample/src/main/res/mipmap-mdpi/ic_launcher.png b/sample/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
Binary files /dev/null and b/sample/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/sample/src/main/res/mipmap-xhdpi/ic_launcher.png b/sample/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
Binary files /dev/null and b/sample/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/sample/src/main/res/mipmap-xhdpi/tm_biz_lifemaster_indicator_normal.png b/sample/src/main/res/mipmap-xhdpi/tm_biz_lifemaster_indicator_normal.png
new file mode 100644
index 0000000..883769c
Binary files /dev/null and b/sample/src/main/res/mipmap-xhdpi/tm_biz_lifemaster_indicator_normal.png differ
diff --git a/sample/src/main/res/mipmap-xhdpi/tm_biz_lifemaster_indicator_selected.png b/sample/src/main/res/mipmap-xhdpi/tm_biz_lifemaster_indicator_selected.png
new file mode 100644
index 0000000..f4a2102
Binary files /dev/null and b/sample/src/main/res/mipmap-xhdpi/tm_biz_lifemaster_indicator_selected.png differ
diff --git a/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png b/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
Binary files /dev/null and b/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..aee44e1
Binary files /dev/null and b/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/sample/src/main/res/values-w820dp/dimens.xml b/sample/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..ce8a59c
--- /dev/null
+++ b/sample/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,32 @@
+
+
+
+
+ 64dp
+
diff --git a/sample/src/main/res/values/colors.xml b/sample/src/main/res/values/colors.xml
new file mode 100644
index 0000000..0fafa0f
--- /dev/null
+++ b/sample/src/main/res/values/colors.xml
@@ -0,0 +1,32 @@
+
+
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+
diff --git a/sample/src/main/res/values/dimens.xml b/sample/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..2938755
--- /dev/null
+++ b/sample/src/main/res/values/dimens.xml
@@ -0,0 +1,32 @@
+
+
+
+
+ 16dp
+ 16dp
+ 16dp
+
diff --git a/sample/src/main/res/values/ids.xml b/sample/src/main/res/values/ids.xml
new file mode 100644
index 0000000..3d7c456
--- /dev/null
+++ b/sample/src/main/res/values/ids.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0a82d66
--- /dev/null
+++ b/sample/src/main/res/values/strings.xml
@@ -0,0 +1,46 @@
+
+
+
+ UltraViewPager
+ UltraViewPager
+
+ None
+ Circle
+ Icon
+ Count
+
+
+ Left
+ Right
+ Center
+
+
+ Top
+ Bottom
+ Center
+
+
diff --git a/sample/src/main/res/values/styles.xml b/sample/src/main/res/values/styles.xml
new file mode 100644
index 0000000..b414e03
--- /dev/null
+++ b/sample/src/main/res/values/styles.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..38036fb
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,27 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+include ':sample', ':ultraviewpager'
diff --git a/ultraviewpager/.gitignore b/ultraviewpager/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/ultraviewpager/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/ultraviewpager/build.gradle b/ultraviewpager/build.gradle
new file mode 100644
index 0000000..83071fc
--- /dev/null
+++ b/ultraviewpager/build.gradle
@@ -0,0 +1,58 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+apply plugin: 'com.android.library'
+apply plugin: "maven"
+apply plugin: 'maven-publish'
+
+def VERSION = System.properties['version'] ?: '10'
+def VERSION_NAME = System.properties['versionName'] ?: '0.1.0'
+
+android {
+ compileSdkVersion Integer.parseInt(System.properties['compileSdkVersion'] ?: '23')
+ buildToolsVersion System.properties['buildToolsVersion'] ?: '23.0.2'
+
+ defaultConfig {
+ minSdkVersion 14
+ targetSdkVersion Integer.parseInt(System.properties['targetSdkVersion'] ?: '23')
+ versionCode Integer.parseInt(VERSION)
+ versionName VERSION_NAME
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ testCompile 'junit:junit:4.12'
+ compile "com.android.support:support-v4:23.1.1@aar"
+ compile 'com.android.support:recyclerview-v7:23.1.1@aar'
+}
+
diff --git a/ultraviewpager/proguard-rules.pro b/ultraviewpager/proguard-rules.pro
new file mode 100644
index 0000000..4ad4192
--- /dev/null
+++ b/ultraviewpager/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/mikeafc/Library/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/ultraviewpager/src/androidTest/java/com/tmall/ultraviewpager/ApplicationTest.java b/ultraviewpager/src/androidTest/java/com/tmall/ultraviewpager/ApplicationTest.java
new file mode 100644
index 0000000..c03d45b
--- /dev/null
+++ b/ultraviewpager/src/androidTest/java/com/tmall/ultraviewpager/ApplicationTest.java
@@ -0,0 +1,39 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager;
+
+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/ultraviewpager/src/main/AndroidManifest.xml b/ultraviewpager/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..1c3a17a
--- /dev/null
+++ b/ultraviewpager/src/main/AndroidManifest.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
diff --git a/ultraviewpager/src/main/java/com/tmall/ultraviewpager/IUltraIndicatorBuilder.java b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/IUltraIndicatorBuilder.java
new file mode 100644
index 0000000..b440f7e
--- /dev/null
+++ b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/IUltraIndicatorBuilder.java
@@ -0,0 +1,134 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager;
+
+import android.graphics.Bitmap;
+
+/**
+ * Created by mikeafc on 15/11/25.
+ */
+public interface IUltraIndicatorBuilder {
+ /**
+ * Set focused color for indicator.
+ * @param focusColor
+ * @return
+ */
+ IUltraIndicatorBuilder setFocusColor(int focusColor);
+
+ /**
+ * Set normal color for indicator.
+ * @param normalColor
+ * @return
+ */
+ IUltraIndicatorBuilder setNormalColor(int normalColor);
+
+ /**
+ * Set stroke color for indicator.
+ * @param strokeColor
+ * @return
+ */
+ IUltraIndicatorBuilder setStrokeColor(int strokeColor);
+
+ /**
+ * Set stroke width for indicator.
+ * @param strokeWidth
+ * @return
+ */
+ IUltraIndicatorBuilder setStrokeWidth(int strokeWidth);
+
+ /**
+ * Set spacing between indicator item ,the default value is item's height.
+ * @param indicatorPadding
+ * @return
+ */
+ IUltraIndicatorBuilder setIndicatorPadding(int indicatorPadding);
+
+ /**
+ * Set the corner radius of the indicator item.
+ * @param radius
+ * @return
+ */
+ IUltraIndicatorBuilder setRadius(int radius);
+
+ /**
+ * Sets the orientation of the layout.
+ * @param orientation
+ * @return
+ */
+ IUltraIndicatorBuilder setOrientation(UltraViewPager.Orientation orientation);
+
+ /**
+ * Set the location at which the indicator should appear on the screen.
+ *
+ * @param gravity android.view.Gravity
+ * @return
+ */
+ IUltraIndicatorBuilder setGravity(int gravity);
+
+ /**
+ * Set focused resource ID for indicator.
+ * @param focusResId
+ * @return
+ */
+ IUltraIndicatorBuilder setFocusResId(int focusResId);
+
+ /**
+ * Set normal resource ID for indicator.
+ * @param normalResId
+ * @return
+ */
+ IUltraIndicatorBuilder setNormalResId(int normalResId);
+
+ /**
+ * Set focused icon for indicator.
+ * @param bitmap
+ * @return
+ */
+ IUltraIndicatorBuilder setFocusIcon(Bitmap bitmap);
+
+ /**
+ * Set normal icon for indicator.
+ * @param bitmap
+ * @return
+ */
+ IUltraIndicatorBuilder setNormalIcon(Bitmap bitmap);
+
+ /**
+ * Set margins for indicator.
+ * @param left the left margin in pixels
+ * @param top the top margin in pixels
+ * @param right the right margin in pixels
+ * @param bottom the bottom margin in pixels
+ * @return
+ */
+ IUltraIndicatorBuilder setMargin(int left, int top, int right, int bottom);
+
+ /**
+ * Combine all of the options that have been set and return a new IUltraIndicatorBuilder object.
+ */
+ void build();
+}
diff --git a/ultraviewpager/src/main/java/com/tmall/ultraviewpager/IUltraViewPagerFeature.java b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/IUltraViewPagerFeature.java
new file mode 100644
index 0000000..da86233
--- /dev/null
+++ b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/IUltraViewPagerFeature.java
@@ -0,0 +1,179 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager;
+
+import android.graphics.Bitmap;
+
+/**
+ * Created by mikeafc on 15/11/30.
+ */
+interface IUltraViewPagerFeature {
+ /**
+ * Constructs a indicator with no options. this indicator support set-Method in chained mode.
+ * meanwhile focusColor and normalColor are necessary,or the indicator won't be show.
+ */
+ IUltraIndicatorBuilder initIndicator();
+
+ /**
+ * Set options for indicator
+ *
+ * @param focusColor defines the color when indicator is focused.
+ * @param normalColor defines the color when indicator is in the default state (not focused).
+ * @param radiusInPixel defines the radius of indicator item.
+ * @param gravity specifies how to align the indicator. for example, using Gravity.BOTTOM | Gravity.RIGHT
+ */
+ IUltraIndicatorBuilder initIndicator(int focusColor, int normalColor, int radiusInPixel, int gravity);
+
+ /**
+ * Set options for indicator
+ *
+ * @param focusColor defines the color when indicator is focused.
+ * @param normalColor defines the color when indicator is in the default state (not focused).
+ * @param strokeColor stroke color
+ * @param strokeWidth stroke width
+ * @param radiusInPixel the radius of indicator item.
+ * @param gravity specifies how to align the indicator. for example, using Gravity.BOTTOM | Gravity.RIGHT
+ */
+ IUltraIndicatorBuilder initIndicator(int focusColor, int normalColor, int strokeColor, int strokeWidth, int radiusInPixel, int gravity);
+
+ /**
+ * Set options for indicator
+ *
+ * @param focusResId defines the resource id when indicator is focused.
+ * @param normalResId defines the resource id when indicator is in the default state (not focused).
+ * @param gravity specifies how to align the indicator. for example, using Gravity.BOTTOM | Gravity.RIGHT
+ */
+ IUltraIndicatorBuilder initIndicator(int focusResId, int normalResId, int gravity);
+
+ /**
+ *
+ * @param focusBitmap defines the bitmap when indicator is focused
+ * @param normalBitmap defines the bitmap when indicator is in the default state (not focused).
+ * @param gravity specifies how to align the indicator. for example, using Gravity.BOTTOM | Gravity.RIGHT
+ * @return
+ */
+ IUltraIndicatorBuilder initIndicator(Bitmap focusBitmap, Bitmap normalBitmap, int gravity);
+
+ /**
+ * Remove indicator
+ */
+ void disableIndicator();
+
+ /**
+ * Enable auto-scroll mode
+ *
+ * @param intervalInMillis The interval time to scroll in milliseconds.
+ */
+ void setAutoScroll(int intervalInMillis);
+
+ /**
+ * Disable auto-scroll mode
+ */
+ void disableAutoScroll();
+
+ /**
+ * Set an infinite loop
+ *
+ * @param enable enable or disable
+ */
+ void setInfiniteLoop(boolean enable);
+
+ /**
+ * Supply a maximum width for this ViewPager.
+ *
+ * @param width width
+ */
+ void setMaxWidth(int width);
+
+ /**
+ * Supply a maximum height for this ViewPager.
+ *
+ * @param height height
+ */
+ void setMaxHeight(int height);
+
+ /**
+ * Set the aspect ratio for UltraViewPager.
+ *
+ * @param ratio
+ */
+ void setRatio(float ratio);
+
+ /**
+ * Set scroll mode for UltraViewPager.
+ *
+ * @param scrollMode UltraViewPager.ScrollMode.HORIZONTAL or UltraViewPager.ScrollMode.VERTICAL
+ */
+ void setScrollMode(UltraViewPager.ScrollMode scrollMode);
+
+ /**
+ * Disable scroll direction. the default value is ScrollDirection.NONE
+ *
+ * @param direction NONE, BACKWARD, FORWARD
+ */
+ void disableScrollDirection(UltraViewPager.ScrollDirection direction);
+
+ /**
+ * Scroll to the next page, and return to the first page when the last page is reached.
+ */
+ void scrollNextPage();
+
+ /**
+ * Set multi-screen mode , the aspect ratio of PageViewer should less than or equal to 1.0f
+ */
+ void setMultiScreen(float ratio);
+
+ /**
+ * Adjust the height of the ViewPager to the height of child automatically.
+ */
+ void setAutoMeasureHeight(boolean status);
+
+ /**
+ * Adjust the height of child item view with aspect ratio.
+ *
+ * @param ratio aspect ratio
+ */
+ void setItemRatio(double ratio);
+
+ /**
+ * Set item margin
+ *
+ * @param left the left margin in pixels
+ * @param top the top margin in pixels
+ * @param right the right margin in pixels
+ * @param bottom the bottom margin in pixels
+ */
+ void setItemMargin(int left, int top, int right, int bottom);
+
+ /**
+ * Set margins for this ViewPager
+ *
+ * @param left the left margin in pixels
+ * @param right the right margin in pixels
+ */
+ void setScrollMargin(int left, int right);
+}
diff --git a/ultraviewpager/src/main/java/com/tmall/ultraviewpager/TimerHandler.java b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/TimerHandler.java
new file mode 100644
index 0000000..4ad90e4
--- /dev/null
+++ b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/TimerHandler.java
@@ -0,0 +1,59 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager;
+
+import android.os.Handler;
+import android.os.Message;
+
+/**
+ * Created by mikeafc on 15/11/25.
+ */
+class TimerHandler extends Handler {
+ interface TimerHandlerListener {
+ void callBack();
+ }
+
+ long interval;
+ boolean isInTouchMode;
+ TimerHandlerListener listener;
+
+ static final int MSG_TIMER_ID = 87108;
+
+ TimerHandler(TimerHandlerListener listener, long interval) {
+ this.listener = listener;
+ this.interval = interval;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (MSG_TIMER_ID == msg.what) {
+ if (listener != null && !isInTouchMode)
+ listener.callBack();
+ sendEmptyMessageDelayed(MSG_TIMER_ID, interval);
+ }
+ }
+}
diff --git a/ultraviewpager/src/main/java/com/tmall/ultraviewpager/UltraViewPager.java b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/UltraViewPager.java
new file mode 100644
index 0000000..bfb23a5
--- /dev/null
+++ b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/UltraViewPager.java
@@ -0,0 +1,451 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RelativeLayout;
+
+/**
+ * Created by mikeafc on 15/10/26.
+ * UltraViewPager is a super extension for ViewPager.
+ * It's actually a RelativeLayout in order to display indicator, UltraViewPager offers some usual
+ * method delegate for ViewPager, you can also invoke more method by call getViewPager() and get the actual
+ * ViewPager.
+ */
+public class UltraViewPager extends RelativeLayout implements IUltraViewPagerFeature {
+
+ public enum ScrollMode {
+ HORIZONTAL(0), VERTICAL(1);
+ int id;
+
+ ScrollMode(int id) {
+ this.id = id;
+ }
+
+ static ScrollMode getScrollMode(int id) {
+ for (ScrollMode scrollMode : values()) {
+ if (scrollMode.id == id)
+ return scrollMode;
+ }
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public enum Orientation {
+ HORIZONTAL, VERTICAL
+ }
+
+ public enum ScrollDirection {
+ NONE(0), BACKWARD(1), FORWARD(2);
+ int id;
+
+ ScrollDirection(int id) {
+ this.id = id;
+ }
+
+ static ScrollDirection getScrollDirection(int id) {
+ for (ScrollDirection direction : values()) {
+ if (direction.id == id)
+ return direction;
+ }
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private final Point size;
+ private final Point maxSize;
+
+ private float ratio = Float.NaN;
+
+ //Maximum width of child when enable multiScreen.
+ private int maxWidth = -1;
+
+ //Maximum height of child when enable multiScreen.
+ private int maxHeight = -1;
+
+ private UltraViewPagerView viewPager;
+ private UltraViewPagerIndicator pagerIndicator;
+
+ private TimerHandler timer;
+
+
+ public UltraViewPager(Context context) {
+ super(context);
+ size = new Point();
+ maxSize = new Point();
+ initView();
+ }
+
+ public UltraViewPager(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ size = new Point();
+ maxSize = new Point();
+ initView();
+ initView(context, attrs);
+ }
+
+ public UltraViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ size = new Point();
+ maxSize = new Point();
+ initView();
+ }
+
+ private void initView() {
+ viewPager = new UltraViewPagerView(getContext());
+ addView(viewPager, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ }
+
+ private void initView(Context context, AttributeSet attrs) {
+ TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.UltraViewPager);
+ setAutoScroll(ta.getInt(R.styleable.UltraViewPager_upv_autoscroll, 0));
+ setInfiniteLoop(ta.getBoolean(R.styleable.UltraViewPager_upv_infiniteloop, false));
+ setRatio(ta.getFloat(R.styleable.UltraViewPager_upv_ratio, Float.NaN));
+ setScrollMode(ScrollMode.getScrollMode(ta.getInt(R.styleable.UltraViewPager_upv_scrollmode, 0)));
+ disableScrollDirection(ScrollDirection.getScrollDirection(ta.getInt(R.styleable.UltraViewPager_upv_disablescroll, 0)));
+ setMultiScreen(ta.getFloat(R.styleable.UltraViewPager_upv_multiscreen, 1f));
+ setAutoMeasureHeight(ta.getBoolean(R.styleable.UltraViewPager_upv_automeasure, false));
+ setItemRatio(ta.getFloat(R.styleable.UltraViewPager_upv_itemratio, Float.NaN));
+ ta.recycle();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ if (!Float.isNaN(ratio)) {
+ int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) (widthSize / ratio), MeasureSpec.EXACTLY);
+ }
+ size.set(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
+ if (maxWidth >= 0 || maxHeight >= 0) {
+ maxSize.set(maxWidth, maxHeight);
+ constrainTo(size, maxSize);
+ widthMeasureSpec = MeasureSpec.makeMeasureSpec(size.x, MeasureSpec.EXACTLY);
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(size.y, MeasureSpec.EXACTLY);
+ }
+ if (viewPager.getConstrainLength() > 0) {
+ if (viewPager.getConstrainLength() == heightMeasureSpec) {
+ viewPager.measure(widthMeasureSpec, heightMeasureSpec);
+ setMeasuredDimension(size.x, size.y);
+ } else {
+ if (viewPager.getScrollMode() == ScrollMode.HORIZONTAL) {
+ super.onMeasure(widthMeasureSpec, viewPager.getConstrainLength());
+ } else {
+ super.onMeasure(viewPager.getConstrainLength(), heightMeasureSpec);
+ }
+ }
+ } else {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ startTimer();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ stopTimer();
+ }
+
+ @Override
+ protected void onVisibilityChanged(View changedView, int visibility) {
+ super.onVisibilityChanged(changedView, visibility);
+ if (visibility == VISIBLE) {
+ startTimer();
+ } else {
+ stopTimer();
+ }
+ }
+
+ @Override
+ public void onStartTemporaryDetach() {
+ super.onStartTemporaryDetach();
+ stopTimer();
+ }
+
+ @Override
+ public void onFinishTemporaryDetach() {
+ super.onFinishTemporaryDetach();
+ startTimer();
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ if (timer != null) {
+ final int action = ev.getAction();
+ if (action == MotionEvent.ACTION_DOWN)
+ timer.isInTouchMode = true;
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL)
+ timer.isInTouchMode = false;
+ }
+ return super.dispatchTouchEvent(ev);
+ }
+
+ @Override
+ public IUltraIndicatorBuilder initIndicator() {
+ disableIndicator();
+ pagerIndicator = new UltraViewPagerIndicator(getContext());
+ pagerIndicator.setViewPager(viewPager);
+ pagerIndicator.setIndicatorBuildListener(new UltraViewPagerIndicator.UltraViewPagerIndicatorListener() {
+ @Override
+ public void build() {
+ removeView(pagerIndicator);
+ addView(pagerIndicator, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ }
+ });
+ return pagerIndicator;
+ }
+
+ @Override
+ public IUltraIndicatorBuilder initIndicator(int focusColor, int normalColor, int radiusInPixel, int gravity) {
+ return initIndicator()
+ .setFocusColor(focusColor)
+ .setNormalColor(normalColor)
+ .setRadius(radiusInPixel)
+ .setGravity(gravity);
+ }
+
+ @Override
+ public IUltraIndicatorBuilder initIndicator(int focusColor, int normalColor, int strokeColor, int strokeWidth, int radiusInPixel, int gravity) {
+ return initIndicator()
+ .setFocusColor(focusColor)
+ .setNormalColor(normalColor)
+ .setStrokeWidth(strokeWidth)
+ .setStrokeColor(strokeColor)
+ .setRadius(radiusInPixel)
+ .setGravity(gravity);
+ }
+
+ @Override
+ public IUltraIndicatorBuilder initIndicator(int focusResId, int normalResId, int gravity) {
+ return initIndicator()
+ .setFocusResId(focusResId)
+ .setNormalResId(normalResId)
+ .setGravity(gravity);
+ }
+
+ @Override
+ public IUltraIndicatorBuilder initIndicator(Bitmap focusBitmap, Bitmap normalBitmap, int gravity) {
+ return initIndicator()
+ .setFocusIcon(focusBitmap)
+ .setNormalIcon(normalBitmap)
+ .setGravity(gravity);
+ }
+
+ @Override
+ public void disableIndicator() {
+ if (pagerIndicator != null) {
+ removeView(pagerIndicator);
+ pagerIndicator = null;
+ }
+ }
+
+ public IUltraIndicatorBuilder getIndicator() {
+ return pagerIndicator;
+ }
+
+ private TimerHandler.TimerHandlerListener mTimerHandlerListener = new TimerHandler.TimerHandlerListener() {
+ @Override
+ public void callBack() {
+ scrollNextPage();
+ }
+ };
+
+ @Override
+ public void setAutoScroll(int intervalInMillis) {
+ if (0 == intervalInMillis)
+ return;
+ if (timer != null) {
+ disableAutoScroll();
+ }
+ timer = new TimerHandler(mTimerHandlerListener, intervalInMillis);
+ startTimer();
+ }
+
+ @Override
+ public void disableAutoScroll() {
+ stopTimer();
+ timer = null;
+ }
+
+ @Override
+ public void setScrollMode(ScrollMode scrollMode) {
+ viewPager.setScrollMode(scrollMode);
+ }
+
+ @Override
+ public void setInfiniteLoop(boolean enableLoop) {
+ viewPager.setEnableLoop(enableLoop);
+ }
+
+ @Override
+ public void setMaxWidth(int width) {
+ maxWidth = width;
+ }
+
+ @Override
+ public void setRatio(float ratio) {
+ this.ratio = ratio;
+ viewPager.setRatio(ratio);
+ }
+
+ @Override
+ public void setMaxHeight(int height) {
+ maxHeight = height;
+ }
+
+ @Override
+ public void disableScrollDirection(UltraViewPager.ScrollDirection direction) {
+
+ }
+
+ @Override
+ public void scrollNextPage() {
+ if (viewPager != null && viewPager.getAdapter() != null && viewPager.getAdapter().getCount() > 0) {
+ final int curr = viewPager.getCurrentItemFake();
+ int nextPage = 0;
+ if (curr < viewPager.getAdapter().getCount() - 1) {
+ nextPage = curr + 1;
+ }
+ viewPager.setCurrentItemFake(nextPage, true);
+ }
+ }
+
+ @Override
+ public void setMultiScreen(float ratio) {
+ if (ratio <= 0 || ratio > 1) {
+ throw new IllegalArgumentException("");
+ }
+ if (ratio <= 1f) {
+ viewPager.setMultiScreen(ratio);
+ }
+ }
+
+ @Override
+ public void setAutoMeasureHeight(boolean status) {
+ viewPager.setAutoMeasureHeight(status);
+ }
+
+ @Override
+ public void setItemRatio(double ratio) {
+ viewPager.setItemRatio(ratio);
+ }
+
+ @Override
+ public void setItemMargin(int left, int top, int right, int bottom) {
+ viewPager.setItemMargin(left, top, right, bottom);
+ }
+
+ @Override
+ public void setScrollMargin(int left, int right) {
+ viewPager.setPadding(left, 0, right, 0);
+ }
+
+ /**
+ * delegate viewpager
+ */
+
+ public void setAdapter(PagerAdapter adapter) {
+ viewPager.setAdapter(adapter);
+ }
+
+ public void setOffscreenPageLimit(int limit) {
+ viewPager.setOffscreenPageLimit(limit);
+ }
+
+ public PagerAdapter getAdapter() {
+ return viewPager.getAdapter() == null ? null : ((UltraViewPagerAdapter) viewPager.getAdapter()).getAdapter();
+ }
+
+ public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
+ if (pagerIndicator == null) {
+ viewPager.setOnPageChangeListener(listener);
+ } else {
+ pagerIndicator.setPageChangeListener(listener);
+ }
+ }
+
+ public void setCurrentItem(int item) {
+ viewPager.setCurrentItem(item);
+ }
+
+ public void setCurrentItem(int item, boolean smoothScroll) {
+ viewPager.setCurrentItem(item, smoothScroll);
+ }
+
+ public int getCurrentItem() {
+ return viewPager.getCurrentItem();
+ }
+
+ public void setPageTransformer(boolean reverseDrawingOrder, ViewPager.PageTransformer transformer) {
+ viewPager.setPageTransformer(reverseDrawingOrder, transformer);
+ }
+
+ public ViewPager getViewPager() {
+ return viewPager;
+ }
+
+ private void constrainTo(Point size, Point maxSize) {
+ if (maxSize.x >= 0) {
+ if (size.x > maxSize.x) {
+ size.x = maxSize.x;
+ }
+ }
+ if (maxSize.y >= 0) {
+ if (size.y > maxSize.y) {
+ size.y = maxSize.y;
+ }
+ }
+ }
+
+ private void startTimer() {
+ if (timer == null)
+ return;
+ timer.listener = mTimerHandlerListener;
+ timer.removeCallbacksAndMessages(null);
+ timer.sendEmptyMessageDelayed(TimerHandler.MSG_TIMER_ID, timer.interval);
+ }
+
+ private void stopTimer() {
+ if (timer == null)
+ return;
+ timer.removeCallbacksAndMessages(null);
+ timer.listener = null;
+ }
+}
diff --git a/ultraviewpager/src/main/java/com/tmall/ultraviewpager/UltraViewPagerAdapter.java b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/UltraViewPagerAdapter.java
new file mode 100644
index 0000000..a048f7f
--- /dev/null
+++ b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/UltraViewPagerAdapter.java
@@ -0,0 +1,265 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager;
+
+import android.database.DataSetObserver;
+import android.os.Parcelable;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.support.v7.widget.RecyclerView;
+import android.util.SparseArray;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RelativeLayout;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Created by mikeafc on 15/11/25.
+ */
+class UltraViewPagerAdapter extends PagerAdapter {
+ interface UltraViewPagerCenterListener {
+ void center();
+
+ void resetPosition();
+ }
+
+ private static final int INFINITE_RATIO = 4;
+ public static final String MULTISCR_TAG = "multi_scr_tag_";
+
+ private PagerAdapter adapter;
+ private boolean enableLoop;
+ private float multiScrRatio = Float.NaN;
+ private boolean hasCentered; //ensure that the first item is in the middle when enabling loop-mode
+ private int scrWidth;
+ private UltraViewPagerCenterListener centerListener;
+
+ private SparseArray viewArray = new SparseArray();
+
+ public UltraViewPagerAdapter(PagerAdapter adapter) {
+ this.adapter = adapter;
+ }
+
+ @Override
+ public int getCount() {
+ int count;
+ if (enableLoop) {
+ if (adapter.getCount() == 0) {
+ count = 0;
+ } else {
+ count = adapter.getCount() *INFINITE_RATIO;
+ }
+ } else {
+ count = adapter.getCount();
+ }
+ return count;
+ }
+
+
+ @Override
+ public Object instantiateItem(ViewGroup container, int position) {
+ int realPosition = position;
+ //TODO
+ if (enableLoop && adapter.getCount() != 0) {
+ realPosition = position % adapter.getCount();
+ }
+
+ Object item = adapter.instantiateItem(container, realPosition);
+ //TODO
+ View childView = null;
+ if (item instanceof View)
+ childView = (View) item;
+ if (item instanceof RecyclerView.ViewHolder)
+ childView = ((RecyclerView.ViewHolder) item).itemView;
+
+ ViewPager viewPager = (ViewPager) container;
+ int childCount = viewPager.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = viewPager.getChildAt(i);
+ if (isViewFromObject(child, item)) {
+ viewArray.put(realPosition, child);
+ break;
+ }
+ }
+
+ if (isEnableMultiScr()) {
+ if (scrWidth == 0) {
+ scrWidth = container.getResources().getDisplayMetrics().widthPixels;
+ }
+ RelativeLayout relativeLayout = new RelativeLayout(container.getContext());
+
+ if (childView.getLayoutParams() != null) {
+ RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
+ (int) (scrWidth * multiScrRatio),
+ ViewGroup.LayoutParams.MATCH_PARENT);
+
+ layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
+ childView.setLayoutParams(layoutParams);
+ }
+
+ container.removeView(childView);
+ relativeLayout.addView(childView);
+
+ container.addView(relativeLayout);
+ return relativeLayout;
+ }
+
+ return item;
+ }
+
+ @Override
+ public void destroyItem(ViewGroup container, int position, Object object) {
+ int realPosition = position;
+
+ //TODO
+ if (enableLoop && adapter.getCount() != 0)
+ realPosition = position % adapter.getCount();
+
+ if (isEnableMultiScr() && object instanceof RelativeLayout) {
+ View child = ((RelativeLayout) object).getChildAt(0);
+ ((RelativeLayout) object).removeAllViews();
+ adapter.destroyItem(container, realPosition, child);
+ } else {
+ adapter.destroyItem(container, realPosition, object);
+ }
+
+ viewArray.remove(realPosition);
+ }
+
+ public View getViewAtPosition(int position) {
+ return (View) viewArray.get(position);
+ }
+
+ @Override
+ public void finishUpdate(ViewGroup container) {
+ // only need to set the center position when the loop is enabled
+ if (!hasCentered) {
+ if (adapter.getCount() > 0 && getCount() > adapter.getCount()) {
+ centerListener.center();
+ }
+ }
+ hasCentered = true;
+ adapter.finishUpdate(container);
+ }
+
+ @Override
+ public boolean isViewFromObject(View view, Object object) {
+ return adapter.isViewFromObject(view, object);
+ }
+
+ @Override
+ public void restoreState(Parcelable bundle, ClassLoader classLoader) {
+ adapter.restoreState(bundle, classLoader);
+ }
+
+ @Override
+ public Parcelable saveState() {
+ return adapter.saveState();
+ }
+
+ @Override
+ public void startUpdate(ViewGroup container) {
+ adapter.startUpdate(container);
+ }
+
+ @Override
+ public CharSequence getPageTitle(int position) {
+ int virtualPosition = position % adapter.getCount();
+ return adapter.getPageTitle(virtualPosition);
+ }
+
+ @Override
+ public float getPageWidth(int position) {
+ return adapter.getPageWidth(position);
+ }
+
+ @Override
+ public void setPrimaryItem(ViewGroup container, int position, Object object) {
+ adapter.setPrimaryItem(container, position, object);
+ }
+
+ @Override
+ public void unregisterDataSetObserver(DataSetObserver observer) {
+ adapter.unregisterDataSetObserver(observer);
+ }
+
+ @Override
+ public void registerDataSetObserver(DataSetObserver observer) {
+ adapter.registerDataSetObserver(observer);
+ }
+
+ @Override
+ public void notifyDataSetChanged() {
+ super.notifyDataSetChanged();
+ adapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public int getItemPosition(Object object) {
+ return adapter.getItemPosition(object);
+ }
+
+ public PagerAdapter getAdapter() {
+ return adapter;
+ }
+
+ public int getRealCount() {
+ return adapter.getCount();
+ }
+
+ void setEnableLoop(boolean status) {
+ this.enableLoop = status;
+ notifyDataSetChanged();
+ if (!status) {
+ centerListener.resetPosition();
+ } else {
+ try {
+ centerListener.center();
+ } catch (Exception e) {
+
+ }
+ }
+
+ }
+
+ boolean isEnableLoop() {
+ return enableLoop;
+ }
+
+ void setMultiScrRatio(float ratio) {
+ multiScrRatio = ratio;
+ }
+
+ boolean isEnableMultiScr() {
+ return !Float.isNaN(multiScrRatio) && multiScrRatio < 1f;
+ }
+
+ void setCenterListener(UltraViewPagerCenterListener listener) {
+ centerListener = listener;
+ }
+}
diff --git a/ultraviewpager/src/main/java/com/tmall/ultraviewpager/UltraViewPagerIndicator.java b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/UltraViewPagerIndicator.java
new file mode 100644
index 0000000..ee0f0ed
--- /dev/null
+++ b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/UltraViewPagerIndicator.java
@@ -0,0 +1,402 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.support.v4.view.ViewPager;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.View;
+/**
+ * Created by mikeafc on 15/11/25.
+ */
+public class UltraViewPagerIndicator extends View implements ViewPager.OnPageChangeListener, IUltraIndicatorBuilder {
+ interface UltraViewPagerIndicatorListener {
+ void build();
+ }
+
+ private UltraViewPagerView viewPager;
+ private ViewPager.OnPageChangeListener pageChangeListener;
+ private int scrollState;
+
+ //attr for custom
+ private int radius;
+ private int indicatorPadding;
+ private boolean animateIndicator;
+ private int gravity;
+ private UltraViewPager.Orientation orientation = UltraViewPager.Orientation.HORIZONTAL;
+
+ private int marginLeft;
+ private int marginTop;
+ private int marginRight;
+ private int marginBottom;
+ //for circle
+ private int focusColor;
+ private int normalColor;
+ //for custom icon
+ private Bitmap focusBitmap;
+ private Bitmap normalBitmap;
+
+ //paint
+ private Paint paintStroke;
+ private Paint paintFill;
+
+ float pageOffset;
+ float defaultRadius;
+
+ //default
+ private static final int DEFAULT_RADIUS = 3;
+
+ private UltraViewPagerIndicatorListener indicatorBuildListener;
+
+ public UltraViewPagerIndicator(Context context) {
+ super(context);
+ init();
+ }
+
+ public UltraViewPagerIndicator(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public UltraViewPagerIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init();
+ }
+
+ private void init() {
+ paintStroke = new Paint(Paint.ANTI_ALIAS_FLAG);
+ paintStroke.setStyle(Paint.Style.STROKE);
+ paintFill = new Paint(Paint.ANTI_ALIAS_FLAG);
+ paintFill.setStyle(Paint.Style.FILL);
+ defaultRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_RADIUS, getResources().getDisplayMetrics());
+ }
+
+ public void setViewPager(UltraViewPagerView viewPager) {
+ this.viewPager = viewPager;
+ this.viewPager.setOnPageChangeListener(this);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (viewPager == null || viewPager.getAdapter() == null)
+ return;
+
+ final int count = ((UltraViewPagerAdapter) viewPager.getAdapter()).getRealCount();
+ if (count == 0)
+ return;
+
+ int longSize;
+ int shortSize;
+
+ int longPaddingBefore;
+ int longPaddingAfter;
+ int shortPaddingBefore;
+ int shortPaddingAfter;
+ if (orientation == UltraViewPager.Orientation.HORIZONTAL) {
+ longSize = viewPager.getWidth();
+ shortSize = viewPager.getHeight();
+ longPaddingBefore = (int) (getItemWidth() + getPaddingLeft() + marginLeft);
+ longPaddingAfter = getPaddingRight() + marginRight;
+ shortPaddingBefore = (int) (getItemWidth() + getPaddingTop() + marginTop);
+ shortPaddingAfter = (int) paintStroke.getStrokeWidth() + getPaddingBottom() + marginBottom;
+ } else {
+ longSize = viewPager.getHeight();
+ shortSize = viewPager.getWidth();
+ longPaddingBefore = (int) (getItemWidth() + getPaddingTop() + marginTop);
+ longPaddingAfter = (int) paintStroke.getStrokeWidth() + getPaddingBottom() + marginBottom;
+ shortPaddingBefore = (int) (getItemWidth() + getPaddingLeft() + marginLeft);
+ shortPaddingAfter = getPaddingRight() + marginRight;
+ }
+
+ final float itemWidth = getItemWidth();
+ final int widthRatio = isDrawResIndicator() ? 1 : 2; //bitmap resource X1 : circle X2
+ if (indicatorPadding == 0) {
+ indicatorPadding = (int) itemWidth;
+ }
+
+ float shortOffset = shortPaddingBefore;
+ float longOffset = longPaddingBefore;
+
+ final float indicatorLength = count * itemWidth * widthRatio + (count - 1) * indicatorPadding;
+
+ final int horizontalGravityMask = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+ final int verticalGravityMask = gravity & Gravity.VERTICAL_GRAVITY_MASK;
+ switch (horizontalGravityMask) {
+ case Gravity.CENTER_HORIZONTAL:
+ longOffset = (longSize - longPaddingBefore - longPaddingAfter - indicatorLength) / 2.0f;
+ break;
+ case Gravity.RIGHT:
+ if (orientation == UltraViewPager.Orientation.HORIZONTAL) {
+ longOffset = longSize - longPaddingAfter - indicatorLength;
+ }
+ if (orientation == UltraViewPager.Orientation.VERTICAL) {
+ shortOffset = shortSize - shortPaddingAfter - itemWidth;
+ }
+ break;
+ case Gravity.LEFT:
+ default:
+ break;
+ }
+
+ switch (verticalGravityMask) {
+ case Gravity.CENTER_VERTICAL:
+ shortOffset = (shortSize - shortPaddingAfter - shortPaddingBefore - itemWidth) / 2;
+ break;
+ case Gravity.BOTTOM:
+ if (orientation == UltraViewPager.Orientation.HORIZONTAL) {
+ shortOffset = shortSize - shortPaddingAfter - getItemHeight();
+ }
+ if (orientation == UltraViewPager.Orientation.VERTICAL) {
+ longOffset = longSize - longPaddingAfter - indicatorLength;
+ }
+ break;
+ case Gravity.TOP:
+ default:
+ break;
+ }
+
+ if (horizontalGravityMask == Gravity.CENTER_HORIZONTAL && verticalGravityMask == Gravity.CENTER_VERTICAL) {
+ shortOffset = (shortSize - shortPaddingAfter - shortPaddingBefore - itemWidth) / 2;
+ }
+
+ float dX;
+ float dY;
+
+ float pageFillRadius = radius;
+ if (paintStroke.getStrokeWidth() > 0) {
+ pageFillRadius -= paintStroke.getStrokeWidth() / 2.0f; //TODO may not/2
+ }
+
+ //Draw stroked circles
+ for (int iLoop = 0; iLoop < count; iLoop++) {
+ float drawLong = longOffset + (iLoop * (itemWidth * widthRatio + indicatorPadding));
+ if (orientation == UltraViewPager.Orientation.HORIZONTAL) {
+ dX = drawLong;
+ dY = shortOffset;
+ } else {
+ dX = shortOffset;
+ dY = drawLong;
+ }
+
+ if (isDrawResIndicator()) {
+ if (iLoop == viewPager.getCurrentItem())
+ continue;
+ canvas.drawBitmap(normalBitmap, dX, dY, paintFill);
+ } else {
+ // Only paint fill if not completely transparent
+ if (paintFill.getAlpha() > 0) {
+ paintFill.setColor(normalColor);
+ canvas.drawCircle(dX, dY, pageFillRadius, paintFill);
+ }
+
+ // Only paint stroke if a stroke width was non-zero
+ if (pageFillRadius != radius) {
+ canvas.drawCircle(dX, dY, radius, paintStroke);
+ }
+ }
+ }
+
+ //Draw the filled circle according to the current scroll
+ float cx = (viewPager.getCurrentItem()) * (itemWidth * widthRatio + indicatorPadding);
+ if (animateIndicator)
+ cx += pageOffset * itemWidth;
+ if (orientation == UltraViewPager.Orientation.HORIZONTAL) {
+ dX = longOffset + cx;
+ dY = shortOffset;
+ } else {
+ dX = shortOffset;
+ dY = longOffset + cx;
+ }
+
+ if (isDrawResIndicator()) {
+ canvas.drawBitmap(focusBitmap, dX, dY, paintStroke);
+ } else {
+ paintFill.setColor(focusColor);
+ canvas.drawCircle(dX, dY, radius, paintFill);
+ }
+ }
+
+ private boolean isDrawResIndicator() {
+ return focusBitmap != null && normalBitmap != null;
+ }
+
+ private float getItemWidth() {
+ if (isDrawResIndicator()) {
+ return Math.max(focusBitmap.getWidth(), normalBitmap.getWidth());
+ }
+ return radius == 0 ? defaultRadius : radius;
+ }
+
+ private float getItemHeight() {
+ if (isDrawResIndicator()) {
+ return Math.max(focusBitmap.getHeight(), normalBitmap.getHeight());
+ }
+ return radius == 0 ? defaultRadius : radius;
+ }
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ pageOffset = positionOffset;
+ invalidate();
+
+ if (pageChangeListener != null) {
+ pageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
+ }
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ if (scrollState == ViewPager.SCROLL_STATE_IDLE) {
+ invalidate();
+ }
+
+ if (pageChangeListener != null) {
+ pageChangeListener.onPageSelected(position);
+ }
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ scrollState = state;
+
+ if (pageChangeListener != null) {
+ pageChangeListener.onPageScrollStateChanged(state);
+ }
+ }
+
+ @Override
+ public IUltraIndicatorBuilder setOrientation(UltraViewPager.Orientation orien) {
+ this.orientation = orien;
+ return this;
+ }
+
+ @Override
+ public IUltraIndicatorBuilder setRadius(int radius) {
+ this.radius = radius;
+ return this;
+ }
+
+ @Override
+ public IUltraIndicatorBuilder setIndicatorPadding(int indicatorPadding) {
+ this.indicatorPadding = indicatorPadding;
+ return this;
+ }
+
+ @Override
+ public IUltraIndicatorBuilder setFocusColor(int focusColor) {
+ this.focusColor = focusColor;
+ return this;
+ }
+
+ @Override
+ public IUltraIndicatorBuilder setNormalColor(int normalColor) {
+ this.normalColor = normalColor;
+ return this;
+ }
+
+ @Override
+ public IUltraIndicatorBuilder setStrokeColor(int strokeColor) {
+ paintStroke.setColor(strokeColor);
+ return this;
+ }
+
+ @Override
+ public IUltraIndicatorBuilder setStrokeWidth(int strokeWidth) {
+ paintStroke.setStrokeWidth(strokeWidth);
+ return this;
+ }
+
+ @Override
+ public IUltraIndicatorBuilder setGravity(int gravity) {
+ this.gravity = gravity;
+ return this;
+ }
+
+ @Override
+ public IUltraIndicatorBuilder setFocusResId(int focusResId) {
+ try {
+ focusBitmap = BitmapFactory.decodeResource(getResources(), focusResId);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public IUltraIndicatorBuilder setNormalResId(int normalResId) {
+ try {
+ normalBitmap = BitmapFactory.decodeResource(getResources(), normalResId);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return this;
+ }
+
+ @Override
+ public IUltraIndicatorBuilder setFocusIcon(Bitmap bitmap) {
+ focusBitmap = bitmap;
+ return this;
+ }
+
+ @Override
+ public IUltraIndicatorBuilder setNormalIcon(Bitmap bitmap) {
+ normalBitmap = bitmap;
+ return this;
+ }
+
+ @Override
+ public IUltraIndicatorBuilder setMargin(int left, int top, int right, int bottom) {
+ marginLeft = left;
+ marginTop = top;
+ marginRight = right;
+ marginBottom = bottom;
+ return this;
+ }
+
+ @Override
+ public void build() {
+ if(indicatorBuildListener != null){
+ indicatorBuildListener.build();
+ }
+ }
+
+ public void setPageChangeListener(ViewPager.OnPageChangeListener pageChangeListener) {
+ this.pageChangeListener = pageChangeListener;
+ }
+
+ public void setIndicatorBuildListener(UltraViewPagerIndicatorListener listener) {
+ this.indicatorBuildListener = listener;
+ }
+}
diff --git a/ultraviewpager/src/main/java/com/tmall/ultraviewpager/UltraViewPagerView.java b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/UltraViewPagerView.java
new file mode 100644
index 0000000..621bb54
--- /dev/null
+++ b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/UltraViewPagerView.java
@@ -0,0 +1,349 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager;
+
+import com.tmall.ultraviewpager.transformer.UltraVerticalTransformer;
+
+import android.content.Context;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Created by mikeafc on 15/11/25.
+ */
+public class UltraViewPagerView extends ViewPager implements UltraViewPagerAdapter.UltraViewPagerCenterListener {
+
+ private UltraViewPagerAdapter pagerAdapter;
+
+ //Internal state to schedule a new measurement pass.
+ private boolean needsMeasurePage;
+
+ private float multiScrRatio = Float.NaN;
+ private boolean enableLoop;
+ private boolean autoMeasureHeight;
+ private double itemRatio = Double.NaN;
+ private int constrainLength;
+
+ private int itemMarginLeft;
+ private int itemMarginTop;
+ private int itemMarginRight;
+ private int itemMarginBottom;
+
+ private float ratio = Float.NaN;
+
+ private UltraViewPager.ScrollMode scrollMode = UltraViewPager.ScrollMode.HORIZONTAL;
+
+ public UltraViewPagerView(Context context) {
+ super(context);
+ init(context, null);
+ }
+
+ public UltraViewPagerView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context, attrs);
+ }
+
+ private void init(Context context, AttributeSet attrs) {
+ setClipChildren(false);
+ setOverScrollMode(OVER_SCROLL_NEVER);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ onMeasurePage(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ protected void onMeasurePage(int widthMeasureSpec, int heightMeasureSpec) {
+ Log.d("TEST","onMeasurePage"+getCurrentItem());
+ View child = pagerAdapter.getViewAtPosition(getCurrentItem());
+ if (child == null) {
+ child = getChildAt(0);
+ }
+ if (child == null) {
+ return;
+ }
+ for (int i = 0; i < getChildCount(); i++) {
+ View view = getChildAt(i);
+ if ((view.getPaddingLeft() != itemMarginLeft ||
+ view.getPaddingTop() != itemMarginTop ||
+ view.getPaddingRight() != itemMarginRight ||
+ view.getPaddingBottom() != itemMarginBottom)) {
+ view.setPadding(itemMarginLeft, itemMarginTop, itemMarginRight, itemMarginBottom);
+ }
+ }
+
+ ViewGroup.LayoutParams lp = child.getLayoutParams();
+ final int childWidthSpec = getChildMeasureSpec(widthMeasureSpec, 0, lp.width);
+ final int childHeightSpec = getChildMeasureSpec(heightMeasureSpec, 0, lp.height);
+
+ int childWidth = (int) ((MeasureSpec.getSize(childWidthSpec) - getPaddingLeft() - getPaddingRight()) * pagerAdapter.getPageWidth(getCurrentItem()));
+ int childHeight = MeasureSpec.getSize(childHeightSpec) - getPaddingTop() - getPaddingBottom();
+
+ if (!needsMeasurePage || childWidth == 0 && childHeight == 0) {
+ return;
+ }
+
+ if (!Double.isNaN(itemRatio)) {
+ int itemHeight = (int) (childWidth / itemRatio);
+ for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
+ View view = getChildAt(i);
+ view.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(itemHeight, MeasureSpec.EXACTLY));
+ }
+ } else {
+ for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
+ View view = getChildAt(i);
+ if (pagerAdapter.getPageWidth(getCurrentItem()) != 1) {
+ view.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+ } else {
+ view.measure(childWidthSpec, childHeightSpec);
+ }
+ }
+ }
+
+ final boolean isHorizontalScroll = scrollMode == UltraViewPager.ScrollMode.HORIZONTAL;
+
+ childWidth = itemMarginLeft + child.getMeasuredWidth() + itemMarginRight;
+ childHeight = itemMarginTop + child.getMeasuredHeight() + itemMarginBottom;
+
+ if (!Float.isNaN(ratio)) {
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) (getMeasuredWidth() / ratio), MeasureSpec.EXACTLY);
+ setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
+ for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
+ View view = getChildAt(i);
+ view.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY), heightMeasureSpec);
+ }
+ } else {
+ if (autoMeasureHeight) {
+ if (isHorizontalScroll) {
+ constrainLength = MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY);
+ setMeasuredDimension(getMeasuredWidth(), childHeight);
+ } else {
+ constrainLength = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY);
+ setMeasuredDimension(childWidth, getMeasuredHeight());
+ }
+
+ needsMeasurePage = childHeight == itemMarginTop + itemMarginBottom;
+ }
+ }
+
+ if (!pagerAdapter.isEnableMultiScr()) {
+ return;
+ }
+
+ int pageLength = isHorizontalScroll ? getMeasuredWidth() : getMeasuredHeight();
+
+ final int childLength = isHorizontalScroll ? child.getMeasuredWidth() : child.getMeasuredHeight();
+
+ // Check that the measurement was successful
+ if (childLength > 0) {
+ needsMeasurePage = false;
+ int difference = pageLength - childLength;
+ if (getPageMargin() == 0) {
+ setPageMargin(-difference);
+ }
+ int offscreen = (int) Math.ceil((float) pageLength / (float) childLength) + 1;
+ setOffscreenPageLimit(offscreen);
+ requestLayout();
+ }
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ // Schedule a new measurement pass as the dimensions have changed
+ needsMeasurePage = true;
+ }
+
+ @Override
+ public void setAdapter(PagerAdapter adapter) {
+ if (adapter != null) {
+ pagerAdapter = new UltraViewPagerAdapter(adapter);
+ pagerAdapter.setCenterListener(this);
+ pagerAdapter.setEnableLoop(enableLoop);
+ pagerAdapter.setMultiScrRatio(multiScrRatio);
+ needsMeasurePage = true;
+ constrainLength = 0;
+ super.setAdapter(pagerAdapter);
+ } else {
+ super.setAdapter(adapter);
+ }
+ }
+
+ @Override
+ public void setCurrentItem(int item) {
+ setCurrentItem(item, false);
+ }
+
+ @Override
+ public void setCurrentItem(int item, boolean smoothScroll) {
+ if (pagerAdapter.getCount() != 0 && pagerAdapter.isEnableLoop()) {
+ item = pagerAdapter.getCount() / 2 + item % pagerAdapter.getRealCount();
+ }
+ super.setCurrentItem(item, smoothScroll);
+ }
+
+ @Override
+ public int getCurrentItem() {
+ if (pagerAdapter.getCount() != 0) {
+ int position = super.getCurrentItem();
+ return position % pagerAdapter.getRealCount();
+ }
+ return super.getCurrentItem();
+ }
+
+
+ /**
+ * 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
+ */
+ void setCurrentItemFake(int item, boolean smoothScroll) {
+ super.setCurrentItem(item, smoothScroll);
+ }
+
+ /**
+ * Get the currently selected page.
+ */
+ int getCurrentItemFake() {
+ return super.getCurrentItem();
+ }
+
+ public void setMultiScreen(float ratio) {
+ multiScrRatio = ratio;
+ if (pagerAdapter != null) {
+ pagerAdapter.setMultiScrRatio(ratio);
+ needsMeasurePage = true;
+ }
+ float pageMargin = (1 - ratio) * getResources().getDisplayMetrics().widthPixels;
+ if(scrollMode == UltraViewPager.ScrollMode.VERTICAL){
+ setPageMargin((int) (pageMargin));
+ }else{
+ setPageMargin((int) (-(pageMargin + convertDp2Px(getContext(), 1f))));
+ }
+
+
+
+ }
+
+ private int convertDp2Px(Context context, float dp) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
+ }
+
+ public void setEnableLoop(boolean status) {
+ enableLoop = status;
+ if (pagerAdapter != null) {
+ pagerAdapter.setEnableLoop(enableLoop);
+ }
+ }
+
+ public void setItemRatio(double itemRatio) {
+ this.itemRatio = itemRatio;
+ }
+
+ public void setAutoMeasureHeight(boolean autoMeasureHeight) {
+ this.autoMeasureHeight = autoMeasureHeight;
+ }
+
+ public void setScrollMode(UltraViewPager.ScrollMode scrollMode) {
+ this.scrollMode = scrollMode;
+ if (scrollMode == UltraViewPager.ScrollMode.VERTICAL)
+ setPageTransformer(false, new UltraVerticalTransformer());
+ }
+
+ public UltraViewPager.ScrollMode getScrollMode() {
+ return scrollMode;
+ }
+
+ public int getConstrainLength() {
+ return constrainLength;
+ }
+
+ public void setItemMargin(int left, int top, int right, int bottom) {
+ itemMarginLeft = left;
+ itemMarginTop = top;
+ itemMarginRight = right;
+ itemMarginBottom = bottom;
+ }
+
+ public float getRatio() {
+ return ratio;
+ }
+
+ public void setRatio(float ratio) {
+ this.ratio = ratio;
+ }
+
+ @Override
+ public void center() {
+ setCurrentItem(0);
+ }
+
+ @Override
+ public void resetPosition() {
+ setCurrentItem(getCurrentItem());
+ }
+
+ private MotionEvent swapTouchEvent(MotionEvent event) {
+ float width = getWidth();
+ float height = getHeight();
+
+ float swappedX = (event.getY() / height) * width;
+ float swappedY = (event.getX() / width) * height;
+
+ event.setLocation(swappedX, swappedY);
+
+ return event;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (scrollMode == UltraViewPager.ScrollMode.VERTICAL) {
+ boolean intercept = super.onInterceptTouchEvent(swapTouchEvent(ev));
+ //If not intercept, touch event should not be swapped.
+ swapTouchEvent(ev);
+ return intercept;
+ }
+ return super.onInterceptTouchEvent(ev);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (scrollMode == UltraViewPager.ScrollMode.VERTICAL)
+ return super.onTouchEvent(swapTouchEvent(ev));
+ return super.onTouchEvent(ev);
+ }
+}
diff --git a/ultraviewpager/src/main/java/com/tmall/ultraviewpager/transformer/UltraDepthScaleTransformer.java b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/transformer/UltraDepthScaleTransformer.java
new file mode 100644
index 0000000..bb0db2a
--- /dev/null
+++ b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/transformer/UltraDepthScaleTransformer.java
@@ -0,0 +1,60 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager.transformer;
+
+import android.support.v4.view.ViewPager;
+import android.view.View;
+
+/**
+ * Created by mikeafc on 15/12/3.
+ */
+public class UltraDepthScaleTransformer implements ViewPager.PageTransformer {
+ private static final float MIN_SCALE = 0.5f;
+ private static final float MAX_ROTATION = 30;
+
+ @Override
+ public void transformPage(View view, float position) {
+ final float scale = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
+ final float rotation = MAX_ROTATION * Math.abs(position);
+
+ if (position <= 0f) {
+ view.setTranslationX(view.getWidth() * -position * 0.19f);
+ view.setPivotY(0.5f * view.getHeight());
+ view.setPivotX(0.5f * view.getWidth());
+ view.setScaleX(scale);
+ view.setScaleY(scale);
+ view.setRotationY(rotation);
+ } else if (position <= 1f) {
+ view.setTranslationX(view.getWidth() * -position * 0.19f);
+ view.setPivotY(0.5f * view.getHeight());
+ view.setPivotX(0.5f * view.getWidth());
+ view.setScaleX(scale);
+ view.setScaleY(scale);
+ view.setRotationY(-rotation);
+ }
+ }
+}
diff --git a/ultraviewpager/src/main/java/com/tmall/ultraviewpager/transformer/UltraScaleTransformer.java b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/transformer/UltraScaleTransformer.java
new file mode 100644
index 0000000..cdea434
--- /dev/null
+++ b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/transformer/UltraScaleTransformer.java
@@ -0,0 +1,59 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager.transformer;
+
+import android.support.v4.view.ViewPager;
+import android.view.View;
+
+/**
+ * Created by mikeafc on 15/12/3.
+ */
+public class UltraScaleTransformer implements ViewPager.PageTransformer {
+ private static final float MIN_SCALE = 0.75f;
+
+ @Override
+ public void transformPage(View page, float position) {
+ final int pageWidth = page.getWidth();
+ final float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
+
+ if (position < 0) { // [-1,0]
+ // Scale the page down (between MIN_SCALE and 1)
+ page.setScaleX(scaleFactor);
+ page.setScaleY(scaleFactor);
+
+ } else if (position == 0) {
+ page.setScaleX(1);
+ page.setScaleY(1);
+
+ } else if (position <= 1) { // (0,1]
+ // Scale the page down (between MIN_SCALE and 1)
+ page.setScaleX(scaleFactor);
+ page.setScaleY(scaleFactor);
+
+ }
+ }
+}
diff --git a/ultraviewpager/src/main/java/com/tmall/ultraviewpager/transformer/UltraVerticalTransformer.java b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/transformer/UltraVerticalTransformer.java
new file mode 100644
index 0000000..1cbfdf4
--- /dev/null
+++ b/ultraviewpager/src/main/java/com/tmall/ultraviewpager/transformer/UltraVerticalTransformer.java
@@ -0,0 +1,48 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager.transformer;
+
+import android.support.v4.view.ViewPager;
+import android.view.View;
+
+/**
+ * Created by mikeafc on 15/11/26.
+ */
+public class UltraVerticalTransformer implements ViewPager.PageTransformer {
+ private float yPosition;
+
+ @Override
+ public void transformPage(View view, float position) {
+ view.setTranslationX(view.getWidth() * -position);
+ yPosition = position * view.getHeight();
+ view.setTranslationY(yPosition);
+ }
+
+ public float getPosition() {
+ return yPosition;
+ }
+}
diff --git a/ultraviewpager/src/main/res/values/attrs.xml b/ultraviewpager/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..c2e896d
--- /dev/null
+++ b/ultraviewpager/src/main/res/values/attrs.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ultraviewpager/src/main/res/values/ids.xml b/ultraviewpager/src/main/res/values/ids.xml
new file mode 100644
index 0000000..f9a48cf
--- /dev/null
+++ b/ultraviewpager/src/main/res/values/ids.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ultraviewpager/src/main/res/values/strings.xml b/ultraviewpager/src/main/res/values/strings.xml
new file mode 100644
index 0000000..893663f
--- /dev/null
+++ b/ultraviewpager/src/main/res/values/strings.xml
@@ -0,0 +1,29 @@
+
+
+
+ UltraViewPager
+
diff --git a/ultraviewpager/src/test/java/com/tmall/ultraviewpager/ExampleUnitTest.java b/ultraviewpager/src/test/java/com/tmall/ultraviewpager/ExampleUnitTest.java
new file mode 100644
index 0000000..70bfc07
--- /dev/null
+++ b/ultraviewpager/src/test/java/com/tmall/ultraviewpager/ExampleUnitTest.java
@@ -0,0 +1,41 @@
+/*
+ *
+ * MIT License
+ *
+ * Copyright (c) 2017 Alibaba Group
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+package com.tmall.ultraviewpager;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * To work on unit tests, switch the Test Artifact in the Build Variants view.
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file