├── .gitignore
├── .idea
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── CHANGELOG.md
├── README.md
├── TestPic
├── demo.gif
├── t1.jpg
├── t2.jpg
├── t3.jpg
├── t4.jpg
├── t5.jpg
└── t6.jpg
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── lib
│ │ └── homhom
│ │ └── psv
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── lib
│ │ │ └── homhom
│ │ │ └── psv
│ │ │ ├── MainActivity.java
│ │ │ └── MyApplication.java
│ └── res
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── lib
│ └── homhom
│ └── psv
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── library-v12
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── homhomlib
│ │ └── lib
│ │ └── v12
│ │ └── parallax
│ │ └── sv
│ │ └── ParallaxSupportView.java
│ └── res
│ └── values
│ └── strings.xml
├── library
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── homhomlib
│ │ └── lib
│ │ └── parallax
│ │ └── sv
│ │ └── ParallaxSupportView.java
│ └── res
│ └── values
│ └── strings.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | v1.0.0
2 | 创建版本
3 |
4 | v1.0.1
5 | 优化性能和效率
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Android-ParallaxSupportView
2 |
3 | Android-ParallaxSupportView是一种Android平台的动态视觉差控件,支持N个任意View的视觉差效果,支持最低API v9。
4 |
5 | Project site: .
6 |
7 | 最新版本:v1.0.1
8 |
9 |
10 | 
11 |
12 | ## 支持平台
13 |
14 | API v9+
15 |
16 | ## 导入项目
17 |
18 | **API v9+:**
19 |
20 | **Gradle dependency:**
21 | ``` groovy
22 | compile 'homhomlin.lib:psv-library:1.0.1'
23 | ```
24 |
25 | or
26 |
27 | **Maven dependency:**
28 | ``` xml
29 |
30 | homhomlin.lib
31 | psv-library
32 | 1.0.1
33 |
34 | ```
35 |
36 | **API v12+:**
37 |
38 | **Gradle dependency:**
39 | ``` groovy
40 | compile 'homhomlin.lib.v12:psv-library:1.0.1'
41 | ```
42 |
43 | or
44 |
45 | **Maven dependency:**
46 | ``` xml
47 |
48 | homhomlin.lib.v12
49 | psv-library
50 | 1.0.1
51 |
52 | ```
53 |
54 | ## 依赖
55 |
56 | 如果你使用的是API v9+的ParallaxSupportView,需要以下依赖:
57 |
58 | ``` groovy
59 | compile 'com.nineoldandroids:library:2.4.0'
60 | ```
61 |
62 | 使用API v12+的ParallaxSupportView不需要依赖。
63 |
64 | ## 用法
65 |
66 | 1.在需要添加的界面xml中添加组件
67 |
68 | ``` xml
69 |
73 | ```
74 |
75 | 2.创建ParallaxProvider
76 |
77 | 与RecyclerView的RecyclerViewAdpater构造方式一致,首先需要一个ParallaxSupportView.ViewHolder,然后再进行Provider的构造,ParallaxSupportView不会重复构建View,以下为最基本的Provider构造。
78 |
79 | ``` java
80 | class ParallaxProvider extends ParallaxSupportView.ParallaxSupportViewProvider{
81 |
82 | class ViewHolder extends ParallaxSupportView.ViewHolder{
83 | public ImageView mImageView;
84 |
85 | public ViewHolder(View itemView) {
86 | super(itemView);
87 | mImageView = (ImageView)itemView;
88 | }
89 | }
90 |
91 | @Override
92 | public ViewHolder onCreateViewHolder(int type) {
93 | ImageView iv = new ImageView(MainActivity.this);
94 | iv.setLayoutParams(new FrameLayout.LayoutParams(
95 | FrameLayout.LayoutParams.MATCH_PARENT,
96 | FrameLayout.LayoutParams.MATCH_PARENT));
97 | iv.setScaleType(ImageView.ScaleType.CENTER_CROP);
98 | return new ViewHolder(htv);
99 | }
100 |
101 | @Override
102 | public void onBindViewHolder(ViewHolder holder, int position) {
103 | holder.mImageView.setBackgroundResource(R.mipmap.ic_launcher);
104 |
105 | }
106 |
107 | @Override
108 | public int getItemCount() {
109 | return 5;
110 | }
111 | }
112 | ```
113 |
114 | 3.在代码中find该组件,并且设置provider。
115 |
116 | ``` java
117 | ParallaxSupportView parallaxSupportView = (ParallaxSupportView) findViewById(R.id.parallaxSv);
118 | parallaxSupportView.setProvider(new ParallaxProvider());
119 | ```
120 |
121 | ## 高级ParallaxSupportView使用
122 |
123 | 1.ParallaxSupportViewProvider
124 |
125 | ParallaxSupportView支持你构建多种不同的View,为了能这么做,你需要重写ParallaxSupportViewProvider中的两个个方法:
126 |
127 | * public int getItemTypeCount();用于返回type类型的数量
128 | * public int getItemType(int position);用于返回type类型
129 |
130 | 2.动画拦截
131 |
132 | ParallaxSupportView支持你对动画进行拦截,你可以实现自己想要的动画特效而不一定使用ParallaxSupportView自带的默认动画,回调的View为当前即将执行动画的View,方法返回真会导致默认动画不会继续执行:
133 |
134 | ``` java
135 | mParallaxSupportView.setAnimInterceptor(new ParallaxSupportView.AnimInterceptor() {
136 | @Override
137 | public boolean anim(View view) {
138 | return false;
139 | }
140 | });
141 | ```
142 |
143 | ## 反馈
144 |
145 | 如果使用上有问题或者需要提交代码,请直接提issue,谢谢。
146 |
147 | ## Developed By
148 |
149 | * Linhonghong -
150 |
151 | ## License
152 | Copyright 2016 LinHongHong
153 |
154 | Licensed under the Apache License, Version 2.0 (the "License");
155 | you may not use this file except in compliance with the License.
156 | You may obtain a copy of the License at
157 |
158 | http://www.apache.org/licenses/LICENSE-2.0
159 |
160 | Unless required by applicable law or agreed to in writing, software
161 | distributed under the License is distributed on an "AS IS" BASIS,
162 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163 | See the License for the specific language governing permissions and
164 | limitations under the License.
165 |
--------------------------------------------------------------------------------
/TestPic/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/2ac97e5126f67ead2111c57adf8dbf3ab94796e1/TestPic/demo.gif
--------------------------------------------------------------------------------
/TestPic/t1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/2ac97e5126f67ead2111c57adf8dbf3ab94796e1/TestPic/t1.jpg
--------------------------------------------------------------------------------
/TestPic/t2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/2ac97e5126f67ead2111c57adf8dbf3ab94796e1/TestPic/t2.jpg
--------------------------------------------------------------------------------
/TestPic/t3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/2ac97e5126f67ead2111c57adf8dbf3ab94796e1/TestPic/t3.jpg
--------------------------------------------------------------------------------
/TestPic/t4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/2ac97e5126f67ead2111c57adf8dbf3ab94796e1/TestPic/t4.jpg
--------------------------------------------------------------------------------
/TestPic/t5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/2ac97e5126f67ead2111c57adf8dbf3ab94796e1/TestPic/t5.jpg
--------------------------------------------------------------------------------
/TestPic/t6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/2ac97e5126f67ead2111c57adf8dbf3ab94796e1/TestPic/t6.jpg
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | applicationId "lib.homhom.psv"
9 | minSdkVersion 12
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | testCompile 'junit:junit:4.12'
25 | compile 'com.android.support:appcompat-v7:23.1.1'
26 |
27 | // compile project(':library')
28 |
29 | compile project(':library-v12')
30 |
31 | compile 'homhomlin.lib:frescoimageview:1.3.0'
32 |
33 | compile 'com.facebook.fresco:fresco:0.9.0'
34 |
35 | compile 'com.nineoldandroids:library:2.4.0'
36 |
37 | // compile 'homhomlin.lib:psv-library:1.0.1'
38 | //
39 | // compile 'homhomlin.lib.v12:psv-library:1.0.1'
40 | }
41 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/Linhh/Develop/Android/android-sdk-macosx/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/lib/homhom/psv/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package lib.homhom.psv;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/java/lib/homhom/psv/MainActivity.java:
--------------------------------------------------------------------------------
1 | package lib.homhom.psv;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.FrameLayout;
7 | import android.widget.ImageView;
8 |
9 | import homhomlib.lib.v12.parallax.sv.ParallaxSupportView;
10 | import lib.lhh.fiv.library.FrescoImageView;
11 |
12 | public class MainActivity extends AppCompatActivity {
13 |
14 | private ParallaxSupportView mParallaxSupportView;
15 | private final static String[] mPic = new String[]{
16 | "https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/master/TestPic/t1.jpg",
17 | "https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/master/TestPic/t2.jpg",
18 | "https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/master/TestPic/t3.jpg",
19 | "https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/master/TestPic/t4.jpg",
20 | "https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/master/TestPic/t5.jpg",
21 | "https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/master/TestPic/t6.jpg"
22 | };
23 |
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | setContentView(R.layout.activity_main);
28 | mParallaxSupportView = (ParallaxSupportView) findViewById(R.id.parallaxSv);
29 | ParallaxProvider provider = new ParallaxProvider();
30 | mParallaxSupportView.setProvider(provider);
31 | mParallaxSupportView.setFadeDuration(2000);
32 | mParallaxSupportView.setAnimInterceptor(new ParallaxSupportView.AnimInterceptor() {
33 | @Override
34 | public boolean anim(View view) {
35 | float fromScale = mParallaxSupportView.pickScale();
36 | float toScale = mParallaxSupportView.pickScale();
37 | view.setScaleX(fromScale);
38 | view.setScaleY(fromScale);
39 | view.animate()
40 | .scaleX(toScale)
41 | .scaleY(toScale)
42 | .setDuration(mParallaxSupportView.getAnimDuration());
43 | return true;
44 | }
45 | });
46 | // provider.notifyDataSetChanged();
47 | }
48 |
49 | class ParallaxProvider extends ParallaxSupportView.ParallaxSupportViewProvider{
50 |
51 | class ViewHolder extends ParallaxSupportView.ViewHolder{
52 | public FrescoImageView mHtv;
53 |
54 | public ViewHolder(View itemView) {
55 | super(itemView);
56 | mHtv = (FrescoImageView)itemView;
57 | }
58 | }
59 |
60 | @Override
61 | public ViewHolder onCreateViewHolder(int type) {
62 | FrescoImageView htv = new FrescoImageView(MainActivity.this);
63 | htv.setLayoutParams(new FrameLayout.LayoutParams(
64 | FrameLayout.LayoutParams.MATCH_PARENT,
65 | FrameLayout.LayoutParams.MATCH_PARENT));
66 | htv.setScaleType(ImageView.ScaleType.CENTER_CROP);
67 | return new ViewHolder(htv);
68 | }
69 |
70 | @Override
71 | public void onBindViewHolder(ViewHolder holder, int position) {
72 | holder.mHtv.loadView(mPic[position], R.mipmap.ic_launcher);
73 |
74 | }
75 |
76 | @Override
77 | public int getItemCount() {
78 | return mPic.length;
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/app/src/main/java/lib/homhom/psv/MyApplication.java:
--------------------------------------------------------------------------------
1 | package lib.homhom.psv;
2 |
3 | import android.app.Application;
4 |
5 | import com.facebook.drawee.backends.pipeline.Fresco;
6 |
7 | /**
8 | * Created by Linhh on 16/3/24.
9 | */
10 | public class MyApplication extends Application{
11 | @Override
12 | public void onCreate() {
13 | super.onCreate();
14 | Fresco.initialize(this);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/2ac97e5126f67ead2111c57adf8dbf3ab94796e1/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/2ac97e5126f67ead2111c57adf8dbf3ab94796e1/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/2ac97e5126f67ead2111c57adf8dbf3ab94796e1/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/2ac97e5126f67ead2111c57adf8dbf3ab94796e1/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/2ac97e5126f67ead2111c57adf8dbf3ab94796e1/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Android-ParallaxSupportView
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/lib/homhom/psv/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package lib.homhom.psv;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2'
10 | classpath "org.jfrog.buildinfo:build-info-extractor-gradle:3.1.1"
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | jcenter()
19 | }
20 | }
21 |
22 | task clean(type: Delete) {
23 | delete rootProject.buildDir
24 | }
25 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | #v9
21 | #PROJ_GROUP=homhomlin.lib
22 | #PROJ_VERSION=1.2.0
23 | #PROJ_NAME=Android-ParallaxSupportView
24 | #PROJ_WEBSITEURL=https://github.com/HomHomLin/Android-ParallaxSupportView
25 | #PROJ_ISSUETRACKERURL=
26 | #PROJ_VCSURL=https://github.com/HomHomLin/Android-ParallaxSupportView.git
27 | #PROJ_DESCRIPTION=/Android-ParallaxSupportView
28 | #PROJ_ARTIFACTID=psv-library
29 | #
30 | #DEVELOPER_ID=homhomlin
31 | #DEVELOPER_NAME=linhonghong
32 | #DEVELOPER_EMAIL=linhh90@163.com
33 |
34 | #v12
35 | PROJ_GROUP=homhomlin.lib.v12
36 | PROJ_VERSION=1.2.1
37 | PROJ_NAME=Android-ParallaxSupportView-v12
38 | PROJ_WEBSITEURL=https://github.com/HomHomLin/Android-ParallaxSupportView
39 | PROJ_ISSUETRACKERURL=
40 | PROJ_VCSURL=https://github.com/HomHomLin/Android-ParallaxSupportView.git
41 | PROJ_DESCRIPTION=/Android-ParallaxSupportView
42 | PROJ_ARTIFACTID=psv-library
43 |
44 | DEVELOPER_ID=homhomlin
45 | DEVELOPER_NAME=linhonghong
46 | DEVELOPER_EMAIL=linhh90@163.com
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HomHomLin/Android-ParallaxSupportView/2ac97e5126f67ead2111c57adf8dbf3ab94796e1/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/library-v12/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/library-v12/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | minSdkVersion 12
9 | targetSdkVersion 23
10 | }
11 | buildTypes {
12 | release {
13 | minifyEnabled false
14 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
15 | }
16 | }
17 | }
18 |
19 | dependencies {
20 | compile fileTree(dir: 'libs', include: ['*.jar'])
21 | testCompile 'junit:junit:4.12'
22 | }
23 |
24 | apply from: 'https://raw.githubusercontent.com/HomHomLin/Gradle-Publish/master/bintray.gradle'
25 |
--------------------------------------------------------------------------------
/library-v12/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/Linhh/Develop/Android/android-sdk-macosx/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/library-v12/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/library-v12/src/main/java/homhomlib/lib/v12/parallax/sv/ParallaxSupportView.java:
--------------------------------------------------------------------------------
1 | package homhomlib.lib.v12.parallax.sv;
2 |
3 | import android.animation.AnimatorSet;
4 | import android.animation.ObjectAnimator;
5 | import android.content.Context;
6 | import android.database.Observable;
7 | import android.os.Handler;
8 | import android.util.AttributeSet;
9 | import android.util.SparseArray;
10 | import android.view.View;
11 | import android.widget.FrameLayout;
12 |
13 | import java.util.Random;
14 |
15 | /**
16 | * Created by Linhh on 16/3/27.
17 | */
18 | public class ParallaxSupportView extends FrameLayout {
19 |
20 | private final Random mRandom = new Random();
21 | // private final Handler mHandler;
22 |
23 | private final ParallaxSupportViewDataObserver mObserver = new ParallaxSupportViewDataObserver();
24 |
25 | private int mIndex = 0;
26 |
27 | private final SparseArray mViewHolders = new SparseArray<>();
28 | private final SparseArray mCopyHolders = new SparseArray<>();
29 |
30 | private boolean mIsAttachedToWindow = false;
31 |
32 | private int mParallaxDuration = 10000;
33 | private int mFadeDuration = 500;
34 |
35 | private float mMaxScaleSize = 1.5F;
36 | private float mMinScaleSize = 1.0F;
37 |
38 | private ParallaxSupportViewProvider mProvider;
39 |
40 | private AnimInterceptor mAnimInterceptor;
41 |
42 | public static abstract class ViewHolder {
43 | public final View itemView;
44 | public ViewHolder(View itemView) {
45 | if (itemView == null) {
46 | throw new IllegalArgumentException("itemView may not be null");
47 | }
48 | this.itemView = itemView;
49 | }
50 | }
51 |
52 | public interface AnimInterceptor{
53 | public boolean anim(View view);
54 | }
55 |
56 | public static abstract class ParallaxSupportViewProvider{
57 |
58 | private final AdapterDataObservable mObservable = new AdapterDataObservable();
59 |
60 | private int mItemTypeCount = 1;
61 |
62 | private final static int NO_TYPE = 0;
63 |
64 | public abstract VH onCreateViewHolder(int type);
65 |
66 | public abstract void onBindViewHolder(VH holder, int position);
67 |
68 | public abstract int getItemCount();
69 |
70 | public int getItemTypeCount(){
71 | return mItemTypeCount;
72 | }
73 |
74 | /**
75 | * 根据pos来确定使用哪个type布局
76 | * @param position
77 | * @return
78 | */
79 | public int getItemType(int position){
80 | return NO_TYPE;
81 | }
82 |
83 | public final VH createViewHolder(int type){
84 | final VH holder = onCreateViewHolder(type);
85 | return holder;
86 | }
87 |
88 | public final void bindViewHolder(VH holder, int position) {
89 | onBindViewHolder(holder, position);
90 | }
91 |
92 | public void notifyDataSetChanged() {
93 | mObservable.notifyChanged();
94 | }
95 |
96 |
97 | public void registerAdapterDataObserver(AdapterDataObserver observer) {
98 | mObservable.registerObserver(observer);
99 | }
100 |
101 | public void unregisterAdapterDataObserver(AdapterDataObserver observer) {
102 | mObservable.unregisterObserver(observer);
103 | }
104 |
105 |
106 | public final boolean hasObservers() {
107 | return mObservable.hasObservers();
108 | }
109 |
110 | }
111 |
112 | public ParallaxSupportView(Context context) {
113 | this(context, null);
114 | }
115 |
116 | public ParallaxSupportView(Context context, AttributeSet attrs) {
117 | this(context, attrs, 0);
118 | }
119 |
120 | public ParallaxSupportView(Context context, AttributeSet attrs, int defStyle) {
121 | super(context, attrs, defStyle);
122 | // mHandler = new Handler();
123 | }
124 |
125 | public void setProvider(ParallaxSupportViewProvider provider){
126 |
127 | if (mProvider != null) {
128 | mProvider.unregisterAdapterDataObserver(mObserver);
129 | }
130 |
131 | mProvider = provider;
132 |
133 | if (mProvider != null) {
134 | mProvider.registerAdapterDataObserver(mObserver);
135 | }
136 |
137 | viewsInvalid();
138 | }
139 |
140 | public void setAnimInterceptor(AnimInterceptor animInterceptor){
141 | mAnimInterceptor = animInterceptor;
142 | }
143 |
144 | public ParallaxSupportViewProvider getProvider(){
145 | return mProvider;
146 | }
147 |
148 | private Runnable mParallaxImageRunnable = new Runnable() {
149 | @Override
150 | public void run() {
151 | swapImage();
152 | ParallaxSupportView.this.postDelayed(mParallaxImageRunnable, mParallaxDuration);
153 | }
154 | };
155 |
156 | @Override
157 | public void onWindowFocusChanged(boolean hasWindowFocus) {
158 | super.onWindowFocusChanged(hasWindowFocus);
159 | }
160 |
161 | private void swapImage() {
162 |
163 | if(mProvider == null){
164 | return;
165 | }
166 |
167 | if(mProvider.getItemCount() <= 0){
168 | return;
169 | }
170 |
171 | if(this.getChildCount() > 1)
172 | this.removeViewAt(0);
173 |
174 | int type = mProvider.getItemType(mIndex);
175 |
176 | ViewHolder viewHolder = mViewHolders.get(type);
177 |
178 | if(viewHolder.itemView.getParent() == null) {
179 | mProvider.bindViewHolder(viewHolder, mIndex);
180 | this.addView(viewHolder.itemView);
181 | }else{
182 | // if(mCopyHolders == null){
183 | // mCopyHolders = new SparseArray<>();
184 | // }
185 | ViewHolder copy_viewHolder = mCopyHolders.get(type);
186 | if(copy_viewHolder == null){
187 | copy_viewHolder = mProvider.createViewHolder(type);
188 | mCopyHolders.put(type , copy_viewHolder);
189 | }
190 | mProvider.bindViewHolder(copy_viewHolder, mIndex);
191 | this.addView(copy_viewHolder.itemView);
192 | }
193 |
194 | mIndex = (1 + mIndex) % mProvider.getItemCount();
195 |
196 | View oldView = this.getChildAt(0);
197 | View newView = this.getChildAt(1);
198 |
199 | if(newView == null){
200 | //没有新图,说明是第一次
201 | animate(oldView);
202 | return;
203 | }
204 |
205 | newView.setAlpha(0.0F);
206 | // oldView.setAlpha(1.0F);
207 | //
208 | // newView.animate()
209 | // .alpha(1.0F)
210 | // .setDuration(mFadeDuration);
211 | // oldView.animate()
212 | // .alpha(0.0F)
213 | // .setDuration(mFadeDuration);
214 |
215 | animate(newView);
216 |
217 | AnimatorSet animatorSet = new AnimatorSet();
218 | animatorSet.setDuration(mFadeDuration);
219 | animatorSet.playTogether(
220 | ObjectAnimator.ofFloat(oldView, "alpha", 1.0F, 0.0F),
221 | ObjectAnimator.ofFloat(newView, "alpha", 0.0F, 1.0F)
222 | );
223 | animatorSet.start();
224 |
225 | }
226 |
227 | public void setFadeDuration(int duration){
228 | mFadeDuration = duration;
229 | }
230 |
231 | public int getFadeDuration(){
232 | return mFadeDuration;
233 | }
234 |
235 | public void setParallaxDuration(int duration){
236 | mParallaxDuration = duration;
237 | }
238 |
239 | public int getParallaxDuration(){
240 | return mParallaxDuration;
241 | }
242 |
243 | public void setMinScaleSize(int minScaleSize){
244 | mMinScaleSize = minScaleSize;
245 | }
246 |
247 | public void setMaxScaleSize(int maxScaleSize){
248 | mMaxScaleSize = maxScaleSize;
249 | }
250 |
251 | private void startParallax(View view, long duration, float fromScale, float toScale, float fromTranslationX, float fromTranslationY, float toTranslationX, float toTranslationY) {
252 | view.setScaleX(fromScale);
253 | view.setScaleY(fromScale);
254 | view.setTranslationX(fromTranslationX);
255 | view.setTranslationY(fromTranslationY);
256 | view.animate()
257 | .translationX(toTranslationX)
258 | .translationY(toTranslationY)
259 | .scaleX(toScale)
260 | .scaleY(toScale)
261 | .setDuration(duration);
262 | }
263 |
264 | public final float pickScale() {
265 | return mMinScaleSize + mRandom.nextFloat() * (mMaxScaleSize - mMinScaleSize);
266 | }
267 |
268 | public final float pickTranslation(int value, float ratio) {
269 | return value * (ratio - 1.0F) * (mRandom.nextFloat() - 0.5F);
270 | }
271 |
272 | private void animate(View view) {
273 | if(view == null){
274 | return;
275 | }
276 | if(mAnimInterceptor != null && mAnimInterceptor.anim(view)){
277 | return;
278 | }
279 | float fromScale = pickScale();
280 | float toScale = pickScale();
281 | float fromTranslationX = pickTranslation(view.getWidth(), fromScale);
282 | // if(fromTranslationX == 0){
283 | // fromTranslationX = -70;//默认
284 | // }
285 |
286 | float fromTranslationY = pickTranslation(view.getHeight(), fromScale);
287 | // if(fromTranslationY == 0){
288 | // fromTranslationY = -20;//默认
289 | // }
290 | float toTranslationX = pickTranslation(view.getWidth(), toScale);
291 | // if(toTranslationX == 0){
292 | // toTranslationX = 60;
293 | // }
294 | float toTranslationY = pickTranslation(view.getHeight(), toScale);
295 | // if(toTranslationY == 0){
296 | // toTranslationY = 40;
297 | // }
298 | startParallax(view, mParallaxDuration - mFadeDuration * 2, fromScale, toScale, fromTranslationX, fromTranslationY, toTranslationX, toTranslationY);
299 | }
300 |
301 | public int getAnimDuration(){
302 | return mParallaxDuration - mFadeDuration * 2;
303 | }
304 |
305 | @Override
306 | protected void onDetachedFromWindow() {
307 | super.onDetachedFromWindow();
308 | mIsAttachedToWindow = false;
309 | release();
310 | }
311 |
312 | private void release() {
313 | mAnimInterceptor = null;
314 | mProvider = null;
315 | this.removeCallbacks(mParallaxImageRunnable);
316 | if(mCopyHolders != null){
317 | for(int i = 0; i < mCopyHolders.size(); i ++){
318 | mCopyHolders.get(i).itemView.clearAnimation();
319 | }
320 | mCopyHolders.clear();
321 | // mCopyHolders = null;
322 | }
323 | if(mViewHolders != null){
324 | for(int i = 0; i < mViewHolders.size(); i ++){
325 | mViewHolders.get(i).itemView.clearAnimation();
326 | }
327 | mViewHolders.clear();
328 | // mViewHolders = null;
329 | }
330 | }
331 |
332 | @Override
333 | protected void onAttachedToWindow() {
334 | super.onAttachedToWindow();
335 | mIsAttachedToWindow = true;
336 | }
337 |
338 | private void viewsInvalid() {
339 |
340 | this.removeCallbacks(mParallaxImageRunnable);
341 |
342 | if(this.getChildCount() > 0){
343 | this.removeAllViews();
344 | }
345 |
346 | if(mProvider == null){
347 | throw new IllegalArgumentException("provider may not be null");
348 | }
349 |
350 | if(mViewHolders != null){
351 | mViewHolders.clear();
352 | }
353 |
354 | if(mCopyHolders != null){
355 | mCopyHolders.clear();
356 | }
357 |
358 | // if(mViewHolders == null){
359 | // mViewHolders = new SparseArray<>();
360 | // }
361 |
362 | for (int type = 0; type < mProvider.getItemTypeCount(); type ++ ){
363 | ViewHolder viewHolder = mProvider.createViewHolder(type);
364 | // if(mViewHolders == null){
365 | // mViewHolders = new SparseArray<>();
366 | // }
367 |
368 | mViewHolders.put(type, viewHolder);
369 | }
370 |
371 | this.post(mParallaxImageRunnable);
372 | }
373 |
374 | public static abstract class AdapterDataObserver {
375 | public void onChanged() {
376 | }
377 | }
378 |
379 | private class ParallaxSupportViewDataObserver extends AdapterDataObserver {
380 | @Override
381 | public void onChanged() {
382 | //refersh View
383 | viewsInvalid();
384 | }
385 | }
386 |
387 | static class AdapterDataObservable extends Observable {
388 |
389 | public boolean hasObservers() {
390 | return !mObservers.isEmpty();
391 | }
392 |
393 | public void notifyChanged() {
394 | for (int i = mObservers.size() - 1; i >= 0; i--) {
395 | mObservers.get(i).onChanged();
396 | }
397 | }
398 | }
399 | }
400 |
401 |
--------------------------------------------------------------------------------
/library-v12/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | library-v12
3 |
4 |
--------------------------------------------------------------------------------
/library/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | minSdkVersion 9
9 | targetSdkVersion 23
10 | }
11 | buildTypes {
12 | release {
13 | minifyEnabled false
14 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
15 | }
16 | }
17 | }
18 |
19 | dependencies {
20 | compile fileTree(dir: 'libs', include: ['*.jar'])
21 | testCompile 'junit:junit:4.12'
22 | compile 'com.android.support:appcompat-v7:23.1.1'
23 |
24 | compile 'com.nineoldandroids:library:2.4.0'
25 | }
26 |
27 | apply from: 'https://raw.githubusercontent.com/HomHomLin/Gradle-Publish/master/bintray.gradle'
28 |
--------------------------------------------------------------------------------
/library/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/Linhh/Develop/Android/android-sdk-macosx/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/library/src/main/java/homhomlib/lib/parallax/sv/ParallaxSupportView.java:
--------------------------------------------------------------------------------
1 | package homhomlib.lib.parallax.sv;
2 |
3 | import android.content.Context;
4 | import android.database.Observable;
5 | import android.os.Handler;
6 | import android.util.AttributeSet;
7 | import android.util.Log;
8 | import android.util.SparseArray;
9 | import android.view.View;
10 | import android.widget.FrameLayout;
11 |
12 | import com.nineoldandroids.animation.Animator;
13 | import com.nineoldandroids.animation.AnimatorSet;
14 | import com.nineoldandroids.animation.ObjectAnimator;
15 | import com.nineoldandroids.view.ViewHelper;
16 | import com.nineoldandroids.view.ViewPropertyAnimator;
17 |
18 | import java.util.Random;
19 |
20 | /**
21 | * Created by Linhh on 16/3/22.
22 | */
23 | public class ParallaxSupportView extends FrameLayout {
24 | private final Random mRandom = new Random();
25 | // private final Handler mHandler;
26 |
27 | private final ParallaxSupportViewDataObserver mObserver = new ParallaxSupportViewDataObserver();
28 |
29 | private int mIndex = 0;
30 |
31 | private final SparseArray mViewHolders = new SparseArray<>();
32 | private final SparseArray mCopyHolders = new SparseArray<>();
33 |
34 | private boolean mIsAttachedToWindow = false;
35 |
36 | private int mParallaxDuration = 10000;
37 | private int mFadeDuration = 500;
38 |
39 | private float mMaxScaleSize = 1.5F;
40 | private float mMinScaleSize = 1.0F;
41 |
42 | private ParallaxSupportViewProvider mProvider;
43 |
44 | private AnimInterceptor mAnimInterceptor;
45 |
46 | public static abstract class ViewHolder {
47 | public final View itemView;
48 | public ViewHolder(View itemView) {
49 | if (itemView == null) {
50 | throw new IllegalArgumentException("itemView may not be null");
51 | }
52 | this.itemView = itemView;
53 | }
54 | }
55 |
56 | public interface AnimInterceptor{
57 | public boolean anim(View view);
58 | }
59 |
60 | public static abstract class ParallaxSupportViewProvider{
61 |
62 | private final AdapterDataObservable mObservable = new AdapterDataObservable();
63 |
64 | private int mItemTypeCount = 1;
65 |
66 | private final static int NO_TYPE = 0;
67 |
68 | public abstract VH onCreateViewHolder(int type);
69 |
70 | public abstract void onBindViewHolder(VH holder, int position);
71 |
72 | public abstract int getItemCount();
73 |
74 | public int getItemTypeCount(){
75 | return mItemTypeCount;
76 | }
77 |
78 | /**
79 | * 根据pos来确定使用哪个type布局
80 | * @param position
81 | * @return
82 | */
83 | public int getItemType(int position){
84 | return NO_TYPE;
85 | }
86 |
87 | public final VH createViewHolder(int type){
88 | final VH holder = onCreateViewHolder(type);
89 | return holder;
90 | }
91 |
92 | public final void bindViewHolder(VH holder, int position) {
93 | onBindViewHolder(holder, position);
94 | }
95 |
96 | public void notifyDataSetChanged() {
97 | mObservable.notifyChanged();
98 | }
99 |
100 |
101 | public void registerAdapterDataObserver(AdapterDataObserver observer) {
102 | mObservable.registerObserver(observer);
103 | }
104 |
105 | public void unregisterAdapterDataObserver(AdapterDataObserver observer) {
106 | mObservable.unregisterObserver(observer);
107 | }
108 |
109 |
110 | public final boolean hasObservers() {
111 | return mObservable.hasObservers();
112 | }
113 |
114 | }
115 |
116 | public ParallaxSupportView(Context context) {
117 | this(context, null);
118 | }
119 |
120 | public ParallaxSupportView(Context context, AttributeSet attrs) {
121 | this(context, attrs, 0);
122 | }
123 |
124 | public ParallaxSupportView(Context context, AttributeSet attrs, int defStyle) {
125 | super(context, attrs, defStyle);
126 | }
127 |
128 | public void setProvider(ParallaxSupportViewProvider provider){
129 |
130 | if (mProvider != null) {
131 | mProvider.unregisterAdapterDataObserver(mObserver);
132 | }
133 |
134 | mProvider = provider;
135 |
136 | if (mProvider != null) {
137 | mProvider.registerAdapterDataObserver(mObserver);
138 | }
139 |
140 | viewsInvalid();
141 | }
142 |
143 | public void setAnimInterceptor(AnimInterceptor animInterceptor){
144 | mAnimInterceptor = animInterceptor;
145 | }
146 |
147 | public ParallaxSupportViewProvider getProvider(){
148 | return mProvider;
149 | }
150 |
151 | private Runnable mParallaxImageRunnable = new Runnable() {
152 | @Override
153 | public void run() {
154 | swapImage();
155 | ParallaxSupportView.this.postDelayed(mParallaxImageRunnable, mParallaxDuration);
156 | }
157 | };
158 |
159 | @Override
160 | public void onWindowFocusChanged(boolean hasWindowFocus) {
161 | super.onWindowFocusChanged(hasWindowFocus);
162 | }
163 |
164 | private void swapImage() {
165 |
166 | if(mProvider == null){
167 | return;
168 | }
169 |
170 | if(mProvider.getItemCount() <= 0){
171 | return;
172 | }
173 |
174 | if(this.getChildCount() > 1)
175 | this.removeViewAt(0);
176 |
177 | int type = mProvider.getItemType(mIndex);
178 |
179 | ViewHolder viewHolder = mViewHolders.get(type);
180 |
181 | if(viewHolder.itemView.getParent() == null) {
182 | mProvider.bindViewHolder(viewHolder, mIndex);
183 | this.addView(viewHolder.itemView);
184 | }else{
185 | ViewHolder copy_viewHolder = mCopyHolders.get(type);
186 | if(copy_viewHolder == null){
187 | copy_viewHolder = mProvider.createViewHolder(type);
188 | mCopyHolders.put(type , copy_viewHolder);
189 | }
190 | mProvider.bindViewHolder(copy_viewHolder, mIndex);
191 | this.addView(copy_viewHolder.itemView);
192 | }
193 |
194 | mIndex = (1 + mIndex) % mProvider.getItemCount();
195 |
196 | View oldView = this.getChildAt(0);
197 | View newView = this.getChildAt(1);
198 |
199 | if(newView == null){
200 | //没有新图,说明是第一次
201 | animate(oldView);
202 | return;
203 | }
204 |
205 |
206 | animate(newView);
207 | ViewHelper.setAlpha(newView, 0.0F);
208 | ViewHelper.setAlpha(oldView, 1.0F);
209 |
210 | ViewPropertyAnimator new_propertyAnimator = ViewPropertyAnimator
211 | .animate(newView)
212 | .alpha(1.0F)
213 | .setDuration(mFadeDuration);
214 |
215 | new_propertyAnimator.start();
216 |
217 | ViewPropertyAnimator old_propertyAnimator = ViewPropertyAnimator
218 | .animate(oldView)
219 | .alpha(0.0F)
220 | .setDuration(mFadeDuration);
221 |
222 | old_propertyAnimator.start();
223 | // AnimatorSet animatorSet = new AnimatorSet();
224 | // animatorSet.setDuration(mFadeDuration);
225 | // animatorSet.playTogether(
226 | // ObjectAnimator.ofFloat(oldView, "alpha", 1.0F, 0.0F),
227 | // ObjectAnimator.ofFloat(newView, "alpha", 0.0F, 1.0F)
228 | // );
229 | // animatorSet.addListener(new Animator.AnimatorListener() {
230 | // @Override
231 | // public void onAnimationStart(Animator animation) {
232 | // Log.d("anim-psv","start");
233 | // }
234 | //
235 | // @Override
236 | // public void onAnimationEnd(Animator animation) {
237 | // Log.d("anim-psv","over");
238 | // }
239 | //
240 | // @Override
241 | // public void onAnimationCancel(Animator animation) {
242 | //
243 | // }
244 | //
245 | // @Override
246 | // public void onAnimationRepeat(Animator animation) {
247 | //
248 | // }
249 | // });
250 | // animatorSet.start();
251 | }
252 |
253 | public void setFadeDuration(int duration){
254 | mFadeDuration = duration;
255 | }
256 |
257 | public int getFadeDuration(){
258 | return mFadeDuration;
259 | }
260 |
261 | public void setParallaxDuration(int duration){
262 | mParallaxDuration = duration;
263 | }
264 |
265 | public int getParallaxDuration(){
266 | return mParallaxDuration;
267 | }
268 |
269 | public void setMinScaleSize(int minScaleSize){
270 | mMinScaleSize = minScaleSize;
271 | }
272 |
273 | public void setMaxScaleSize(int maxScaleSize){
274 | mMaxScaleSize = maxScaleSize;
275 | }
276 |
277 | private void startParallax(View view, long duration, float fromScale, float toScale, float fromTranslationX, float fromTranslationY, float toTranslationX, float toTranslationY) {
278 | ViewHelper.setScaleX(view, fromScale);
279 | ViewHelper.setScaleY(view, fromScale);
280 | ViewHelper.setTranslationX(view, fromTranslationX);
281 | ViewHelper.setTranslationY(view, fromTranslationY);
282 | ViewPropertyAnimator propertyAnimator = ViewPropertyAnimator
283 | .animate(view)
284 | .translationX(toTranslationX)
285 | .translationY(toTranslationY)
286 | .scaleX(toScale)
287 | .scaleY(toScale)
288 | .setDuration(duration);
289 |
290 | propertyAnimator.start();
291 | }
292 |
293 | private float pickScale() {
294 | return mMinScaleSize + mRandom.nextFloat() * (mMaxScaleSize - mMinScaleSize);
295 | }
296 |
297 | private float pickTranslation(int value, float ratio) {
298 | return value * (ratio - 1.0F) * (mRandom.nextFloat() - 0.5F);
299 | }
300 |
301 | private void animate(View view) {
302 | if(view == null){
303 | return;
304 | }
305 | if(mAnimInterceptor != null && mAnimInterceptor.anim(view)){
306 | return;
307 | }
308 | float fromScale = pickScale();
309 | float toScale = pickScale();
310 | float fromTranslationX = pickTranslation(view.getWidth(), fromScale);
311 | // if(fromTranslationX == 0){
312 | // fromTranslationX = -70;//默认
313 | // }
314 |
315 | float fromTranslationY = pickTranslation(view.getHeight(), fromScale);
316 | // if(fromTranslationY == 0){
317 | // fromTranslationY = -20;//默认
318 | // }
319 | float toTranslationX = pickTranslation(view.getWidth(), toScale);
320 | // if(toTranslationX == 0){
321 | // toTranslationX = 60;
322 | // }
323 | float toTranslationY = pickTranslation(view.getHeight(), toScale);
324 | // if(toTranslationY == 0){
325 | // toTranslationY = 40;
326 | // }
327 | startParallax(view, mParallaxDuration - 2 * mFadeDuration, fromScale, toScale, fromTranslationX, fromTranslationY, toTranslationX, toTranslationY);
328 | }
329 |
330 | @Override
331 | protected void onDetachedFromWindow() {
332 | super.onDetachedFromWindow();
333 | mIsAttachedToWindow = false;
334 | release();
335 | }
336 |
337 | private void release() {
338 | mAnimInterceptor = null;
339 | mProvider = null;
340 | this.removeCallbacks(mParallaxImageRunnable);
341 | if(mCopyHolders != null){
342 | for(int i = 0; i < mCopyHolders.size(); i ++){
343 | mCopyHolders.get(i).itemView.clearAnimation();
344 | }
345 | mCopyHolders.clear();
346 | // mCopyHolders = null;
347 | }
348 | if(mViewHolders != null){
349 | for(int i = 0; i < mViewHolders.size(); i ++){
350 | mViewHolders.get(i).itemView.clearAnimation();
351 | }
352 | mViewHolders.clear();
353 | // mViewHolders = null;
354 | }
355 | }
356 |
357 | @Override
358 | protected void onAttachedToWindow() {
359 | super.onAttachedToWindow();
360 | mIsAttachedToWindow = true;
361 | }
362 |
363 | private void viewsInvalid() {
364 |
365 | this.removeCallbacks(mParallaxImageRunnable);
366 |
367 | if(this.getChildCount() > 0){
368 | this.removeAllViews();
369 | }
370 |
371 | if(mProvider == null){
372 | throw new IllegalArgumentException("provider may not be null");
373 | }
374 |
375 | if(mViewHolders != null){
376 | mViewHolders.clear();
377 | }
378 |
379 | if(mCopyHolders != null){
380 | mCopyHolders.clear();
381 | }
382 |
383 | for (int type = 0; type < mProvider.getItemTypeCount(); type ++ ){
384 | ViewHolder viewHolder = mProvider.createViewHolder(type);
385 | mViewHolders.put(type, viewHolder);
386 | }
387 |
388 | this.post(mParallaxImageRunnable);
389 | }
390 |
391 | public static abstract class AdapterDataObserver {
392 | public void onChanged() {
393 | }
394 | }
395 |
396 | private class ParallaxSupportViewDataObserver extends AdapterDataObserver {
397 | @Override
398 | public void onChanged() {
399 | //refersh View
400 | viewsInvalid();
401 | }
402 | }
403 |
404 | static class AdapterDataObservable extends Observable{
405 |
406 | public boolean hasObservers() {
407 | return !mObservers.isEmpty();
408 | }
409 |
410 | public void notifyChanged() {
411 | for (int i = mObservers.size() - 1; i >= 0; i--) {
412 | mObservers.get(i).onChanged();
413 | }
414 | }
415 | }
416 | }
417 |
418 |
--------------------------------------------------------------------------------
/library/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Library
3 |
4 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':library-v12'
2 |
--------------------------------------------------------------------------------