├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── bg_parallax_pager.png
├── build.gradle
├── example
├── build.gradle
├── proguard-rules.txt
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ └── Bitter-Bold.ttf
│ ├── java
│ ├── com
│ │ └── prolificinteractive
│ │ │ └── parallaxproject
│ │ │ ├── ParallaxActivity.java
│ │ │ ├── ParallaxFragment.java
│ │ │ └── SampleApplication.java
│ └── uk
│ │ └── co
│ │ └── chrisjenx
│ │ └── calligraphy
│ │ └── OpenCalligraphyFactory.java
│ └── res
│ ├── drawable-hdpi
│ └── ic_launcher.png
│ ├── drawable-xhdpi
│ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ ├── earth.jpg
│ ├── ic_launcher.png
│ ├── jupiter.jpg
│ ├── mars.jpg
│ ├── mercury.jpg
│ ├── neptune.jpg
│ ├── saturn.jpg
│ ├── uranus.jpg
│ └── venus.jpg
│ ├── layout
│ ├── activity_parallax.xml
│ ├── fragment_parallax.xml
│ ├── parallax_view_1.xml
│ ├── parallax_view_2.xml
│ ├── parallax_view_3.xml
│ └── parallax_view_4.xml
│ └── values
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── gradle.properties
├── gradle
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── parallaxpager
├── build.gradle
├── proguard-rules.txt
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── prolificinteractive
│ │ └── parallaxpager
│ │ ├── OnViewCreatedListener.java
│ │ ├── ParallaxContainer.java
│ │ ├── ParallaxContextWrapper.java
│ │ ├── ParallaxFactory.java
│ │ ├── ParallaxLayoutInflater.java
│ │ ├── ParallaxPagerAdapter.java
│ │ ├── ParallaxViewTag.java
│ │ └── ReflectionUtils.java
│ └── res
│ └── values
│ ├── attrs.xml
│ └── ids.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | .DS_Store
3 |
4 | # android
5 | gen
6 | bin
7 | obj
8 |
9 | # gradle
10 | build
11 | .gradle
12 |
13 | # intellij
14 | .idea
15 | *.iml
16 |
17 | # eclipse
18 | local.properties
19 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Change Log
2 | ==========
3 | Version 2.2.2 *(2018-5-3)*
4 | ----------------------------
5 |
6 | * Upgrade: Gradle file
7 | * Upgrade: Moved to Jitpack
8 | * Updated: ReadMe
9 |
10 | Version 2.2.0 *(2015-02-23)*
11 | ----------------------------
12 |
13 | * New: added `override_visibility` attribute to allow for overriding the default visibility behaviour.
14 | When false, it will act as it has; true will not change the visibility of the View at all,
15 | leaving it to the implementer.
16 |
17 |
18 | Version 2.1.0 *(2015-02-19)*
19 | ----------------------------
20 |
21 | * New: `ParallaxContainer.setOnPageChangeListener()` to access page change events of the
22 | underlying ViewPager. This means that `ParallaxContainer.attachOnPageChangeListener()` is now
23 | deprecated. You should use the listener setter from above.
24 | * New: `ParallaxContainer.getViewPager()` to allow access to the underlying ViewPager for
25 | existing code that relies on having a ViewPager instance.
26 |
27 |
28 | Version 2.0.0 *(2015-02-17)*
29 | ----------------------------
30 |
31 | * Release should be mostly backwards compatible with v1.0.0, but the sweeping changes to the
32 | subsystem merited a major bump.
33 | * Bugfix: Fix targeting API v21
34 | * New: Ability to add custom listeners to the View creation process.
35 | This is to help work around an issue with trying to have multiple ContextWrappers meddle with
36 | the view creation process. See sample project for Calligraphy example.
37 |
38 |
39 | Version 1.0.0
40 | -------------
41 |
42 | * Start of ChangeLog
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2018 Prolific Interactive.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Parallax Pager
4 | [](https://android-arsenal.com/details/1/537)
5 | [](https://jitpack.io/#prolificinteractive/ParallaxPager)
6 |
7 |
8 | Add some depth to your Android scrolling using the parallax effect!
9 |
10 | ## Installation
11 |
12 | Step 1. Add the JitPack repository to your build file
13 |
14 | ```groovy
15 | allprojects {
16 | repositories {
17 | ...
18 | maven { url 'https://jitpack.io' }
19 | }
20 | }
21 | ```
22 |
23 | Step 2. Add the dependency
24 |
25 | ```groovy
26 | dependencies {
27 | implementation 'com.github.prolificinteractive:parallaxpager:${parallaxpagerVersion}'
28 | }
29 | ```
30 |
31 | ## Usage
32 |
33 |
34 | There are 4 important steps:
35 |
36 | 1. Use a `ParallaxContainer` in layout XML
37 |
38 | 2. Create a layout XML file for each page
39 |
40 | 3. Wrap the Activity Context
41 |
42 | 4. Add the attachment code to `onCreate` of your Activity or `onCreateView` of your Fragment
43 |
44 |
45 | ## 1. Use a `ParallaxContainer` in layout XML
46 |
47 | Use the class `com.prolificinteractive.parallaxpager.ParallaxContainer` in your layout XML, sizing it however you like.
48 |
49 | Ex:
50 |
51 | ```xml
52 |
56 | ```
57 |
58 |
59 | ## 2. Create a layout XML file for each page
60 |
61 | Each page must have its own layout XML file. Use whichever Layouts or Views you like, as usual.
62 |
63 | Ensure this line is added to the Root Element:
64 |
65 | >xmlns:app="http://schemas.android.com/apk/res-auto"
66 |
67 | Assign any combination of the following attributes (all floats):
68 |
69 | * `x_in`: as the View **enters** the screen, it will translate in the horizontal direction along with user swiping, at a rate multiplied by this value. Default is `0`.
70 |
71 | * `x_out`: as the View **leaves** the screen, it will translate in the horizontal direction along with user swiping, at a rate multiplied by this value. Default is `0`.
72 |
73 | * `y_in`: as the View **enters** the screen, it will translate **downward** as the user swipes right to left, at a rate multiplied by this value. Default is `0`.
74 |
75 | * `y_out`: as the View **leaves** the screen, it will translate **upward** as the user swipes right to left, at a rate multiplied by this value. Default is `0`.
76 |
77 | * `a_in`: as the View **enters** the screen, it will **fade in** as the user swipes right to left, at a rate multiplied by this value. Default is `0`.
78 |
79 | * `a_out`: as the View **leaves** the screen, it will **fade out** as the user swipes right to left, at a rate multiplied by this value. Default is `0`.
80 |
81 | Ex:
82 |
83 | ```xml
84 |
85 |
90 |
91 |
102 |
103 |
114 |
115 | ```
116 |
117 | Keep in mind that negative values mean a change in direction for translation effects, and have no effect for alpha. For translation effects, values between `0` and `1` will result in a high level of funkiness.
118 |
119 |
120 | ## 3. Wrap the Activity Context
121 | Wrap the activity context using `com.prolificinteractive.parallaxpager.ParallaxContextWrapper` in your activity.
122 |
123 | Ex:
124 |
125 | ```java
126 | @Override
127 | protected void attachBaseContext(Context newBase) {
128 | super.attachBaseContext(new ParallaxContextWrapper(newBase));
129 | }
130 | ```
131 |
132 | **Note**: If you are using this in conjunction with another library that wraps Context, it doesn't appear to like chaining them together.
133 | Instead, we've added the ability to hook into the View creation process to use with other libraries.
134 | The sample project shows how to hook into Calligraphy.
135 |
136 | Ex:
137 |
138 | ```java
139 | @Override
140 | protected void attachBaseContext(Context newBase) {
141 | super.attachBaseContext(
142 | new ParallaxContextWrapper(newBase, new OnViewCreatedListener() {
143 | @Override public View onViewCreated(View view, Context context, AttributeSet attrs) {
144 | //Setup view as needed
145 | return view; //Return the view passed in
146 | }
147 | })
148 | );
149 | }
150 | ```
151 |
152 |
153 | ## 4. Add the attachment code to `onCreate` of your Activity or `onCreateView` of your Fragment
154 |
155 | Important steps in `onCreate` of an Activity (or `onCreateView` of a Fragment):
156 |
157 | * Find the parallax container by ID
158 |
159 | * Specify whether the pager should loop (`true` means it *will* loop)
160 |
161 | * Submit a **Layout Inflater** and list the layouts for each page (in order). Currently there must be at least 2 in this list (repeats allowed).
162 |
163 | Ex:
164 |
165 | ```java
166 | // find the parallax container
167 | ParallaxContainer parallaxContainer = (ParallaxContainer) findViewById(R.id.parallax_container);
168 |
169 | // specify whether pager will loop
170 | parallaxContainer.setLooping(true);
171 |
172 | // wrap the inflater and inflate children with custom attributes
173 | parallaxContainer.setupChildren(getLayoutInflater(),
174 | R.layout.parallax_view_1,
175 | R.layout.parallax_view_2,
176 | R.layout.parallax_view_3,
177 | R.layout.parallax_view_4);
178 | ```
179 |
180 | Extras
181 | ======
182 |
183 | ## Extra 1. Setting a `ViewPager.OnPageChangeListener`
184 |
185 | You can set a `ViewPager.OnPageChangeListener` after the attachment code in step 4.
186 |
187 | ```java
188 | // optionally set a ViewPager.OnPageChangeListener
189 | parallaxContainer.setOnPageChangeListener(this);
190 | ```
191 |
192 | ## Extra 2. `ViewPager` access
193 |
194 | You have access to the `ViewPager` by calling:
195 |
196 | ```java
197 | parallaxContainer.getViewPager();
198 | ```
199 |
200 | This is exposed for use with existing code which requires a `ViewPager` instance. Please make sure that if you call methods like `setAdapter` or `setOnPageChangeListener` on the instance returned, that you do so with forethought and good reason.
201 |
202 | ## Extra 3. Overriding parallax visibility
203 |
204 | Parallax views will be `VISIBLE` when onscreen, and `GONE` when offscreen. If you need to override this behavior, set this attribute on your View in XML:
205 |
206 | ```xml
207 | app:override_visibility="true"
208 | ```
209 |
210 |
211 | ## Contributing
212 |
213 | To report a bug or enhancement request, feel free to file an issue under the respective heading. If you wish to contribute to the project, fork this repo and submit a pull request.
214 |
215 |
216 | Code contributions should follow the standards specified in the [Prolific Android Code Style](https://github.com/prolificinteractive/android-code-styles).
217 |
218 |
219 | ## License
220 |
221 | 
222 |
223 | Copyright (c) 2018 Prolific Interactive
224 |
225 | Parallax Pager is maintained and sponsored by Prolific Interactive. It may be redistributed under the terms specified in the [LICENSE] file.
226 |
227 | [LICENSE]: ./LICENSE
228 |
--------------------------------------------------------------------------------
/bg_parallax_pager.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prolificinteractive/ParallaxPager/1e76f85cf20e7cf9fa36247a3ebedd60495f057e/bg_parallax_pager.png
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | google()
6 | jcenter()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.1.2'
10 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/example/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 | group='com.github.prolificinteractive'
4 | android {
5 | compileSdkVersion 27
6 | buildToolsVersion "23.0.3"
7 |
8 | defaultConfig {
9 | minSdkVersion 16
10 | targetSdkVersion 27
11 | versionCode 1
12 | versionName version
13 | }
14 |
15 | compileOptions {
16 | sourceCompatibility JavaVersion.VERSION_1_7
17 | targetCompatibility JavaVersion.VERSION_1_7
18 | }
19 | }
20 |
21 | dependencies {
22 | implementation project(':parallaxpager')
23 | implementation 'uk.co.chrisjenx:calligraphy:2.3.0'
24 | implementation 'com.android.support:appcompat-v7:27.1.1'
25 | }
26 |
--------------------------------------------------------------------------------
/example/proguard-rules.txt:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Applications/Android Studio.app/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the ProGuard
5 | # include property in project.properties.
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 | #}
--------------------------------------------------------------------------------
/example/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/example/src/main/assets/Bitter-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prolificinteractive/ParallaxPager/1e76f85cf20e7cf9fa36247a3ebedd60495f057e/example/src/main/assets/Bitter-Bold.ttf
--------------------------------------------------------------------------------
/example/src/main/java/com/prolificinteractive/parallaxproject/ParallaxActivity.java:
--------------------------------------------------------------------------------
1 | package com.prolificinteractive.parallaxproject;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.support.v7.app.AppCompatActivity;
6 |
7 | import com.prolificinteractive.parallaxpager.ParallaxContextWrapper;
8 |
9 | import uk.co.chrisjenx.calligraphy.OpenCalligraphyFactory;
10 |
11 | public class ParallaxActivity extends AppCompatActivity {
12 |
13 | @Override protected void attachBaseContext(Context newBase) {
14 | //ParallaxPager and Calligraphy don't seem to play nicely together
15 | //The solution was to add a listener for view creation events so that we can hook up
16 | // Calligraphy to our view creation calls instead.
17 | super.attachBaseContext(
18 | new ParallaxContextWrapper(newBase, new OpenCalligraphyFactory())
19 | );
20 | }
21 |
22 | ////Normal Usage
23 | //@Override protected void attachBaseContext(Context newBase) {
24 | // super.attachBaseContext(new ParallaxContextWrapper(newBase));
25 | //}
26 |
27 | @Override
28 | protected void onCreate(Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | setContentView(R.layout.activity_parallax);
31 |
32 | if (savedInstanceState == null) {
33 | getSupportFragmentManager().beginTransaction()
34 | .add(R.id.content, new ParallaxFragment())
35 | .commit();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/example/src/main/java/com/prolificinteractive/parallaxproject/ParallaxFragment.java:
--------------------------------------------------------------------------------
1 | package com.prolificinteractive.parallaxproject;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.Fragment;
5 | import android.support.v4.view.ViewPager;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.ImageView;
10 | import android.widget.Toast;
11 | import com.prolificinteractive.parallaxpager.ParallaxContainer;
12 |
13 | public class ParallaxFragment extends Fragment implements ViewPager.OnPageChangeListener {
14 |
15 | ImageView mEarthImageView;
16 |
17 | @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,
18 | Bundle savedInstanceState) {
19 |
20 | View view = inflater.inflate(R.layout.fragment_parallax, container, false);
21 |
22 | // find the parallax container
23 | ParallaxContainer parallaxContainer =
24 | (ParallaxContainer) view.findViewById(R.id.parallax_container);
25 |
26 | // specify whether pager will loop
27 | parallaxContainer.setLooping(true);
28 |
29 | // wrap the inflater and inflate children with custom attributes
30 | parallaxContainer.setupChildren(inflater,
31 | R.layout.parallax_view_1,
32 | R.layout.parallax_view_2,
33 | R.layout.parallax_view_3,
34 | R.layout.parallax_view_4);
35 |
36 | // optionally set a ViewPager.OnPageChangeListener
37 | parallaxContainer.setOnPageChangeListener(this);
38 |
39 | view.findViewById(R.id.btn_new_frag).setOnClickListener(new View.OnClickListener() {
40 | @Override public void onClick(View v) {
41 | getFragmentManager().beginTransaction()
42 | .replace(R.id.content, new Fragment())
43 | .addToBackStack("test")
44 | .commit();
45 | }
46 | });
47 |
48 | // Earth ImageView has `override_visibility` set to `true` so we need to manually manage visibility
49 | mEarthImageView = (ImageView) view.findViewById(R.id.imageview_earth);
50 |
51 | return view;
52 | }
53 |
54 | @Override public void onPageScrolled(int position, float offset, int offsetPixels) {
55 | // example of manually setting view visibility
56 | if (position == 1 && offset > 0.2) {
57 | // just before leaving the screen, Earth will disappear
58 | mEarthImageView.setVisibility(View.INVISIBLE);
59 | } else if (position == 0 || position == 1) {
60 | mEarthImageView.setVisibility(View.VISIBLE);
61 | } else {
62 | mEarthImageView.setVisibility(View.GONE);
63 | }
64 | }
65 |
66 | @Override public void onPageSelected(int position) {
67 | Toast.makeText(getActivity(), "Page Selected: " + position, Toast.LENGTH_SHORT).show();
68 | }
69 |
70 | @Override public void onPageScrollStateChanged(int state) {
71 |
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/example/src/main/java/com/prolificinteractive/parallaxproject/SampleApplication.java:
--------------------------------------------------------------------------------
1 | package com.prolificinteractive.parallaxproject;
2 |
3 | import android.app.Application;
4 | import uk.co.chrisjenx.calligraphy.CalligraphyConfig;
5 |
6 | public class SampleApplication extends Application {
7 |
8 | @Override public void onCreate() {
9 | super.onCreate();
10 |
11 | CalligraphyConfig.initDefault(
12 | new CalligraphyConfig.Builder()
13 | .setDefaultFontPath("Bitter-Bold.ttf")
14 | .build()
15 | );
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/example/src/main/java/uk/co/chrisjenx/calligraphy/OpenCalligraphyFactory.java:
--------------------------------------------------------------------------------
1 | package uk.co.chrisjenx.calligraphy;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.View;
6 | import com.prolificinteractive.parallaxpager.OnViewCreatedListener;
7 |
8 | /**
9 | * {@linkplain uk.co.chrisjenx.calligraphy.CalligraphyFactory} is a package local class,
10 | * so in order to get access to the
11 | * {@linkplain #onViewCreated(android.view.View, android.content.Context, android.util.AttributeSet)}
12 | * we need to subclass this in the same package.
13 | * This also implements {@linkplain com.prolificinteractive.parallaxpager.OnViewCreatedListener} as
14 | * a convenience.
15 | */
16 | public class OpenCalligraphyFactory extends CalligraphyFactory implements OnViewCreatedListener {
17 |
18 | public OpenCalligraphyFactory() {
19 | super(CalligraphyConfig.get().getAttrId());
20 | }
21 |
22 | public OpenCalligraphyFactory(int attributeId) {
23 | super(attributeId);
24 | }
25 |
26 | @Override
27 | public View onViewCreated(View view, Context context, AttributeSet attrs) {
28 | return super.onViewCreated(view, context, attrs);
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/example/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prolificinteractive/ParallaxPager/1e76f85cf20e7cf9fa36247a3ebedd60495f057e/example/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prolificinteractive/ParallaxPager/1e76f85cf20e7cf9fa36247a3ebedd60495f057e/example/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/drawable-xxhdpi/earth.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prolificinteractive/ParallaxPager/1e76f85cf20e7cf9fa36247a3ebedd60495f057e/example/src/main/res/drawable-xxhdpi/earth.jpg
--------------------------------------------------------------------------------
/example/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prolificinteractive/ParallaxPager/1e76f85cf20e7cf9fa36247a3ebedd60495f057e/example/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/drawable-xxhdpi/jupiter.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prolificinteractive/ParallaxPager/1e76f85cf20e7cf9fa36247a3ebedd60495f057e/example/src/main/res/drawable-xxhdpi/jupiter.jpg
--------------------------------------------------------------------------------
/example/src/main/res/drawable-xxhdpi/mars.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prolificinteractive/ParallaxPager/1e76f85cf20e7cf9fa36247a3ebedd60495f057e/example/src/main/res/drawable-xxhdpi/mars.jpg
--------------------------------------------------------------------------------
/example/src/main/res/drawable-xxhdpi/mercury.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prolificinteractive/ParallaxPager/1e76f85cf20e7cf9fa36247a3ebedd60495f057e/example/src/main/res/drawable-xxhdpi/mercury.jpg
--------------------------------------------------------------------------------
/example/src/main/res/drawable-xxhdpi/neptune.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prolificinteractive/ParallaxPager/1e76f85cf20e7cf9fa36247a3ebedd60495f057e/example/src/main/res/drawable-xxhdpi/neptune.jpg
--------------------------------------------------------------------------------
/example/src/main/res/drawable-xxhdpi/saturn.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prolificinteractive/ParallaxPager/1e76f85cf20e7cf9fa36247a3ebedd60495f057e/example/src/main/res/drawable-xxhdpi/saturn.jpg
--------------------------------------------------------------------------------
/example/src/main/res/drawable-xxhdpi/uranus.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prolificinteractive/ParallaxPager/1e76f85cf20e7cf9fa36247a3ebedd60495f057e/example/src/main/res/drawable-xxhdpi/uranus.jpg
--------------------------------------------------------------------------------
/example/src/main/res/drawable-xxhdpi/venus.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prolificinteractive/ParallaxPager/1e76f85cf20e7cf9fa36247a3ebedd60495f057e/example/src/main/res/drawable-xxhdpi/venus.jpg
--------------------------------------------------------------------------------
/example/src/main/res/layout/activity_parallax.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/example/src/main/res/layout/fragment_parallax.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
17 |
18 |
24 |
25 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/example/src/main/res/layout/parallax_view_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
21 |
22 |
32 |
33 |
44 |
45 |
56 |
57 |
--------------------------------------------------------------------------------
/example/src/main/res/layout/parallax_view_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
24 |
25 |
32 |
33 |
41 |
42 |
52 |
53 |
54 |
55 |
56 |
68 |
69 |
79 |
80 |
--------------------------------------------------------------------------------
/example/src/main/res/layout/parallax_view_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
21 |
22 |
32 |
33 |
45 |
46 |
56 |
57 |
--------------------------------------------------------------------------------
/example/src/main/res/layout/parallax_view_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
20 |
21 |
33 |
34 |
44 |
45 |
57 |
58 |
--------------------------------------------------------------------------------
/example/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 20sp
4 | 10dp
5 |
6 | - 2.5
7 | - 5.0
8 | - 10.0
9 | - 20.0
10 |
11 | - -2.5
12 | - -5.0
13 | - -10.0
14 |
--------------------------------------------------------------------------------
/example/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Parallax
4 | Planets!
5 | Mercury
6 | Venus
7 | Earth
8 | (Home)
9 | Mars
10 | Jupiter
11 | Saturn
12 | Uranus
13 | Neptune
14 |
--------------------------------------------------------------------------------
/example/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Settings specified in this file will override any Gradle settings
5 | # configured through the IDE.
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
--------------------------------------------------------------------------------
/gradle/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prolificinteractive/ParallaxPager/1e76f85cf20e7cf9fa36247a3ebedd60495f057e/gradle/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Jan 27 10:07:30 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-bin.zip
7 |
--------------------------------------------------------------------------------
/gradle/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 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradle/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 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prolificinteractive/ParallaxPager/1e76f85cf20e7cf9fa36247a3ebedd60495f057e/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/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 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
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 Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/parallaxpager/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 |
4 | group = 'com.github.prolificinteractive'
5 |
6 | android {
7 | compileSdkVersion 27
8 | buildToolsVersion "27.0.3"
9 |
10 | defaultConfig {
11 | minSdkVersion 16
12 | targetSdkVersion 27
13 | versionCode 1
14 | versionName version
15 | }
16 | }
17 |
18 | dependencies {
19 | testImplementation 'junit:junit:4.12'
20 | implementation 'com.android.support:appcompat-v7:27.1.1'
21 | }
--------------------------------------------------------------------------------
/parallaxpager/proguard-rules.txt:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Applications/Android Studio.app/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the ProGuard
5 | # include property in project.properties.
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 | #}
--------------------------------------------------------------------------------
/parallaxpager/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/parallaxpager/src/main/java/com/prolificinteractive/parallaxpager/OnViewCreatedListener.java:
--------------------------------------------------------------------------------
1 | package com.prolificinteractive.parallaxpager;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.View;
6 |
7 | /**
8 | * A listener for view creation
9 | */
10 | public interface OnViewCreatedListener {
11 | /**
12 | * Called when a View is created in the LayoutInflater
13 | * @param view View created
14 | * @param context Context
15 | * @param attrs View attributes
16 | * @return The same view that is passed in. This is mostly to match up with Calligraphy
17 | */
18 | View onViewCreated(View view, Context context, AttributeSet attrs);
19 | }
20 |
--------------------------------------------------------------------------------
/parallaxpager/src/main/java/com/prolificinteractive/parallaxpager/ParallaxContainer.java:
--------------------------------------------------------------------------------
1 | package com.prolificinteractive.parallaxpager;
2 |
3 | import android.content.Context;
4 | import android.support.v4.view.ViewPager;
5 | import android.util.AttributeSet;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.FrameLayout;
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
14 |
15 | @SuppressWarnings("UnusedDeclaration")
16 | public class ParallaxContainer extends FrameLayout implements ViewPager.OnPageChangeListener {
17 |
18 | private List parallaxViews = new ArrayList<>();
19 | private ViewPager viewPager;
20 | private int pageCount = 0;
21 | private int containerWidth;
22 | private boolean isLooping = false;
23 | private final ParallaxPagerAdapter adapter;
24 | private ViewPager.OnPageChangeListener pageChangeListener;
25 |
26 | public ParallaxContainer(Context context) {
27 | this(context, null);
28 | }
29 |
30 | public ParallaxContainer(Context context, AttributeSet attrs) {
31 | this(context, attrs, 0);
32 | }
33 |
34 | public ParallaxContainer(Context context, AttributeSet attrs, int defStyle) {
35 | super(context, attrs, defStyle);
36 |
37 | adapter = new ParallaxPagerAdapter(context);
38 | }
39 |
40 | @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
41 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
42 | containerWidth = getMeasuredWidth();
43 | }
44 |
45 | public void setLooping(boolean looping) {
46 | isLooping = looping;
47 | updateAdapterCount();
48 | }
49 |
50 | private void updateAdapterCount() {
51 | adapter.setCount(isLooping ? Integer.MAX_VALUE : pageCount);
52 | }
53 |
54 | public void setupChildren(int... childIds) {
55 | setupChildren(LayoutInflater.from(getContext()), childIds);
56 | }
57 |
58 | public void setupChildren(LayoutInflater inflater, int... childIds) {
59 | if (getChildCount() > 0) {
60 | throw new RuntimeException(
61 | "setupChildren should only be called once when ParallaxContainer is empty");
62 | }
63 |
64 | if (childIds.length == 1) {
65 | int id = childIds[0];
66 | childIds = new int[2];
67 | childIds[0] = id;
68 | childIds[1] = id;
69 | }
70 |
71 | for (int childId : childIds) {
72 | inflater.inflate(childId, this);
73 | }
74 |
75 | // hold pageCount because it will change after we add viewpager
76 | pageCount = getChildCount();
77 | for (int i = 0; i < pageCount; i++) {
78 | View view = getChildAt(i);
79 | addParallaxView(view, i);
80 | }
81 |
82 | updateAdapterCount();
83 |
84 | // make view pager with same attributes as container
85 | viewPager = new ViewPager(getContext());
86 | viewPager.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
87 | viewPager.setId(R.id.parallax_pager);
88 | viewPager.setAdapter(adapter);
89 | attachOnPageChangeListener(viewPager, this);
90 |
91 | addView(viewPager, 0);
92 | }
93 |
94 | /**
95 | * Sets the {@link ViewPager.OnPageChangeListener} to the embedded {@link ViewPager}
96 | * created by the container.
97 | *
98 | * This method can be overridden to add an page indicator to the parallax view. If
99 | * this method is overriden, make sure that the listener methods are called on this
100 | * class as well.
101 | */
102 | @Deprecated
103 | protected void attachOnPageChangeListener(ViewPager viewPager,
104 | ViewPager.OnPageChangeListener listener) {
105 | viewPager.setOnPageChangeListener(listener);
106 | }
107 |
108 | // attach attributes in tag
109 | private void addParallaxView(View view, int pageIndex) {
110 | if (view instanceof ViewGroup) {
111 | // recurse children
112 | ViewGroup viewGroup = (ViewGroup) view;
113 | for (int i = 0, childCount = viewGroup.getChildCount(); i < childCount; i++) {
114 | addParallaxView(viewGroup.getChildAt(i), pageIndex);
115 | }
116 | }
117 |
118 | ParallaxViewTag tag = (ParallaxViewTag) view.getTag(R.id.parallax_view_tag);
119 | if (tag != null) {
120 | // only track view if it has a parallax tag
121 | tag.index = pageIndex;
122 | parallaxViews.add(view);
123 | }
124 | }
125 |
126 | /**
127 | * NOTE: this is exposed for use with existing code which requires a {@linkplain android.support.v4.view.ViewPager} instance.
128 | * Please make sure that if you call methods like {@linkplain android.support.v4.view.ViewPager#setAdapter(android.support.v4.view.PagerAdapter) setAdapter()}
129 | * or {@linkplain android.support.v4.view.ViewPager#setOnPageChangeListener(android.support.v4.view.ViewPager.OnPageChangeListener) setOnPageChangeListener()}
130 | * on the instance returned, that you do so with forethought and good reason.
131 | *
132 | * @return the internal ViewPager, null before {@linkplain #setupChildren(int...) setupChildren()} is called
133 | */
134 | public ViewPager getViewPager() {
135 | return viewPager;
136 | }
137 |
138 | /**
139 | * Set a listener to recieve page change events
140 | * @see android.support.v4.view.ViewPager#setOnPageChangeListener(android.support.v4.view.ViewPager.OnPageChangeListener)
141 | * @param pageChangeListener the listener, or null to clear
142 | */
143 | public void setOnPageChangeListener(ViewPager.OnPageChangeListener pageChangeListener) {
144 | this.pageChangeListener = pageChangeListener;
145 | }
146 |
147 | @Override public void onPageScrolled(int pageIndex, float offset, int offsetPixels) {
148 | if (pageCount > 0) {
149 | pageIndex = pageIndex % pageCount;
150 | }
151 |
152 | ParallaxViewTag tag;
153 | for (View view : parallaxViews) {
154 | tag = (ParallaxViewTag) view.getTag(R.id.parallax_view_tag);
155 | if (tag == null) { continue; }
156 |
157 | if ((pageIndex == tag.index - 1
158 | || (isLooping && (pageIndex == tag.index - 1 + pageCount)))
159 | && containerWidth != 0) {
160 |
161 | if (!tag.overrideVisibility) {
162 | // make visible
163 | view.setVisibility(VISIBLE);
164 | }
165 |
166 | // slide in from right
167 | view.setTranslationX((containerWidth - offsetPixels) * tag.xIn);
168 |
169 | // slide in from top
170 | view.setTranslationY(0 - (containerWidth - offsetPixels) * tag.yIn);
171 |
172 | // fade in
173 | view.setAlpha(1.0f - (containerWidth - offsetPixels) * tag.alphaIn / containerWidth);
174 | } else if (pageIndex == tag.index) {
175 | if (!tag.overrideVisibility) {
176 | // make visible
177 | view.setVisibility(VISIBLE);
178 | }
179 |
180 | // slide out to left
181 | view.setTranslationX(0 - offsetPixels * tag.xOut);
182 |
183 | // slide out to top
184 | view.setTranslationY(0 - offsetPixels * tag.yOut);
185 |
186 | // fade out
187 | view.setAlpha(1.0f - offsetPixels * tag.alphaOut / containerWidth);
188 | } else {
189 | if (!tag.overrideVisibility) {
190 | view.setVisibility(GONE);
191 | }
192 | }
193 | }
194 |
195 | if (pageChangeListener != null) {
196 | pageChangeListener.onPageScrolled(pageIndex, offset, offsetPixels);
197 | }
198 | }
199 |
200 | @Override public void onPageSelected(int position) {
201 | if (pageChangeListener != null) {
202 | pageChangeListener.onPageSelected(position);
203 | }
204 | }
205 |
206 | @Override public void onPageScrollStateChanged(int i) {
207 | if (pageChangeListener != null) {
208 | pageChangeListener.onPageScrollStateChanged(i);
209 | }
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/parallaxpager/src/main/java/com/prolificinteractive/parallaxpager/ParallaxContextWrapper.java:
--------------------------------------------------------------------------------
1 | package com.prolificinteractive.parallaxpager;
2 |
3 | import android.content.Context;
4 | import android.content.ContextWrapper;
5 | import android.view.LayoutInflater;
6 |
7 | public class ParallaxContextWrapper extends ContextWrapper {
8 |
9 | private ParallaxLayoutInflater inflater;
10 |
11 | private final ParallaxFactory mFactory;
12 |
13 | public ParallaxContextWrapper(Context base, OnViewCreatedListener... onViewCreatedListener) {
14 | super(base);
15 | mFactory = new ParallaxFactory(onViewCreatedListener);
16 | }
17 |
18 | @Override
19 | public Object getSystemService(String name) {
20 | if (LAYOUT_INFLATER_SERVICE.equals(name)) {
21 | if (inflater == null) {
22 | inflater = new ParallaxLayoutInflater(
23 | LayoutInflater.from(getBaseContext()),
24 | this,
25 | mFactory);
26 | inflater.setUpLayoutFactories();
27 | }
28 | return inflater;
29 | }
30 | return super.getSystemService(name);
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/parallaxpager/src/main/java/com/prolificinteractive/parallaxpager/ParallaxFactory.java:
--------------------------------------------------------------------------------
1 | package com.prolificinteractive.parallaxpager;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.util.AttributeSet;
6 | import android.view.View;
7 | import java.util.Arrays;
8 | import java.util.List;
9 |
10 | public class ParallaxFactory {
11 |
12 | private final List otherListeners;
13 |
14 | public ParallaxFactory(OnViewCreatedListener... others) {
15 | otherListeners = Arrays.asList(others);
16 | }
17 |
18 | /**
19 | * Handle the created view
20 | *
21 | * @param view nullable.
22 | * @param context shouldn't be null.
23 | * @param attrs shouldn't be null.
24 | * @return null if null is passed in.
25 | */
26 |
27 | public View onViewCreated(View view, Context context, AttributeSet attrs) {
28 | if (view == null) {
29 | return null;
30 | }
31 |
32 | view = onViewCreatedInternal(view, context, attrs);
33 | for (OnViewCreatedListener listener : otherListeners) {
34 | if (listener != null) {
35 | view = listener.onViewCreated(view, context, attrs);
36 | }
37 | }
38 | return view;
39 | }
40 |
41 | private View onViewCreatedInternal(View view, final Context context, AttributeSet attrs) {
42 |
43 | int[] attrIds =
44 | { R.attr.a_in, R.attr.a_out, R.attr.x_in, R.attr.x_out, R.attr.y_in, R.attr.y_out, R.attr.override_visibility };
45 |
46 | TypedArray a = context.obtainStyledAttributes(attrs, attrIds);
47 |
48 | if (a != null) {
49 | if (a.length() > 0) {
50 | ParallaxViewTag tag = new ParallaxViewTag();
51 | tag.alphaIn = a.getFloat(0, 0f);
52 | tag.alphaOut = a.getFloat(1, 0f);
53 | tag.xIn = a.getFloat(2, 0f);
54 | tag.xOut = a.getFloat(3, 0f);
55 | tag.yIn = a.getFloat(4, 0f);
56 | tag.yOut = a.getFloat(5, 0f);
57 | tag.overrideVisibility = a.getBoolean(6, false);
58 | view.setTag(R.id.parallax_view_tag, tag);
59 | }
60 | a.recycle();
61 | }
62 |
63 | return view;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/parallaxpager/src/main/java/com/prolificinteractive/parallaxpager/ParallaxLayoutInflater.java:
--------------------------------------------------------------------------------
1 | package com.prolificinteractive.parallaxpager;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.os.Build;
6 | import android.util.AttributeSet;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import java.lang.reflect.Field;
11 | import java.lang.reflect.Method;
12 | import org.xmlpull.v1.XmlPullParser;
13 |
14 | /**
15 | * Custom LayoutInflater that intercepts View creation and notifies ParallaxFactory of new views.
16 | * This class is a modified version from the Calligraphy project
17 | * @see uk.co.chrisjenx.calligraphy.CalligraphyLayoutInflater
18 | */
19 | class ParallaxLayoutInflater extends LayoutInflater {
20 |
21 | private static final String[] sClassPrefixList = {
22 | "android.widget.",
23 | "android.webkit."
24 | };
25 |
26 | private final ParallaxFactory mParallaxFactory;
27 | // Reflection Hax
28 | private boolean mSetPrivateFactory = false;
29 | private Field mConstructorArgs = null;
30 |
31 | protected ParallaxLayoutInflater(LayoutInflater original, Context newContext,
32 | ParallaxFactory factory) {
33 | super(original, newContext);
34 | this.mParallaxFactory = factory;
35 | }
36 |
37 | @Override
38 | public LayoutInflater cloneInContext(Context newContext) {
39 | return new ParallaxLayoutInflater(this, newContext, mParallaxFactory);
40 | }
41 |
42 | // ===
43 | // Wrapping goodies
44 | // ===
45 |
46 | @Override
47 | public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
48 | setPrivateFactoryInternal();
49 | return super.inflate(parser, root, attachToRoot);
50 | }
51 |
52 | /**
53 | * We don't want to unnecessary create/set our factories if there are none there. We try to be
54 | * as lazy as possible.
55 | */
56 | public void setUpLayoutFactories() {
57 | // If we are HC+ we get and set Factory2 otherwise we just wrap Factory1
58 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
59 | if (getFactory2() != null && !(getFactory2() instanceof WrapperFactory2)) {
60 | setFactory2(getFactory2());
61 | return;
62 | }
63 | }
64 | // We can do this as setFactory2 is used for both methods.
65 | if (getFactory() != null && !(getFactory() instanceof WrapperFactory)) {
66 | setFactory(getFactory());
67 | }
68 | }
69 |
70 | @Override
71 | public void setFactory(Factory factory) {
72 | // Only set our factory and wrap calls to the Factory trying to be set!
73 | if (!(factory instanceof WrapperFactory)) {
74 | super.setFactory(new WrapperFactory(factory, this, mParallaxFactory));
75 | } else {
76 | super.setFactory(factory);
77 | }
78 | }
79 |
80 | @Override
81 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
82 | public void setFactory2(Factory2 factory2) {
83 | // Only set our factory and wrap calls to the Factory2 trying to be set!
84 | if (!(factory2 instanceof WrapperFactory2)) {
85 | super.setFactory2(new WrapperFactory2(factory2, mParallaxFactory));
86 | } else {
87 | super.setFactory2(factory2);
88 | }
89 | }
90 |
91 | private void setPrivateFactoryInternal() {
92 | // Already tried to set the factory.
93 | if (mSetPrivateFactory) return;
94 | // Reflection (Or Old Device) skip.
95 | if (!(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)) { return; }
96 | // Skip if not attached to an activity.
97 | if (!(getContext() instanceof Factory2)) {
98 | mSetPrivateFactory = true;
99 | return;
100 | }
101 |
102 | final Method setPrivateFactoryMethod = ReflectionUtils
103 | .getMethod(LayoutInflater.class, "setPrivateFactory");
104 |
105 | if (setPrivateFactoryMethod != null) {
106 | ReflectionUtils.invokeMethod(this,
107 | setPrivateFactoryMethod,
108 | new PrivateWrapperFactory2((Factory2) getContext(), this, mParallaxFactory));
109 | }
110 | mSetPrivateFactory = true;
111 | }
112 |
113 | // ===
114 | // LayoutInflater ViewCreators
115 | // Works in order of inflation
116 | // ===
117 |
118 | /**
119 | * The LayoutInflater onCreateView is the fourth port of call for LayoutInflation.
120 | * BUT only for none CustomViews.
121 | */
122 | @Override
123 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
124 | protected View onCreateView(View parent, String name, AttributeSet attrs)
125 | throws ClassNotFoundException {
126 | return mParallaxFactory.onViewCreated(super.onCreateView(parent, name, attrs),
127 | getContext(), attrs);
128 | }
129 |
130 | /**
131 | * The LayoutInflater onCreateView is the fourth port of call for LayoutInflation.
132 | * BUT only for none CustomViews.
133 | * Basically if this method doesn't inflate the View nothing probably will.
134 | */
135 | @Override
136 | protected View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException {
137 | // This mimics the {@code PhoneLayoutInflater} in the way it tries to inflate the base
138 | // classes, if this fails its pretty certain the app will fail at this point.
139 | View view = null;
140 | for (String prefix : sClassPrefixList) {
141 | try {
142 | view = createView(name, prefix, attrs);
143 | } catch (ClassNotFoundException ignored) {
144 | }
145 | }
146 | // In this case we want to let the base class take a crack
147 | // at it.
148 | if (view == null) { view = super.onCreateView(name, attrs); }
149 |
150 | return mParallaxFactory.onViewCreated(view, view.getContext(), attrs);
151 | }
152 |
153 | /**
154 | * Nasty method to inflate custom layouts that haven't been handled else where. If this fails it
155 | * will fall back through to the PhoneLayoutInflater method of inflating custom views where
156 | * Calligraphy will NOT have a hook into.
157 | *
158 | * @param parent parent view
159 | * @param view view if it has been inflated by this point, if this is not null this method
160 | * just returns this value.
161 | * @param name name of the thing to inflate.
162 | * @param context Context to inflate by if parent is null
163 | * @param attrs Attr for this view which we can steal fontPath from too.
164 | * @return view or the View we inflate in here.
165 | */
166 | private View createCustomViewInternal(View parent, View view, String name, Context context,
167 | AttributeSet attrs) {
168 | // I by no means advise anyone to do this normally, but Google have locked down access to
169 | // the createView() method, so we never get a callback with attributes at the end of the
170 | // createViewFromTag chain (which would solve all this unnecessary rubbish).
171 | // We at the very least try to optimise this as much as possible.
172 | // We only call for customViews (As they are the ones that never go through onCreateView(...)).
173 | // We also maintain the Field reference and make it accessible which will make a pretty
174 | // significant difference to performance on Android 4.0+.
175 |
176 | // If CustomViewCreation is off skip this.
177 | if (view == null && name.indexOf('.') > -1) {
178 | if (mConstructorArgs == null) {
179 | mConstructorArgs = ReflectionUtils.getField(LayoutInflater.class, "mConstructorArgs");
180 | }
181 |
182 | final Object[] mConstructorArgsArr =
183 | (Object[]) ReflectionUtils.getValue(mConstructorArgs, this);
184 | final Object lastContext = mConstructorArgsArr[0];
185 | mConstructorArgsArr[0] = parent != null ? parent.getContext() : context;
186 | ReflectionUtils.setValue(mConstructorArgs, this, mConstructorArgsArr);
187 | try {
188 | view = createView(name, null, attrs);
189 | } catch (ClassNotFoundException ignored) {
190 | } finally {
191 | mConstructorArgsArr[0] = lastContext;
192 | ReflectionUtils.setValue(mConstructorArgs, this, mConstructorArgsArr);
193 | }
194 | }
195 | return view;
196 | }
197 |
198 | // ===
199 | // Wrapper Factories for Pre/Post HC
200 | // ===
201 |
202 | /**
203 | * Factory 1 is the first port of call for LayoutInflation
204 | */
205 | private static class WrapperFactory implements Factory {
206 |
207 | private final Factory mFactory;
208 | private final ParallaxLayoutInflater mInflater;
209 | private final ParallaxFactory mParallaxFactory;
210 |
211 | public WrapperFactory(Factory factory, ParallaxLayoutInflater inflater,
212 | ParallaxFactory parallaxFactory) {
213 | mFactory = factory;
214 | mInflater = inflater;
215 | mParallaxFactory = parallaxFactory;
216 | }
217 |
218 | @Override
219 | public View onCreateView(String name, Context context, AttributeSet attrs) {
220 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
221 | return mParallaxFactory.onViewCreated(
222 | mInflater.createCustomViewInternal(
223 | null, mFactory.onCreateView(name, context, attrs), name, context, attrs
224 | ),
225 | context, attrs
226 | );
227 | }
228 | return mParallaxFactory.onViewCreated(
229 | mFactory.onCreateView(name, context, attrs),
230 | context, attrs
231 | );
232 | }
233 | }
234 |
235 | /**
236 | * Factory 2 is the second port of call for LayoutInflation
237 | */
238 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
239 | private static class WrapperFactory2 implements Factory2 {
240 | protected final Factory2 mFactory2;
241 | protected final ParallaxFactory mParallaxFactory;
242 |
243 | public WrapperFactory2(Factory2 factory2, ParallaxFactory parallaxFactory) {
244 | mFactory2 = factory2;
245 | mParallaxFactory = parallaxFactory;
246 | }
247 |
248 | @Override
249 | public View onCreateView(String name, Context context, AttributeSet attrs) {
250 | return mParallaxFactory.onViewCreated(
251 | mFactory2.onCreateView(name, context, attrs),
252 | context, attrs);
253 | }
254 |
255 | @Override
256 | public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
257 | return mParallaxFactory.onViewCreated(
258 | mFactory2.onCreateView(parent, name, context, attrs),
259 | context, attrs);
260 | }
261 | }
262 |
263 | /**
264 | * Private factory is step three for Activity Inflation, this is what is attached to the
265 | * Activity on HC+ devices.
266 | */
267 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
268 | private static class PrivateWrapperFactory2 extends WrapperFactory2 {
269 |
270 | private final ParallaxLayoutInflater mInflater;
271 |
272 | public PrivateWrapperFactory2(Factory2 factory2, ParallaxLayoutInflater inflater,
273 | ParallaxFactory parallaxFactory) {
274 | super(factory2, parallaxFactory);
275 | mInflater = inflater;
276 | }
277 |
278 | @Override
279 | public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
280 | return mParallaxFactory.onViewCreated(
281 | mInflater.createCustomViewInternal(parent,
282 | mFactory2.onCreateView(parent, name, context, attrs),
283 | name, context, attrs
284 | ),
285 | context, attrs
286 | );
287 | }
288 | }
289 | }
290 |
--------------------------------------------------------------------------------
/parallaxpager/src/main/java/com/prolificinteractive/parallaxpager/ParallaxPagerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.prolificinteractive.parallaxpager;
2 |
3 | import android.content.Context;
4 | import android.support.v4.view.PagerAdapter;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import java.util.LinkedList;
8 |
9 | import static android.view.ViewGroup.LayoutParams;
10 | import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
11 |
12 | public class ParallaxPagerAdapter extends PagerAdapter {
13 | private int count = 0;
14 | private final Context context;
15 | private final LinkedList recycleBin = new LinkedList<>();
16 |
17 | public ParallaxPagerAdapter(Context context) {
18 | this.context = context;
19 | }
20 |
21 | public void setCount(int count) {
22 | this.count = count;
23 | }
24 |
25 | @Override public int getCount() {
26 | return count;
27 | }
28 |
29 | @Override public Object instantiateItem(ViewGroup container, int position) {
30 | View view;
31 | if (!recycleBin.isEmpty()) {
32 | view = recycleBin.pop();
33 | } else {
34 | view = new View(context);
35 | view.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
36 | }
37 | container.addView(view);
38 | return view;
39 | }
40 |
41 | @Override public void destroyItem(ViewGroup container, int position, Object object) {
42 | View view = (View) object;
43 | container.removeView(view);
44 | recycleBin.push(view);
45 | }
46 |
47 | @Override public boolean isViewFromObject(View view, Object object) {
48 | return view.equals(object);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/parallaxpager/src/main/java/com/prolificinteractive/parallaxpager/ParallaxViewTag.java:
--------------------------------------------------------------------------------
1 | package com.prolificinteractive.parallaxpager;
2 |
3 | public class ParallaxViewTag {
4 | protected int index;
5 | protected float xIn;
6 | protected float xOut;
7 | protected float yIn;
8 | protected float yOut;
9 | protected float alphaIn;
10 | protected float alphaOut;
11 | protected boolean overrideVisibility;
12 | }
13 |
--------------------------------------------------------------------------------
/parallaxpager/src/main/java/com/prolificinteractive/parallaxpager/ReflectionUtils.java:
--------------------------------------------------------------------------------
1 | package com.prolificinteractive.parallaxpager;
2 |
3 | import java.lang.reflect.Field;
4 | import java.lang.reflect.InvocationTargetException;
5 | import java.lang.reflect.Method;
6 |
7 | /**
8 | * Created by chris on 17/12/14.
9 | * For Calligraphy.
10 | */
11 | class ReflectionUtils {
12 |
13 | static Field getField(Class clazz, String fieldName) {
14 | try {
15 | final Field f = clazz.getDeclaredField(fieldName);
16 | f.setAccessible(true);
17 | return f;
18 | } catch (NoSuchFieldException ignored) {
19 | }
20 | return null;
21 | }
22 |
23 | static Object getValue(Field field, Object obj) {
24 | try {
25 | return field.get(obj);
26 | } catch (IllegalAccessException ignored) {
27 | }
28 | return null;
29 | }
30 |
31 | static void setValue(Field field, Object obj, Object value) {
32 | try {
33 | field.set(obj, value);
34 | } catch (IllegalAccessException ignored) {
35 | }
36 | }
37 |
38 | static Method getMethod(Class clazz, String methodName) {
39 | final Method[] methods = clazz.getMethods();
40 | for (Method method : methods) {
41 | if (method.getName().equals(methodName)) {
42 | method.setAccessible(true);
43 | return method;
44 | }
45 | }
46 | return null;
47 | }
48 |
49 | static void invokeMethod(Object object, Method method, Object... args) {
50 | try {
51 | if (method == null) return;
52 | method.invoke(object, args);
53 | } catch (IllegalAccessException | InvocationTargetException ignored) {
54 | ignored.printStackTrace();
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/parallaxpager/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/parallaxpager/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':example', 'parallaxpager'
2 |
--------------------------------------------------------------------------------