├── .gitignore ├── README.md ├── build.gradle └── src └── main └── java └── com └── andraskindler └── parallaxviewpager └── ParallaxViewPager.java /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | 15 | # Ignore gradle files 16 | .gradle/ 17 | <<<<<<< HEAD 18 | /build 19 | ======= 20 | build/ 21 | >>>>>>> 9b5c51719ff6f71297de1197ac54d5c010ac5632 22 | 23 | # Local configuration file (sdk path, etc) 24 | local.properties 25 | 26 | # Proguard folder generated by Eclipse 27 | proguard/ 28 | 29 | # IDEA 30 | .idea/ 31 | *.iml 32 | 33 | # Other 34 | <<<<<<< HEAD 35 | .DS_Store 36 | ======= 37 | .DS_Store 38 | >>>>>>> 9b5c51719ff6f71297de1197ac54d5c010ac5632 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Development stopped in 2014 2 | ================= 3 | Not developed since 2014. Unfinished and not stable - not recommended to use. 4 | 5 | ParallaxViewPager 6 | ================= 7 | 8 | An easy-to-use ViewPager subclass with parallax background. 9 | 10 | Setup requires little extra effort, using the ParallaxViewPager is just like using a standard ViewPager, with the same adapter. Of course, there's no silver bullet - the developer has to supply a background tailored to the current needs (eg. the number of items in the adapter and the size of the ViewPager). 11 | 12 | 1. Include it in your project as a Gradle dependency: 13 | ``` 14 | dependencies { 15 | compile 'com.andraskindler.parallaxviewpager:parallaxviewpager:0.3.1' 16 | } 17 | ``` 18 | 2. Create a ParallaxViewPager programmatically or in a layout xml. 19 | 20 | 3. Set the background via xml or one of the following methods: 21 | * *setBackgroundResource(int resid)* 22 | * *setBackground(Drawable background)* or *setBackgroundDrawable(Drawable background)* 23 | * *setBackground(Bitmap bitmap)* 24 | 25 | 4. (Optional) Specify how the view should scale the background with the *setScaleType(final int scaleType)* method. Choose from the following parameters: 26 | * *FIT_HEIGHT* means the height of the image is resized to matched the height of the View, also stretching the width to keep the aspect ratio. The non-visible part of the bitmap is divided into equal parts, each of them sliding in at the proper position. This is the default value. 27 | * *FIT_WIDTH* means the width of the background image is divided into equal chunks, each taking up the whole width of the screen. This mode is not the usual parallax-effect, as the speed of the background scrolling equals the speed of the views. 28 | 29 | 5. (Optional) Set the amount of overlapping with the *setOverlapPercentage(final float percentage)* method. This is a number between 0 and 1, the smaller it is, the slower is the background scrolling. The default value is 50 percent. This only works with *FIT_HEIGHT*. 30 | 31 | An example, inside the *onCreate()* of an activity: 32 | 33 | //... 34 | final ParallaxViewPager parallaxViewPager = new ParallaxViewPager(this); 35 | parallaxViewPager.setAdapter(new MyPagerAdapter()); 36 | parallaxViewPager.setBackgroundResource(R.drawable.nagy); 37 | setContentView(parallaxViewPager); 38 | //... 39 | 40 | Other notices 41 | ============= 42 | 43 | The lowest supported API level is 14 (Ice Cream Sandwich) 44 | 45 | By **Andras Kindler** (andraskindler@gmail.com) 46 | 47 | License 48 | ======= 49 | 50 | Copyright 2014 Andras Kindler 51 | 52 | Licensed under the Apache License, Version 2.0 (the "License"); 53 | you may not use this file except in compliance with the License. 54 | You may obtain a copy of the License at 55 | 56 | http://www.apache.org/licenses/LICENSE-2.0 57 | 58 | Unless required by applicable law or agreed to in writing, software 59 | distributed under the License is distributed on an "AS IS" BASIS, 60 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 61 | See the License for the specific language governing permissions and 62 | limitations under the License. 63 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'android-library' 2 | 3 | android { 4 | compileSdkVersion 19 5 | buildToolsVersion "19.1.0" 6 | 7 | defaultConfig { 8 | minSdkVersion 8 9 | targetSdkVersion 19 10 | versionCode 5 11 | versionName "0.3.0" 12 | } 13 | 14 | compileOptions { 15 | sourceCompatibility JavaVersion.VERSION_1_7 16 | targetCompatibility JavaVersion.VERSION_1_7 17 | } 18 | buildTypes { 19 | release { 20 | runProguard false 21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' 22 | } 23 | } 24 | } 25 | 26 | dependencies { 27 | compile 'com.android.support:support-v4:19.1.0' 28 | } 29 | 30 | POM_NAME='ParallaxViewPager' 31 | POM_ARTIFACT_ID='parallaxviewpager' 32 | POM_PACKAGING='jar' 33 | 34 | apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle' -------------------------------------------------------------------------------- /src/main/java/com/andraskindler/parallaxviewpager/ParallaxViewPager.java: -------------------------------------------------------------------------------- 1 | package com.andraskindler.parallaxviewpager; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.graphics.Bitmap; 6 | import android.graphics.BitmapFactory; 7 | import android.graphics.Canvas; 8 | import android.graphics.Rect; 9 | import android.graphics.drawable.BitmapDrawable; 10 | import android.graphics.drawable.Drawable; 11 | import android.support.v4.view.ViewPager; 12 | import android.util.AttributeSet; 13 | import android.util.Log; 14 | 15 | @SuppressLint("NewApi") 16 | public class ParallaxViewPager extends ViewPager { 17 | 18 | public static final int FIT_WIDTH = 0; 19 | public static final int FIT_HEIGHT = 1; 20 | public static final float OVERLAP_FULL = 1f; 21 | public static final float OVERLAP_HALF = 0.5f; 22 | public static final float OVERLAP_QUARTER = 0.25f; 23 | private static final float CORRECTION_PERCENTAGE = 0.01f; 24 | public Bitmap bitmap; 25 | private Rect source, destination; 26 | private int scaleType; 27 | private int chunkWidth; 28 | private int projectedWidth; 29 | private float overlap; 30 | private OnPageChangeListener secondOnPageChangeListener; 31 | 32 | public ParallaxViewPager(Context context) { 33 | super(context); 34 | init(); 35 | } 36 | 37 | public ParallaxViewPager(Context context, AttributeSet attrs) { 38 | super(context, attrs); 39 | init(); 40 | } 41 | 42 | private void init() { 43 | source = new Rect(); 44 | destination = new Rect(); 45 | scaleType = FIT_HEIGHT; 46 | overlap = OVERLAP_HALF; 47 | 48 | setOnPageChangeListener(new OnPageChangeListener() { 49 | @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 50 | if (bitmap != null) { 51 | source.left = (int) Math.floor((position + positionOffset - CORRECTION_PERCENTAGE) * chunkWidth); 52 | source.right = (int) Math.ceil((position + positionOffset + CORRECTION_PERCENTAGE) * chunkWidth + projectedWidth); 53 | destination.left = (int) Math.floor((position + positionOffset - CORRECTION_PERCENTAGE) * getWidth()); 54 | destination.right = (int) Math.ceil((position + positionOffset + 1 + CORRECTION_PERCENTAGE) * getWidth()); 55 | invalidate(); 56 | } 57 | 58 | if (secondOnPageChangeListener != null) { 59 | secondOnPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels); 60 | } 61 | } 62 | 63 | @Override public void onPageSelected(int position) { 64 | if (secondOnPageChangeListener != null) { 65 | secondOnPageChangeListener.onPageSelected(position); 66 | } 67 | } 68 | 69 | @Override public void onPageScrollStateChanged(int state) { 70 | if (secondOnPageChangeListener != null) { 71 | secondOnPageChangeListener.onPageScrollStateChanged(state); 72 | } 73 | } 74 | }); 75 | } 76 | 77 | @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { 78 | super.onSizeChanged(w, h, oldw, oldh); 79 | destination.top = 0; 80 | destination.bottom = h; 81 | if (getAdapter() != null && bitmap != null) 82 | calculateParallaxParameters(); 83 | } 84 | 85 | private void calculateParallaxParameters() { 86 | if (bitmap.getWidth() < getWidth() && bitmap.getWidth() < bitmap.getHeight() && scaleType == FIT_HEIGHT) { 87 | Log.w(ParallaxViewPager.class.getName(), "Invalid bitmap bounds for the current device, parallax effect will not work."); 88 | } 89 | 90 | final float ratio = (float) getHeight() / bitmap.getHeight(); 91 | if (ratio != 1) { 92 | switch (scaleType) { 93 | case FIT_WIDTH: 94 | source.top = (int) ((bitmap.getHeight() - bitmap.getHeight() / ratio) / 2); 95 | source.bottom = bitmap.getHeight() - source.top; 96 | chunkWidth = (int) Math.ceil((float) bitmap.getWidth() / (float) getAdapter().getCount()); 97 | projectedWidth = chunkWidth; 98 | break; 99 | case FIT_HEIGHT: 100 | default: 101 | source.top = 0; 102 | source.bottom = bitmap.getHeight(); 103 | projectedWidth = (int) Math.ceil(getWidth() / ratio); 104 | chunkWidth = (int) Math.ceil((bitmap.getWidth() - projectedWidth) / (float) getAdapter().getCount() * overlap); 105 | break; 106 | } 107 | } 108 | } 109 | 110 | /** 111 | * Sets the background from a resource file. 112 | * 113 | * @param resid 114 | */ 115 | @Override public void setBackgroundResource(int resid) { 116 | bitmap = BitmapFactory.decodeResource(getResources(), resid); 117 | } 118 | 119 | /** 120 | * Sets the background from a Drawable. 121 | * 122 | * @param background 123 | */ 124 | @Override public void setBackground(Drawable background) { 125 | bitmap = ((BitmapDrawable) background).getBitmap(); 126 | } 127 | 128 | /** 129 | * Deprecated. 130 | * Sets the background from a Drawable. 131 | * 132 | * @param background 133 | */ 134 | @Override public void setBackgroundDrawable(Drawable background) { 135 | bitmap = ((BitmapDrawable) background).getBitmap(); 136 | } 137 | 138 | /** 139 | * Sets the background from a bitmap. 140 | * 141 | * @param bitmap 142 | * @return The ParallaxViewPager object itself. 143 | */ 144 | public ParallaxViewPager setBackground(Bitmap bitmap) { 145 | this.bitmap = bitmap; 146 | return this; 147 | } 148 | 149 | /** 150 | * Sets how the view should scale the background. The available choices are: 151 | *