├── JazzyViewPager.apk ├── lib ├── libs │ ├── android-support-v4.jar │ └── nineoldandroids-2.4.0.jar ├── res │ ├── drawable-hdpi │ │ └── ic_launcher.png │ ├── drawable-mdpi │ │ └── ic_launcher.png │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ ├── values │ │ ├── colors.xml │ │ ├── ids.xml │ │ ├── strings.xml │ │ ├── styles.xml │ │ └── attrs.xml │ ├── layout │ │ └── activity_main.xml │ ├── values-v11 │ │ └── styles.xml │ ├── values-v14 │ │ └── styles.xml │ └── menu │ │ └── activity_main.xml ├── src │ └── com │ │ └── jfeinstein │ │ └── jazzyviewpager │ │ ├── Util.java │ │ ├── MainActivity.java │ │ ├── OutlineContainer.java │ │ └── JazzyViewPager.java ├── project.properties ├── proguard-project.txt └── AndroidManifest.xml ├── .gitignore ├── README.md └── LICENSE.txt /JazzyViewPager.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfeinstein10/JazzyViewPager/HEAD/JazzyViewPager.apk -------------------------------------------------------------------------------- /lib/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfeinstein10/JazzyViewPager/HEAD/lib/libs/android-support-v4.jar -------------------------------------------------------------------------------- /lib/libs/nineoldandroids-2.4.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfeinstein10/JazzyViewPager/HEAD/lib/libs/nineoldandroids-2.4.0.jar -------------------------------------------------------------------------------- /lib/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfeinstein10/JazzyViewPager/HEAD/lib/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /lib/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfeinstein10/JazzyViewPager/HEAD/lib/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /lib/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jfeinstein10/JazzyViewPager/HEAD/lib/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /lib/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #FF33E5B5 5 | 6 | -------------------------------------------------------------------------------- /lib/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /lib/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /.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 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | 18 | # Eclipse project files 19 | .classpath 20 | .project 21 | -------------------------------------------------------------------------------- /lib/src/com/jfeinstein/jazzyviewpager/Util.java: -------------------------------------------------------------------------------- 1 | package com.jfeinstein.jazzyviewpager; 2 | 3 | import android.content.res.Resources; 4 | import android.util.TypedValue; 5 | 6 | public class Util { 7 | 8 | public static int dpToPx(Resources res, int dp) { 9 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics()); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /lib/res/values-v11/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | -------------------------------------------------------------------------------- /lib/res/values-v14/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | -------------------------------------------------------------------------------- /lib/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JazzyViewPager 5 | 6 | 7 | Standard 8 | Tablet 9 | CubeIn 10 | CubeOut 11 | FlipVertical 12 | FlipHorizontal 13 | Stack 14 | ZoomIn 15 | ZoomOut 16 | RotateUp 17 | RotateDown 18 | Accordion 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-17 15 | android.library=false 16 | -------------------------------------------------------------------------------- /lib/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 15 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /lib/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /lib/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /lib/res/values/attrs.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 | -------------------------------------------------------------------------------- /lib/res/menu/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 10 | 11 | 14 | 15 | 18 | 19 | 22 | 23 | 26 | 27 | 30 | 31 | 34 | 35 | 38 | 39 | 42 | 43 | 46 | 47 | 50 | 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | JazzyViewPager 2 | ============== 3 | 4 | An easy to use ViewPager that adds an awesome set of custom swiping animations. 5 | Just change your ViewPagers to JazzyViewPagers and you're good to go! 6 | 7 | If you're looking at the name of the library and thinking "... so what does jazz have to do with it?" 8 | I'd like to direct you to the following definition that I found in a dictionary: 9 | 10 | ``` 11 | jazz someone or something up: 12 | to make someone or something more exciting or sexy; 13 | to make someone or something appeal more to contemporary tastes. 14 | ``` 15 | 16 | **The aim of this library is to do exactly this: jazz up the normal, everyday `ViewPager`** 17 | 18 | I've included a pretty barebones `apk` to show what the `TransitionEffect.Tablet` animation does. 19 | The example app will get better, but this is just to get something in your hands quickly :D! 20 | 21 | This project was inspired by CyanogenMod's Trebuchet launcher. 22 | 23 | Animations Available 24 | ------- 25 | The `JazzyViewPager`'s animations are encapsulated in `TransitionEffect`. I'll be adding more, but if you can think of anything 26 | in particular, let me know by filing an "Enhancement" in the Issues section. 27 | ```java 28 | public enum TransitionEffect { 29 | Standard, 30 | Tablet, 31 | CubeIn, 32 | CubeOut, 33 | Flip, 34 | Stack, 35 | ZoomIn, 36 | ZoomOut, 37 | RotateUp, 38 | RotateDown, 39 | Accordion 40 | } 41 | ``` 42 | You can select your animation by calling 43 | ```java 44 | private JazzyViewPager mJazzy; 45 | /* ... */ 46 | mJazzy.setTransitionEffect(TransitionEffect.*); 47 | ``` 48 | 49 | 50 | Modifying your `PagerAdapter` 51 | ------- 52 | Due to the limitations of the `ViewPager` class (which `JazzyViewPager` is built upon) in order to get the animations to work correctly 53 | for more than 3 Views, you'll have to add the following to the `instantiateItem` method of your `PagerAdapter`. 54 | ```java 55 | private JazzyViewPager mJazzy; 56 | /* ... */ 57 | @Override 58 | public Object instantiateItem(ViewGroup container, final int position) { 59 | Object obj = super.instantiateItem(container, position); 60 | mJazzy.setObjectForPosition(obj, position); 61 | return obj; 62 | } 63 | ``` 64 | Once your `Object` is registered with the `JazzyViewPager`, you're good to go! 65 | 66 | License 67 | ------- 68 | 69 | Copyright 2013 Jeremy Feinstein 70 | 71 | Licensed under the Apache License, Version 2.0 (the "License"); 72 | you may not use this file except in compliance with the License. 73 | You may obtain a copy of the License at 74 | 75 | http://www.apache.org/licenses/LICENSE-2.0 76 | 77 | Unless required by applicable law or agreed to in writing, software 78 | distributed under the License is distributed on an "AS IS" BASIS, 79 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 80 | See the License for the specific language governing permissions and 81 | limitations under the License. 82 | -------------------------------------------------------------------------------- /lib/src/com/jfeinstein/jazzyviewpager/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.jfeinstein.jazzyviewpager; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.support.v4.view.PagerAdapter; 7 | import android.view.Gravity; 8 | import android.view.Menu; 9 | import android.view.MenuItem; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.view.ViewGroup.LayoutParams; 13 | import android.widget.TextView; 14 | 15 | import com.jfeinstein.jazzyviewpager.JazzyViewPager.TransitionEffect; 16 | 17 | public class MainActivity extends Activity { 18 | 19 | private JazzyViewPager mJazzy; 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_main); 25 | setupJazziness(TransitionEffect.Tablet); 26 | } 27 | 28 | @Override 29 | public boolean onCreateOptionsMenu(Menu menu) { 30 | menu.add("Toggle Fade"); 31 | String[] effects = this.getResources().getStringArray(R.array.jazzy_effects); 32 | for (String effect : effects) 33 | menu.add(effect); 34 | return true; 35 | } 36 | 37 | @Override 38 | public boolean onOptionsItemSelected(MenuItem item) { 39 | if (item.getTitle().toString().equals("Toggle Fade")) { 40 | mJazzy.setFadeEnabled(!mJazzy.getFadeEnabled()); 41 | } else { 42 | TransitionEffect effect = TransitionEffect.valueOf(item.getTitle().toString()); 43 | setupJazziness(effect); 44 | } 45 | return true; 46 | } 47 | 48 | private void setupJazziness(TransitionEffect effect) { 49 | mJazzy = (JazzyViewPager) findViewById(R.id.jazzy_pager); 50 | mJazzy.setTransitionEffect(effect); 51 | mJazzy.setAdapter(new MainAdapter()); 52 | mJazzy.setPageMargin(30); 53 | } 54 | 55 | private class MainAdapter extends PagerAdapter { 56 | @Override 57 | public Object instantiateItem(ViewGroup container, final int position) { 58 | TextView text = new TextView(MainActivity.this); 59 | text.setGravity(Gravity.CENTER); 60 | text.setTextSize(30); 61 | text.setTextColor(Color.WHITE); 62 | text.setText("Page " + position); 63 | text.setPadding(30, 30, 30, 30); 64 | int bg = Color.rgb((int) Math.floor(Math.random()*128)+64, 65 | (int) Math.floor(Math.random()*128)+64, 66 | (int) Math.floor(Math.random()*128)+64); 67 | text.setBackgroundColor(bg); 68 | container.addView(text, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 69 | mJazzy.setObjectForPosition(text, position); 70 | return text; 71 | } 72 | @Override 73 | public void destroyItem(ViewGroup container, int position, Object obj) { 74 | container.removeView(mJazzy.findViewFromObject(position)); 75 | } 76 | @Override 77 | public int getCount() { 78 | return 10; 79 | } 80 | @Override 81 | public boolean isViewFromObject(View view, Object obj) { 82 | if (view instanceof OutlineContainer) { 83 | return ((OutlineContainer) view).getChildAt(0) == obj; 84 | } else { 85 | return view == obj; 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /lib/src/com/jfeinstein/jazzyviewpager/OutlineContainer.java: -------------------------------------------------------------------------------- 1 | package com.jfeinstein.jazzyviewpager; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.graphics.Paint.Style; 7 | import android.graphics.Rect; 8 | import android.graphics.drawable.Animatable; 9 | import android.util.AttributeSet; 10 | import android.view.animation.AnimationUtils; 11 | import android.view.animation.Interpolator; 12 | import android.widget.FrameLayout; 13 | 14 | public class OutlineContainer extends FrameLayout implements Animatable { 15 | 16 | private Paint mOutlinePaint; 17 | 18 | private boolean mIsRunning = false; 19 | private long mStartTime; 20 | private float mAlpha = 1.0f; 21 | private static final long ANIMATION_DURATION = 500; 22 | private static final long FRAME_DURATION = 1000 / 60; 23 | private final Interpolator mInterpolator = new Interpolator() { 24 | public float getInterpolation(float t) { 25 | t -= 1.0f; 26 | return t * t * t + 1.0f; 27 | } 28 | }; 29 | 30 | public OutlineContainer(Context context) { 31 | super(context); 32 | init(); 33 | } 34 | public OutlineContainer(Context context, AttributeSet attrs) { 35 | super(context, attrs); 36 | init(); 37 | } 38 | public OutlineContainer(Context context, AttributeSet attrs, int defStyle) { 39 | super(context, attrs, defStyle); 40 | init(); 41 | } 42 | 43 | private void init() { 44 | mOutlinePaint = new Paint(); 45 | mOutlinePaint.setAntiAlias(true); 46 | mOutlinePaint.setStrokeWidth(Util.dpToPx(getResources(), 2)); 47 | mOutlinePaint.setColor(getResources().getColor(R.color.holo_blue)); 48 | mOutlinePaint.setStyle(Style.STROKE); 49 | 50 | int padding = Util.dpToPx(getResources(), 10); 51 | setPadding(padding, padding, padding, padding); 52 | } 53 | 54 | @Override 55 | protected void dispatchDraw(Canvas canvas) { 56 | super.dispatchDraw(canvas); 57 | int offset = Util.dpToPx(getResources(), 5); 58 | if (mOutlinePaint.getColor() != JazzyViewPager.sOutlineColor) { 59 | mOutlinePaint.setColor(JazzyViewPager.sOutlineColor); 60 | } 61 | mOutlinePaint.setAlpha((int)(mAlpha * 255)); 62 | Rect rect = new Rect(offset, offset, getMeasuredWidth()-offset, getMeasuredHeight()-offset); 63 | canvas.drawRect(rect, mOutlinePaint); 64 | } 65 | 66 | public void setOutlineAlpha(float alpha) { 67 | mAlpha = alpha; 68 | } 69 | 70 | @Override 71 | public boolean isRunning() { 72 | return mIsRunning; 73 | } 74 | 75 | @Override 76 | public void start() { 77 | if (mIsRunning) 78 | return; 79 | mIsRunning = true; 80 | mStartTime = AnimationUtils.currentAnimationTimeMillis(); 81 | post(mUpdater); 82 | } 83 | 84 | @Override 85 | public void stop() { 86 | if (!mIsRunning) 87 | return; 88 | mIsRunning = false; 89 | } 90 | 91 | private final Runnable mUpdater = new Runnable() { 92 | @Override 93 | public void run() { 94 | long now = AnimationUtils.currentAnimationTimeMillis(); 95 | long duration = now - mStartTime; 96 | if (duration >= ANIMATION_DURATION) { 97 | mAlpha = 0.0f; 98 | invalidate(); 99 | stop(); 100 | return; 101 | } else { 102 | mAlpha = mInterpolator.getInterpolation(1 - duration / (float) ANIMATION_DURATION); 103 | invalidate(); 104 | } 105 | postDelayed(mUpdater, FRAME_DURATION); 106 | } 107 | }; 108 | 109 | } 110 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /lib/src/com/jfeinstein/jazzyviewpager/JazzyViewPager.java: -------------------------------------------------------------------------------- 1 | package com.jfeinstein.jazzyviewpager; 2 | 3 | import java.util.HashMap; 4 | import java.util.LinkedHashMap; 5 | 6 | import android.annotation.TargetApi; 7 | import android.content.Context; 8 | import android.content.res.TypedArray; 9 | import android.graphics.Camera; 10 | import android.graphics.Color; 11 | import android.graphics.Matrix; 12 | import android.os.Build; 13 | import android.support.v4.view.PagerAdapter; 14 | import android.support.v4.view.ViewPager; 15 | import android.util.AttributeSet; 16 | import android.util.Log; 17 | import android.view.MotionEvent; 18 | import android.view.View; 19 | 20 | import com.nineoldandroids.view.ViewHelper; 21 | 22 | public class JazzyViewPager extends ViewPager { 23 | 24 | public static final String TAG = "JazzyViewPager"; 25 | 26 | private boolean mEnabled = true; 27 | private boolean mFadeEnabled = false; 28 | private boolean mOutlineEnabled = false; 29 | public static int sOutlineColor = Color.WHITE; 30 | private TransitionEffect mEffect = TransitionEffect.Standard; 31 | 32 | private HashMap mObjs = new LinkedHashMap(); 33 | 34 | private static final float SCALE_MAX = 0.5f; 35 | private static final float ZOOM_MAX = 0.5f; 36 | private static final float ROT_MAX = 15.0f; 37 | 38 | public enum TransitionEffect { 39 | Standard, 40 | Tablet, 41 | CubeIn, 42 | CubeOut, 43 | FlipVertical, 44 | FlipHorizontal, 45 | Stack, 46 | ZoomIn, 47 | ZoomOut, 48 | RotateUp, 49 | RotateDown, 50 | Accordion 51 | } 52 | 53 | private static final boolean API_11; 54 | static { 55 | API_11 = Build.VERSION.SDK_INT >= 11; 56 | } 57 | 58 | public JazzyViewPager(Context context) { 59 | this(context, null); 60 | } 61 | 62 | @SuppressWarnings("incomplete-switch") 63 | public JazzyViewPager(Context context, AttributeSet attrs) { 64 | super(context, attrs); 65 | setClipChildren(false); 66 | // now style everything! 67 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.JazzyViewPager); 68 | int effect = ta.getInt(R.styleable.JazzyViewPager_style, 0); 69 | String[] transitions = getResources().getStringArray(R.array.jazzy_effects); 70 | setTransitionEffect(TransitionEffect.valueOf(transitions[effect])); 71 | setFadeEnabled(ta.getBoolean(R.styleable.JazzyViewPager_fadeEnabled, false)); 72 | setOutlineEnabled(ta.getBoolean(R.styleable.JazzyViewPager_outlineEnabled, false)); 73 | setOutlineColor(ta.getColor(R.styleable.JazzyViewPager_outlineColor, Color.WHITE)); 74 | switch (mEffect) { 75 | case Stack: 76 | case ZoomOut: 77 | setFadeEnabled(true); 78 | } 79 | ta.recycle(); 80 | } 81 | 82 | public void setTransitionEffect(TransitionEffect effect) { 83 | mEffect = effect; 84 | // reset(); 85 | } 86 | 87 | public void setPagingEnabled(boolean enabled) { 88 | mEnabled = enabled; 89 | } 90 | 91 | public void setFadeEnabled(boolean enabled) { 92 | mFadeEnabled = enabled; 93 | } 94 | 95 | public boolean getFadeEnabled() { 96 | return mFadeEnabled; 97 | } 98 | 99 | public void setOutlineEnabled(boolean enabled) { 100 | mOutlineEnabled = enabled; 101 | wrapWithOutlines(); 102 | } 103 | 104 | public void setOutlineColor(int color) { 105 | sOutlineColor = color; 106 | } 107 | 108 | private void wrapWithOutlines() { 109 | for (int i = 0; i < getChildCount(); i++) { 110 | View v = getChildAt(i); 111 | if (!(v instanceof OutlineContainer)) { 112 | removeView(v); 113 | super.addView(wrapChild(v), i); 114 | } 115 | } 116 | } 117 | 118 | private View wrapChild(View child) { 119 | if (!mOutlineEnabled || child instanceof OutlineContainer) return child; 120 | OutlineContainer out = new OutlineContainer(getContext()); 121 | out.setLayoutParams(generateDefaultLayoutParams()); 122 | child.setLayoutParams(new OutlineContainer.LayoutParams( 123 | LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); 124 | out.addView(child); 125 | return out; 126 | } 127 | 128 | public void addView(View child) { 129 | super.addView(wrapChild(child)); 130 | } 131 | 132 | public void addView(View child, int index) { 133 | super.addView(wrapChild(child), index); 134 | } 135 | 136 | public void addView(View child, LayoutParams params) { 137 | super.addView(wrapChild(child), params); 138 | } 139 | 140 | public void addView(View child, int width, int height) { 141 | super.addView(wrapChild(child), width, height); 142 | } 143 | 144 | public void addView(View child, int index, LayoutParams params) { 145 | super.addView(wrapChild(child), index, params); 146 | } 147 | 148 | @Override 149 | public boolean onInterceptTouchEvent(MotionEvent arg0) { 150 | return mEnabled ? super.onInterceptTouchEvent(arg0) : false; 151 | } 152 | 153 | private State mState; 154 | private int oldPage; 155 | 156 | private View mLeft; 157 | private View mRight; 158 | private float mRot; 159 | private float mTrans; 160 | private float mScale; 161 | 162 | private enum State { 163 | IDLE, 164 | GOING_LEFT, 165 | GOING_RIGHT 166 | } 167 | 168 | // public void reset() { 169 | // resetPrivate(); 170 | // int curr = getCurrentItem(); 171 | // onPageScrolled(curr, 0.0f, 0); 172 | //} 173 | // 174 | //private void resetPrivate() { 175 | // for (int i = 0; i < getChildCount(); i++) { 176 | // View v = getChildAt(i); 177 | // // ViewHelper.setRotation(v, -ViewHelper.getRotation(v)); 178 | // // ViewHelper.setRotationX(v, -ViewHelper.getRotationX(v)); 179 | // // ViewHelper.setRotationY(v, -ViewHelper.getRotationY(v)); 180 | // // 181 | // // ViewHelper.setTranslationX(v, -ViewHelper.getTranslationX(v)); 182 | // // ViewHelper.setTranslationY(v, -ViewHelper.getTranslationY(v)); 183 | // 184 | // ViewHelper.setRotation(v, 0); 185 | // ViewHelper.setRotationX(v, 0); 186 | // ViewHelper.setRotationY(v, 0); 187 | // 188 | // ViewHelper.setTranslationX(v, 0); 189 | // ViewHelper.setTranslationY(v, 0); 190 | // 191 | // ViewHelper.setAlpha(v, 1.0f); 192 | // 193 | // ViewHelper.setScaleX(v, 1.0f); 194 | // ViewHelper.setScaleY(v, 1.0f); 195 | // 196 | // ViewHelper.setPivotX(v, 0); 197 | // ViewHelper.setPivotY(v, 0); 198 | // 199 | // logState(v, "Child " + i); 200 | // } 201 | //} 202 | 203 | private void logState(View v, String title) { 204 | Log.v(TAG, title + ": ROT (" + ViewHelper.getRotation(v) + ", " + 205 | ViewHelper.getRotationX(v) + ", " + 206 | ViewHelper.getRotationY(v) + "), TRANS (" + 207 | ViewHelper.getTranslationX(v) + ", " + 208 | ViewHelper.getTranslationY(v) + "), SCALE (" + 209 | ViewHelper.getScaleX(v) + ", " + 210 | ViewHelper.getScaleY(v) + "), ALPHA " + 211 | ViewHelper.getAlpha(v)); 212 | } 213 | 214 | protected void animateScroll(int position, float positionOffset) { 215 | if (mState != State.IDLE) { 216 | mRot = (float)(1-Math.cos(2*Math.PI*positionOffset))/2*30.0f; 217 | ViewHelper.setRotationY(this, mState == State.GOING_RIGHT ? mRot : -mRot); 218 | ViewHelper.setPivotX(this, getMeasuredWidth()*0.5f); 219 | ViewHelper.setPivotY(this, getMeasuredHeight()*0.5f); 220 | } 221 | } 222 | 223 | protected void animateTablet(View left, View right, float positionOffset) { 224 | if (mState != State.IDLE) { 225 | if (left != null) { 226 | manageLayer(left, true); 227 | mRot = 30.0f * positionOffset; 228 | mTrans = getOffsetXForRotation(mRot, left.getMeasuredWidth(), 229 | left.getMeasuredHeight()); 230 | ViewHelper.setPivotX(left, left.getMeasuredWidth()/2); 231 | ViewHelper.setPivotY(left, left.getMeasuredHeight()/2); 232 | ViewHelper.setTranslationX(left, mTrans); 233 | ViewHelper.setRotationY(left, mRot); 234 | logState(left, "Left"); 235 | } 236 | if (right != null) { 237 | manageLayer(right, true); 238 | mRot = -30.0f * (1-positionOffset); 239 | mTrans = getOffsetXForRotation(mRot, right.getMeasuredWidth(), 240 | right.getMeasuredHeight()); 241 | ViewHelper.setPivotX(right, right.getMeasuredWidth()*0.5f); 242 | ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f); 243 | ViewHelper.setTranslationX(right, mTrans); 244 | ViewHelper.setRotationY(right, mRot); 245 | logState(right, "Right"); 246 | } 247 | } 248 | } 249 | 250 | private void animateCube(View left, View right, float positionOffset, boolean in) { 251 | if (mState != State.IDLE) { 252 | if (left != null) { 253 | manageLayer(left, true); 254 | mRot = (in ? 90.0f : -90.0f) * positionOffset; 255 | ViewHelper.setPivotX(left, left.getMeasuredWidth()); 256 | ViewHelper.setPivotY(left, left.getMeasuredHeight()*0.5f); 257 | ViewHelper.setRotationY(left, mRot); 258 | } 259 | if (right != null) { 260 | manageLayer(right, true); 261 | mRot = -(in ? 90.0f : -90.0f) * (1-positionOffset); 262 | ViewHelper.setPivotX(right, 0); 263 | ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f); 264 | ViewHelper.setRotationY(right, mRot); 265 | } 266 | } 267 | } 268 | 269 | private void animateAccordion(View left, View right, float positionOffset) { 270 | if (mState != State.IDLE) { 271 | if (left != null) { 272 | manageLayer(left, true); 273 | ViewHelper.setPivotX(left, left.getMeasuredWidth()); 274 | ViewHelper.setPivotY(left, 0); 275 | ViewHelper.setScaleX(left, 1-positionOffset); 276 | } 277 | if (right != null) { 278 | manageLayer(right, true); 279 | ViewHelper.setPivotX(right, 0); 280 | ViewHelper.setPivotY(right, 0); 281 | ViewHelper.setScaleX(right, positionOffset); 282 | } 283 | } 284 | } 285 | 286 | private void animateZoom(View left, View right, float positionOffset, boolean in) { 287 | if (mState != State.IDLE) { 288 | if (left != null) { 289 | manageLayer(left, true); 290 | mScale = in ? ZOOM_MAX + (1-ZOOM_MAX)*(1-positionOffset) : 291 | 1+ZOOM_MAX - ZOOM_MAX*(1-positionOffset); 292 | ViewHelper.setPivotX(left, left.getMeasuredWidth()*0.5f); 293 | ViewHelper.setPivotY(left, left.getMeasuredHeight()*0.5f); 294 | ViewHelper.setScaleX(left, mScale); 295 | ViewHelper.setScaleY(left, mScale); 296 | } 297 | if (right != null) { 298 | manageLayer(right, true); 299 | mScale = in ? ZOOM_MAX + (1-ZOOM_MAX)*positionOffset : 300 | 1+ZOOM_MAX - ZOOM_MAX*positionOffset; 301 | ViewHelper.setPivotX(right, right.getMeasuredWidth()*0.5f); 302 | ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f); 303 | ViewHelper.setScaleX(right, mScale); 304 | ViewHelper.setScaleY(right, mScale); 305 | } 306 | } 307 | } 308 | 309 | private void animateRotate(View left, View right, float positionOffset, boolean up) { 310 | if (mState != State.IDLE) { 311 | if (left != null) { 312 | manageLayer(left, true); 313 | mRot = (up ? 1 : -1) * (ROT_MAX * positionOffset); 314 | mTrans = (up ? -1 : 1) * (float) (getMeasuredHeight() - getMeasuredHeight()*Math.cos(mRot*Math.PI/180.0f)); 315 | ViewHelper.setPivotX(left, left.getMeasuredWidth()*0.5f); 316 | ViewHelper.setPivotY(left, up ? 0 : left.getMeasuredHeight()); 317 | ViewHelper.setTranslationY(left, mTrans); 318 | ViewHelper.setRotation(left, mRot); 319 | } 320 | if (right != null) { 321 | manageLayer(right, true); 322 | mRot = (up ? 1 : -1) * (-ROT_MAX + ROT_MAX*positionOffset); 323 | mTrans = (up ? -1 : 1) * (float) (getMeasuredHeight() - getMeasuredHeight()*Math.cos(mRot*Math.PI/180.0f)); 324 | ViewHelper.setPivotX(right, right.getMeasuredWidth()*0.5f); 325 | ViewHelper.setPivotY(right, up ? 0 : right.getMeasuredHeight()); 326 | ViewHelper.setTranslationY(right, mTrans); 327 | ViewHelper.setRotation(right, mRot); 328 | } 329 | } 330 | } 331 | 332 | private void animateFlipHorizontal(View left, View right, float positionOffset, int positionOffsetPixels) { 333 | if (mState != State.IDLE) { 334 | if (left != null) { 335 | manageLayer(left, true); 336 | mRot = 180.0f * positionOffset; 337 | if (mRot > 90.0f) { 338 | left.setVisibility(View.INVISIBLE); 339 | } else { 340 | if (left.getVisibility() == View.INVISIBLE) 341 | left.setVisibility(View.VISIBLE); 342 | mTrans = positionOffsetPixels; 343 | ViewHelper.setPivotX(left, left.getMeasuredWidth()*0.5f); 344 | ViewHelper.setPivotY(left, left.getMeasuredHeight()*0.5f); 345 | ViewHelper.setTranslationX(left, mTrans); 346 | ViewHelper.setRotationY(left, mRot); 347 | } 348 | } 349 | if (right != null) { 350 | manageLayer(right, true); 351 | mRot = -180.0f * (1-positionOffset); 352 | if (mRot < -90.0f) { 353 | right.setVisibility(View.INVISIBLE); 354 | } else { 355 | if (right.getVisibility() == View.INVISIBLE) 356 | right.setVisibility(View.VISIBLE); 357 | mTrans = -getWidth()-getPageMargin()+positionOffsetPixels; 358 | ViewHelper.setPivotX(right, right.getMeasuredWidth()*0.5f); 359 | ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f); 360 | ViewHelper.setTranslationX(right, mTrans); 361 | ViewHelper.setRotationY(right, mRot); 362 | } 363 | } 364 | } 365 | } 366 | 367 | private void animateFlipVertical(View left, View right, float positionOffset, int positionOffsetPixels) { 368 | if(mState != State.IDLE) { 369 | if (left != null) { 370 | manageLayer(left, true); 371 | mRot = 180.0f * positionOffset; 372 | if (mRot > 90.0f) { 373 | left.setVisibility(View.INVISIBLE); 374 | } else { 375 | if (left.getVisibility() == View.INVISIBLE) 376 | left.setVisibility(View.VISIBLE); 377 | mTrans = positionOffsetPixels; 378 | ViewHelper.setPivotX(left, left.getMeasuredWidth()*0.5f); 379 | ViewHelper.setPivotY(left, left.getMeasuredHeight()*0.5f); 380 | ViewHelper.setTranslationX(left, mTrans); 381 | ViewHelper.setRotationX(left, mRot); 382 | } 383 | } 384 | if (right != null) { 385 | manageLayer(right, true); 386 | mRot = -180.0f * (1-positionOffset); 387 | if (mRot < -90.0f) { 388 | right.setVisibility(View.INVISIBLE); 389 | } else { 390 | if (right.getVisibility() == View.INVISIBLE) 391 | right.setVisibility(View.VISIBLE); 392 | mTrans = -getWidth()-getPageMargin()+positionOffsetPixels; 393 | ViewHelper.setPivotX(right, right.getMeasuredWidth()*0.5f); 394 | ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f); 395 | ViewHelper.setTranslationX(right, mTrans); 396 | ViewHelper.setRotationX(right, mRot); 397 | } 398 | } 399 | } 400 | } 401 | 402 | protected void animateStack(View left, View right, float positionOffset, int positionOffsetPixels) { 403 | if (mState != State.IDLE) { 404 | if (right != null) { 405 | manageLayer(right, true); 406 | mScale = (1-SCALE_MAX) * positionOffset + SCALE_MAX; 407 | mTrans = -getWidth()-getPageMargin()+positionOffsetPixels; 408 | ViewHelper.setScaleX(right, mScale); 409 | ViewHelper.setScaleY(right, mScale); 410 | ViewHelper.setTranslationX(right, mTrans); 411 | } 412 | if (left != null) { 413 | left.bringToFront(); 414 | } 415 | } 416 | } 417 | 418 | @TargetApi(Build.VERSION_CODES.HONEYCOMB) 419 | private void manageLayer(View v, boolean enableHardware) { 420 | if (!API_11) return; 421 | int layerType = enableHardware ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE; 422 | if (layerType != v.getLayerType()) 423 | v.setLayerType(layerType, null); 424 | } 425 | 426 | @TargetApi(Build.VERSION_CODES.HONEYCOMB) 427 | private void disableHardwareLayer() { 428 | if (!API_11) return; 429 | View v; 430 | for (int i = 0; i < getChildCount(); i++) { 431 | v = getChildAt(i); 432 | if (v.getLayerType() != View.LAYER_TYPE_NONE) 433 | v.setLayerType(View.LAYER_TYPE_NONE, null); 434 | } 435 | } 436 | 437 | private Matrix mMatrix = new Matrix(); 438 | private Camera mCamera = new Camera(); 439 | private float[] mTempFloat2 = new float[2]; 440 | 441 | protected float getOffsetXForRotation(float degrees, int width, int height) { 442 | mMatrix.reset(); 443 | mCamera.save(); 444 | mCamera.rotateY(Math.abs(degrees)); 445 | mCamera.getMatrix(mMatrix); 446 | mCamera.restore(); 447 | 448 | mMatrix.preTranslate(-width * 0.5f, -height * 0.5f); 449 | mMatrix.postTranslate(width * 0.5f, height * 0.5f); 450 | mTempFloat2[0] = width; 451 | mTempFloat2[1] = height; 452 | mMatrix.mapPoints(mTempFloat2); 453 | return (width - mTempFloat2[0]) * (degrees > 0.0f ? 1.0f : -1.0f); 454 | } 455 | 456 | protected void animateFade(View left, View right, float positionOffset) { 457 | if (left != null) { 458 | ViewHelper.setAlpha(left, 1-positionOffset); 459 | } 460 | if (right != null) { 461 | ViewHelper.setAlpha(right, positionOffset); 462 | } 463 | } 464 | 465 | protected void animateOutline(View left, View right) { 466 | if (!(left instanceof OutlineContainer)) 467 | return; 468 | if (mState != State.IDLE) { 469 | if (left != null) { 470 | manageLayer(left, true); 471 | ((OutlineContainer)left).setOutlineAlpha(1.0f); 472 | } 473 | if (right != null) { 474 | manageLayer(right, true); 475 | ((OutlineContainer)right).setOutlineAlpha(1.0f); 476 | } 477 | } else { 478 | if (left != null) 479 | ((OutlineContainer)left).start(); 480 | if (right != null) 481 | ((OutlineContainer)right).start(); 482 | } 483 | } 484 | 485 | @Override 486 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 487 | if (mState == State.IDLE && positionOffset > 0) { 488 | oldPage = getCurrentItem(); 489 | mState = position == oldPage ? State.GOING_RIGHT : State.GOING_LEFT; 490 | } 491 | boolean goingRight = position == oldPage; 492 | if (mState == State.GOING_RIGHT && !goingRight) 493 | mState = State.GOING_LEFT; 494 | else if (mState == State.GOING_LEFT && goingRight) 495 | mState = State.GOING_RIGHT; 496 | 497 | float effectOffset = isSmall(positionOffset) ? 0 : positionOffset; 498 | 499 | // mLeft = getChildAt(position); 500 | // mRight = getChildAt(position+1); 501 | mLeft = findViewFromObject(position); 502 | mRight = findViewFromObject(position+1); 503 | 504 | if (mFadeEnabled) 505 | animateFade(mLeft, mRight, effectOffset); 506 | if (mOutlineEnabled) 507 | animateOutline(mLeft, mRight); 508 | 509 | switch (mEffect) { 510 | case Standard: 511 | break; 512 | case Tablet: 513 | animateTablet(mLeft, mRight, effectOffset); 514 | break; 515 | case CubeIn: 516 | animateCube(mLeft, mRight, effectOffset, true); 517 | break; 518 | case CubeOut: 519 | animateCube(mLeft, mRight, effectOffset, false); 520 | break; 521 | case FlipVertical: 522 | animateFlipVertical(mLeft, mRight, positionOffset, positionOffsetPixels); 523 | break; 524 | case FlipHorizontal: 525 | animateFlipHorizontal(mLeft, mRight, effectOffset, positionOffsetPixels); 526 | case Stack: 527 | animateStack(mLeft, mRight, effectOffset, positionOffsetPixels); 528 | break; 529 | case ZoomIn: 530 | animateZoom(mLeft, mRight, effectOffset, true); 531 | break; 532 | case ZoomOut: 533 | animateZoom(mLeft, mRight, effectOffset, false); 534 | break; 535 | case RotateUp: 536 | animateRotate(mLeft, mRight, effectOffset, true); 537 | break; 538 | case RotateDown: 539 | animateRotate(mLeft, mRight, effectOffset, false); 540 | break; 541 | case Accordion: 542 | animateAccordion(mLeft, mRight, effectOffset); 543 | break; 544 | } 545 | 546 | super.onPageScrolled(position, positionOffset, positionOffsetPixels); 547 | 548 | if (effectOffset == 0) { 549 | disableHardwareLayer(); 550 | mState = State.IDLE; 551 | } 552 | 553 | } 554 | 555 | private boolean isSmall(float positionOffset) { 556 | return Math.abs(positionOffset) < 0.0001; 557 | } 558 | 559 | public void setObjectForPosition(Object obj, int position) { 560 | mObjs.put(Integer.valueOf(position), obj); 561 | } 562 | 563 | public View findViewFromObject(int position) { 564 | Object o = mObjs.get(Integer.valueOf(position)); 565 | if (o == null) { 566 | return null; 567 | } 568 | PagerAdapter a = getAdapter(); 569 | View v; 570 | for (int i = 0; i < getChildCount(); i++) { 571 | v = getChildAt(i); 572 | if (a.isViewFromObject(v, o)) 573 | return v; 574 | } 575 | return null; 576 | } 577 | 578 | } --------------------------------------------------------------------------------