├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── animators ├── build.gradle └── src │ ├── androidTest │ └── java │ │ └── jp │ │ └── wasabeef │ │ └── recyclerview │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ └── java │ └── jp │ └── wasabeef │ └── recyclerview │ ├── adapters │ ├── AlphaInAnimationAdapter.java │ ├── AnimationAdapter.java │ ├── ScaleInAnimationAdapter.java │ ├── SlideInBottomAnimationAdapter.java │ ├── SlideInLeftAnimationAdapter.java │ └── SlideInRightAnimationAdapter.java │ ├── animators │ ├── BaseItemAnimator.java │ ├── FadeInAnimator.java │ ├── FadeInDownAnimator.java │ ├── FadeInLeftAnimator.java │ ├── FadeInRightAnimator.java │ ├── FadeInUpAnimator.java │ ├── FlipInBottomXAnimator.java │ ├── FlipInLeftYAnimator.java │ ├── FlipInRightYAnimator.java │ ├── FlipInTopXAnimator.java │ ├── LandingAnimator.java │ ├── OvershootInLeftAnimator.java │ ├── OvershootInRightAnimator.java │ ├── ScaleInAnimator.java │ ├── ScaleInBottomAnimator.java │ ├── ScaleInLeftAnimator.java │ ├── ScaleInRightAnimator.java │ ├── ScaleInTopAnimator.java │ ├── SlideInDownAnimator.java │ ├── SlideInLeftAnimator.java │ ├── SlideInRightAnimator.java │ ├── SlideInUpAnimator.java │ └── holder │ │ └── AnimateViewHolder.java │ └── internal │ └── ViewHelper.java ├── art ├── demo.gif ├── demo2.gif ├── demo3.gif ├── demo4.gif ├── demo5.gif └── logo.jpg ├── build.gradle ├── example ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── jp │ │ └── wasabeef │ │ └── example │ │ └── recyclerview │ │ ├── AdapterSampleActivity.java │ │ ├── AnimatorSampleActivity.java │ │ ├── MainActivity.java │ │ └── MainAdapter.java │ └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ ├── chip.jpg │ └── ic_launcher.png │ ├── drawable-xxhdpi │ ├── ic_github.png │ └── ic_launcher.png │ ├── layout │ ├── activity_adapter_sample.xml │ ├── activity_animator_sample.xml │ ├── activity_main.xml │ └── layout_list_item.xml │ └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Thumbs.db 3 | 4 | # gradle files 5 | .gradle 6 | 7 | # Intellij project files 8 | .idea 9 | *.iml 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | obj/ 15 | apk/ 16 | target/ 17 | build/ 18 | 19 | # Local configuration file (sdk path, etc) 20 | local.properties 21 | 22 | # Proguard folder generated by Eclipse 23 | proguard/ 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | 3 | # Turning off caching to avoid caching Issues 4 | # cache: false 5 | # Using the new Container-Based Infrastructure 6 | sudo: false 7 | 8 | env: 9 | global: 10 | # Amount of memory granted to Gradle JVM 11 | - GRADLE_OPTS="-Xmx512m -XX:MaxPermSize=512m" 12 | 13 | before_install: 14 | # Making sure gradlew has executable permissions 15 | - chmod +x gradlew 16 | # for gradle output style 17 | - export TERM=dumb 18 | 19 | android: 20 | components: 21 | # The BuildTools version we are using for our project 22 | - build-tools-23.0.2 23 | # The SDK version used to compile your project 24 | - android-23 25 | 26 | # Additional components 27 | - extra-google-google_play_services 28 | - extra-google-m2repository 29 | - extra-android-m2repository 30 | 31 | licenses: 32 | - 'android-sdk-license-.+' 33 | 34 | script: 35 | ./gradlew :animators:clean :animators:build 36 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Change Log 2 | ========== 3 | 4 | Version 2.1.0 *(2015-11-25)* 5 | ---------------------------- 6 | 7 | Move the adapters of the package. 8 | Added BaseItemAnimator#setInterpolator. 9 | 10 | Version 2.0.2 *(2015-11-24)* 11 | ---------------------------- 12 | 13 | Added AnimationAdapter#getIemId 14 | Fixed the getItemId() to return the nested adapter item id 15 | 16 | Version 2.0.1 *(2015-11-10)* 17 | ---------------------------- 18 | 19 | Bug fix registerAdapterDataObserver, unregisterAdapterDataObserver 20 | 21 | Version 2.0.0 *(2015-10-16)* 22 | ---------------------------- 23 | 24 | Support RecyclerView 23.1.0+ 25 | 26 | **Use 1.3.0 If you are using a 23.0.1 or below.** 27 | 28 | Version 1.3.0 *(2015-09-11)* 29 | ---------------------------- 30 | 31 | Added in ability to pass in interpolators to the four ItemAnimators. 32 | Thanks to [@craya1982](https://github.com/craya1982) 33 | 34 | Version 1.2.3 *(2015-09-07)* 35 | ---------------------------- 36 | 37 | Update support library. 38 | 39 | Version 1.2.2 *(2015-08-19)* 40 | ---------------------------- 41 | 42 | Add tension in OvershootAnimators. 43 | 44 | Version 1.2.1 *(2015-07-07)* 45 | ---------------------------- 46 | 47 | Update AnimationAdapter to allow grabbing the wrappedAdapter. 48 | 49 | Version 1.2.0 *(2015-04-15)* 50 | ---------------------------- 51 | 52 | Support Multiple animators for ViewHolders. 53 | 54 | Version 1.1.3 *(2015-04-08)* 55 | ---------------------------- 56 | 57 | Support Interpolator in AnimationAdapter. 58 | 59 | Version 1.1.2 *(2015-03-23)* 60 | ---------------------------- 61 | 62 | Supports multiple viewTypes. 63 | 64 | Version 1.1.1 *(2015-03-17)* 65 | ---------------------------- 66 | 67 | Improved reliability and speed. 68 | 69 | Version 1.1.0 *(2015-01-21)* 70 | ---------------------------- 71 | 72 | add RecyclerView.Adapter support. 73 | 74 | 75 | Version 1.0.3 *(2015-01-21)* 76 | ---------------------------- 77 | 78 | fix setting of pom.xml 79 | 80 | Version 1.0.2 *(2015-01-20)* 81 | ---------------------------- 82 | 83 | fix setting of pom.xml 84 | 85 | Version 1.0.1 *(2015-01-10)* 86 | ---------------------------- 87 | 88 | Attach a jar for non-Gradle Android users. 89 | 90 | Version 1.0.0 *(2015-01-05)* 91 | ---------------------------- 92 | 93 | Initial release. 94 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | RecyclerView Animators 2 | ====================== 3 |

4 | 5 |

6 | 7 | [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/wasabeef/recyclerview-animators?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 8 | 9 | [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-recyclerview--animators-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1327) 10 | [![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0) 11 | [![Download](https://api.bintray.com/packages/wasabeef/maven/recyclerview-animators/images/download.svg)](https://bintray.com/wasabeef/maven/recyclerview-animators/_latestVersion) 12 | 13 | RecyclerView Animators is an Android library that allows developers to easily create RecyclerView with animations. 14 | 15 | Please feel free to use this. 16 | 17 | # Features 18 | 19 | * Animate addition and removal of `ItemAnimator` 20 | * Appearance animations for items in `RecyclerView.Adapter` 21 | 22 | # Demo 23 | 24 | ### ItemAnimator 25 | 26 | 27 | ### Adapters 28 | ![](art/demo3.gif) ![](art/demo5.gif) 29 | 30 | # Samples 31 | 32 | 33 | 34 | # How do I use it? 35 | 36 | ## Setup 37 | 38 | #### Gradle 39 | 40 | **If you are using a RecyclerView 23.1.0 (released Oct 2015) or higher.** 41 | ```groovy 42 | dependencies { 43 | // jCenter 44 | compile 'jp.wasabeef:recyclerview-animators:2.1.0' 45 | } 46 | ``` 47 | 48 | **If you are using a RecyclerView 23.0.1 or below.** 49 | ```groovy 50 | dependencies { 51 | // jCenter 52 | compile 'jp.wasabeef:recyclerview-animators:1.3.0' 53 | } 54 | ``` 55 | 56 | ## ItemAnimator 57 | ### Step 1 58 | 59 | Set RecyclerView ItemAnimator. 60 | 61 | ```java 62 | RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list); 63 | recyclerView.setItemAnimator(new SlideInLeftAnimator()); 64 | ``` 65 | 66 | ```java 67 | RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list); 68 | recyclerView.setItemAnimator(new SlideInUpAnimator(new OvershootInterpolator(1f)); 69 | ``` 70 | 71 | ## Step 2 72 | Please use the following 73 | `notifyItemChanged(int)` 74 | `notifyItemInserted(int)` 75 | `notifyItemRemoved(int)` 76 | `notifyItemRangeChanged(int, int)` 77 | `notifyItemRangeInserted(int, int)` 78 | `notifyItemRangeRemoved(int, int)` 79 | 80 | > If you want your animations to work, do not rely on calling `notifyDataSetChanged()`; 81 | > as it is the RecyclerView's default behavior, animations are not triggered to start inside this method. 82 | 83 | ```java 84 | public void remove(int position) { 85 | mDataSet.remove(position); 86 | notifyItemRemoved(position); 87 | } 88 | 89 | public void add(String text, int position) { 90 | mDataSet.add(position, text); 91 | notifyItemInserted(position); 92 | } 93 | ``` 94 | 95 | ### Advanced Step 3 96 | 97 | You can change the durations. 98 | 99 | ```java 100 | recyclerView.getItemAnimator().setAddDuration(1000); 101 | recyclerView.getItemAnimator().setRemoveDuration(1000); 102 | recyclerView.getItemAnimator().setMoveDuration(1000); 103 | recyclerView.getItemAnimator().setChangeDuration(1000); 104 | ``` 105 | 106 | ### Advanced Step 4 107 | 108 | Change the interpolator. 109 | 110 | ```java 111 | SlideInLeftAnimator animator = new SlideInLeftAnimato(); 112 | animator.setInterpolator(new OvershootInterpolator()); 113 | // or recyclerView.setItemAnimator(new SlideInUpAnimator(new OvershootInterpolator(1f)); 114 | recyclerView.setItemAnimator(animator); 115 | ``` 116 | 117 | ### Advanced Step 5 118 | 119 | By extending AnimateViewHolder, you can override preset animation. 120 | So, custom animation can be set depending on view holder. 121 | 122 | ```java 123 | static class MyViewHolder extends AnimateViewHolder { 124 | 125 | public MyViewHolder(View itemView) { 126 | super(itemView); 127 | } 128 | 129 | @Override 130 | public void animateRemoveImpl(ViewPropertyAnimatorListener listener) { 131 | ViewCompat.animate(itemView) 132 | .translationY(-itemView.getHeight() * 0.3f) 133 | .alpha(0) 134 | .setDuration(300) 135 | .setListener(listener) 136 | .start(); 137 | } 138 | 139 | @Override 140 | public void preAnimateAddImpl() { 141 | ViewCompat.setTranslationY(itemView, -itemView.getHeight() * 0.3f); 142 | ViewCompat.setAlpha(itemView, 0); 143 | } 144 | 145 | @Override 146 | public void animateAddImpl(ViewPropertyAnimatorListener listener) { 147 | ViewCompat.animate(itemView) 148 | .translationY(0) 149 | .alpha(1) 150 | .setDuration(300) 151 | .setListener(listener) 152 | .start(); 153 | } 154 | } 155 | ``` 156 | 157 | ### Animators 158 | 159 | #### Cool 160 | `LandingAnimator` 161 | 162 | ##### Scale 163 | `ScaleInAnimator`, `ScaleInTopAnimator`, `ScaleInBottomAnimator` 164 | `ScaleInLeftAnimator`, `ScaleInRightAnimator` 165 | 166 | 167 | ##### Fade 168 | `FadeInAnimator`, `FadeInDownAnimator`, `FadeInUpAnimator` 169 | `FadeInLeftAnimator`, `FadeInRightAnimator` 170 | 171 | ##### Flip 172 | `FlipInTopXAnimator`, `FlipInBottomXAnimator` 173 | `FlipInLeftYAnimator`, `FlipInRightYAnimator` 174 | 175 | ##### Slide 176 | `SlideInLeftAnimator`, `SlideInRightAnimator`, `OvershootInLeftAnimator`, `OvershootInRightAnimator` 177 | `SlideInUpAnimator`, `SlideInDownAnimator` 178 | 179 | ## RecyclerView.Adapter 180 | ### Step 1 181 | 182 | Set RecyclerView ItemAnimator. 183 | 184 | ```java 185 | RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list); 186 | MyAdapter adapter = new MyAdapter(); 187 | recyclerView.setAdapter(new AlphaInAnimationAdapter(adapter)); 188 | ``` 189 | 190 | ### Advanced Step 2 191 | 192 | Change the durations. 193 | 194 | ```java 195 | MyAdapter adapter = new MyAdapter(); 196 | AlphaInAnimationAdapter alphaAdapter = new AlphaInAnimationAdapter(adapter); 197 | alphaAdapter.setDuration(1000); 198 | recyclerView.setAdapter(alphaAdapter); 199 | ``` 200 | 201 | ### Advanced Step 3 202 | 203 | Change the interpolator. 204 | 205 | ```java 206 | MyAdapter adapter = new MyAdapter(); 207 | AlphaInAnimationAdapter alphaAdapter = new AlphaInAnimationAdapter(adapter); 208 | alphaAdapter.setInterpolator(new OvershootInterpolator()); 209 | recyclerView.setAdapter(alphaAdapter); 210 | ``` 211 | 212 | ### Advanced Step 4 213 | 214 | Disable the first scroll mode. 215 | 216 | ```java 217 | MyAdapter adapter = new MyAdapter(); 218 | AlphaInAnimationAdapter alphaAdapter = new AlphaInAnimationAdapter(adapter); 219 | scaleAdapter.setFirstOnly(false); 220 | recyclerView.setAdapter(alphaAdapter); 221 | ``` 222 | 223 | ### Advanced Step 5 224 | 225 | Multiple Animations 226 | 227 | ```java 228 | MyAdapter adapter = new MyAdapter(); 229 | AlphaInAnimationAdapter alphaAdapter = new AlphaInAnimationAdapter(adapter); 230 | recyclerView.setAdapter(new ScaleInAnimationAdapter(alphaAdapter)); 231 | ``` 232 | 233 | ### Adapters 234 | 235 | #### Alpha 236 | `AlphaInAnimationAdapter` 237 | 238 | #### Scale 239 | `ScaleInAnimationAdapter` 240 | 241 | #### Slide 242 | `SlideInBottomAnimationAdapter` 243 | `SlideInRightAnimationAdapter`, `SlideInLeftAnimationAdapter` 244 | 245 | Applications using RecyclerView Animators 246 | --- 247 | 248 | Please [ping](mailto:dadadada.chop@gmail.com) me or send a pull request if you would like to be added here. 249 | 250 | Icon | Application 251 | ------------ | ------------- 252 | | [Ameba Ownd](https://play.google.com/store/apps/details?id=jp.co.cyberagent.madrid) 253 | 254 | Developed By 255 | ------- 256 | Daichi Furiya (Wasabeef) - 257 | 258 | 259 | Follow me on Twitter 261 | 262 | 263 | Contributions 264 | ------- 265 | 266 | Any contributions are welcome! 267 | 268 | Contributers 269 | ------- 270 | 271 | * [craya1982](https://github.com/craya1982) 272 | 273 | Thanks 274 | ------- 275 | 276 | * Inspired by `AndroidViewAnimations` in [daimajia](https://github.com/daimajia). 277 | 278 | License 279 | ------- 280 | 281 | Copyright 2015 Wasabeef 282 | 283 | Licensed under the Apache License, Version 2.0 (the "License"); 284 | you may not use this file except in compliance with the License. 285 | You may obtain a copy of the License at 286 | 287 | http://www.apache.org/licenses/LICENSE-2.0 288 | 289 | Unless required by applicable law or agreed to in writing, software 290 | distributed under the License is distributed on an "AS IS" BASIS, 291 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 292 | See the License for the specific language governing permissions and 293 | limitations under the License. 294 | -------------------------------------------------------------------------------- /animators/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.novoda.bintray-release' 3 | 4 | android { 5 | compileSdkVersion COMPILE_SDK_VERSION as int 6 | buildToolsVersion BUILD_TOOLS_VERSION 7 | 8 | defaultConfig { 9 | minSdkVersion MIN_SDK_VERSION as int 10 | targetSdkVersion TARGET_SDK_VERSION as int 11 | versionCode "git rev-list origin/master --count".execute().text.toInteger() 12 | versionName VERSION_NAME 13 | } 14 | } 15 | 16 | dependencies { 17 | compile "com.android.support:appcompat-v7:${SUPPORT_PACKAGE_VERSION}" 18 | compile "com.android.support:recyclerview-v7:${SUPPORT_PACKAGE_VERSION}" 19 | } 20 | 21 | publish { 22 | userOrg = POM_DEVELOPER_ID 23 | groupId = GROUP 24 | artifactId = ARTIFACT_ID 25 | publishVersion = VERSION_NAME 26 | desc = POM_DESCRIPTION 27 | website = POM_URL 28 | } 29 | -------------------------------------------------------------------------------- /animators/src/androidTest/java/jp/wasabeef/recyclerview/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | 11 | public ApplicationTest() { 12 | super(Application.class); 13 | } 14 | } -------------------------------------------------------------------------------- /animators/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/adapters/AlphaInAnimationAdapter.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.adapters; 2 | 3 | import android.animation.Animator; 4 | import android.animation.ObjectAnimator; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.View; 7 | 8 | /** 9 | * Copyright (C) 2015 Wasabeef 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | 24 | public class AlphaInAnimationAdapter extends AnimationAdapter { 25 | 26 | private static final float DEFAULT_ALPHA_FROM = 0f; 27 | private final float mFrom; 28 | 29 | public AlphaInAnimationAdapter(RecyclerView.Adapter adapter) { 30 | this(adapter, DEFAULT_ALPHA_FROM); 31 | } 32 | 33 | public AlphaInAnimationAdapter(RecyclerView.Adapter adapter, float from) { 34 | super(adapter); 35 | mFrom = from; 36 | } 37 | 38 | @Override protected Animator[] getAnimators(View view) { 39 | return new Animator[] { ObjectAnimator.ofFloat(view, "alpha", mFrom, 1f) }; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/adapters/AnimationAdapter.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.adapters; 2 | 3 | import android.animation.Animator; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.view.animation.Interpolator; 8 | import android.view.animation.LinearInterpolator; 9 | 10 | import jp.wasabeef.recyclerview.internal.ViewHelper; 11 | 12 | /** 13 | * Copyright (C) 2015 Wasabeef 14 | * 15 | * Licensed under the Apache License, Version 2.0 (the "License"); 16 | * you may not use this file except in compliance with the License. 17 | * You may obtain a copy of the License at 18 | * 19 | * http://www.apache.org/licenses/LICENSE-2.0 20 | * 21 | * Unless required by applicable law or agreed to in writing, software 22 | * distributed under the License is distributed on an "AS IS" BASIS, 23 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 24 | * See the License for the specific language governing permissions and 25 | * limitations under the License. 26 | */ 27 | public abstract class AnimationAdapter extends RecyclerView.Adapter { 28 | 29 | private RecyclerView.Adapter mAdapter; 30 | private int mDuration = 300; 31 | private Interpolator mInterpolator = new LinearInterpolator(); 32 | private int mLastPosition = -1; 33 | 34 | private boolean isFirstOnly = true; 35 | 36 | public AnimationAdapter(RecyclerView.Adapter adapter) { 37 | mAdapter = adapter; 38 | } 39 | 40 | @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 41 | return mAdapter.onCreateViewHolder(parent, viewType); 42 | } 43 | 44 | @Override public void registerAdapterDataObserver(RecyclerView.AdapterDataObserver observer) { 45 | super.registerAdapterDataObserver(observer); 46 | mAdapter.registerAdapterDataObserver(observer); 47 | } 48 | 49 | @Override public void unregisterAdapterDataObserver(RecyclerView.AdapterDataObserver observer) { 50 | super.unregisterAdapterDataObserver(observer); 51 | mAdapter.unregisterAdapterDataObserver(observer); 52 | } 53 | 54 | @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 55 | mAdapter.onBindViewHolder(holder, position); 56 | 57 | if (!isFirstOnly || position > mLastPosition) { 58 | for (Animator anim : getAnimators(holder.itemView)) { 59 | anim.setDuration(mDuration).start(); 60 | anim.setInterpolator(mInterpolator); 61 | } 62 | mLastPosition = position; 63 | } else { 64 | ViewHelper.clear(holder.itemView); 65 | } 66 | } 67 | 68 | @Override public int getItemCount() { 69 | return mAdapter.getItemCount(); 70 | } 71 | 72 | public void setDuration(int duration) { 73 | mDuration = duration; 74 | } 75 | 76 | public void setInterpolator(Interpolator interpolator) { 77 | mInterpolator = interpolator; 78 | } 79 | 80 | public void setStartPosition(int start) { 81 | mLastPosition = start; 82 | } 83 | 84 | protected abstract Animator[] getAnimators(View view); 85 | 86 | public void setFirstOnly(boolean firstOnly) { 87 | isFirstOnly = firstOnly; 88 | } 89 | 90 | @Override public int getItemViewType(int position) { 91 | return mAdapter.getItemViewType(position); 92 | } 93 | 94 | public RecyclerView.Adapter getWrappedAdapter() { 95 | return mAdapter; 96 | } 97 | 98 | @Override 99 | public long getItemId(int position) { 100 | return mAdapter.getItemId(position); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/adapters/ScaleInAnimationAdapter.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.adapters; 2 | 3 | import android.animation.Animator; 4 | import android.animation.ObjectAnimator; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.View; 7 | 8 | /** 9 | * Copyright (C) 2015 Wasabeef 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | 24 | public class ScaleInAnimationAdapter extends AnimationAdapter { 25 | 26 | private static final float DEFAULT_SCALE_FROM = .5f; 27 | private final float mFrom; 28 | 29 | public ScaleInAnimationAdapter(RecyclerView.Adapter adapter) { 30 | this(adapter, DEFAULT_SCALE_FROM); 31 | } 32 | 33 | public ScaleInAnimationAdapter(RecyclerView.Adapter adapter, float from) { 34 | super(adapter); 35 | mFrom = from; 36 | } 37 | 38 | @Override protected Animator[] getAnimators(View view) { 39 | ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", mFrom, 1f); 40 | ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", mFrom, 1f); 41 | return new ObjectAnimator[] { scaleX, scaleY }; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/adapters/SlideInBottomAnimationAdapter.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.adapters; 2 | 3 | import android.animation.Animator; 4 | import android.animation.ObjectAnimator; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.View; 7 | 8 | /** 9 | * Copyright (C) 2015 Wasabeef 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | 24 | public class SlideInBottomAnimationAdapter extends AnimationAdapter { 25 | 26 | public SlideInBottomAnimationAdapter(RecyclerView.Adapter adapter) { 27 | super(adapter); 28 | } 29 | 30 | @Override protected Animator[] getAnimators(View view) { 31 | return new Animator[] { 32 | ObjectAnimator.ofFloat(view, "translationY", view.getMeasuredHeight(), 0) 33 | }; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/adapters/SlideInLeftAnimationAdapter.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.adapters; 2 | 3 | import android.animation.Animator; 4 | import android.animation.ObjectAnimator; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.View; 7 | 8 | /** 9 | * Copyright (C) 2015 Wasabeef 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | 24 | public class SlideInLeftAnimationAdapter extends AnimationAdapter { 25 | 26 | public SlideInLeftAnimationAdapter(RecyclerView.Adapter adapter) { 27 | super(adapter); 28 | } 29 | 30 | @Override protected Animator[] getAnimators(View view) { 31 | return new Animator[] { 32 | ObjectAnimator.ofFloat(view, "translationX", -view.getRootView().getWidth(), 0) 33 | }; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/adapters/SlideInRightAnimationAdapter.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.adapters; 2 | 3 | import android.animation.Animator; 4 | import android.animation.ObjectAnimator; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.View; 7 | 8 | /** 9 | * Copyright (C) 2015 Wasabeef 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | 24 | public class SlideInRightAnimationAdapter extends AnimationAdapter { 25 | 26 | public SlideInRightAnimationAdapter(RecyclerView.Adapter adapter) { 27 | super(adapter); 28 | } 29 | 30 | @Override protected Animator[] getAnimators(View view) { 31 | return new Animator[] { 32 | ObjectAnimator.ofFloat(view, "translationX", view.getRootView().getWidth(), 0) 33 | }; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/BaseItemAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | /* 3 | * Copyright (C) 2015 Wasabeef 4 | * Copyright (C) 2014 The Android Open Source Project 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | import android.support.v4.view.ViewCompat; 21 | import android.support.v4.view.ViewPropertyAnimatorCompat; 22 | import android.support.v4.view.ViewPropertyAnimatorListener; 23 | import android.support.v7.widget.RecyclerView; 24 | import android.support.v7.widget.RecyclerView.ViewHolder; 25 | import android.support.v7.widget.SimpleItemAnimator; 26 | import android.view.View; 27 | import android.view.animation.Interpolator; 28 | import android.view.animation.LinearInterpolator; 29 | import java.util.ArrayList; 30 | import java.util.List; 31 | import jp.wasabeef.recyclerview.animators.holder.AnimateViewHolder; 32 | import jp.wasabeef.recyclerview.internal.ViewHelper; 33 | 34 | public abstract class BaseItemAnimator extends SimpleItemAnimator { 35 | 36 | private static final boolean DEBUG = false; 37 | 38 | private ArrayList mPendingRemovals = new ArrayList<>(); 39 | private ArrayList mPendingAdditions = new ArrayList<>(); 40 | private ArrayList mPendingMoves = new ArrayList<>(); 41 | private ArrayList mPendingChanges = new ArrayList<>(); 42 | 43 | private ArrayList> mAdditionsList = new ArrayList<>(); 44 | private ArrayList> mMovesList = new ArrayList<>(); 45 | private ArrayList> mChangesList = new ArrayList<>(); 46 | 47 | protected ArrayList mAddAnimations = new ArrayList<>(); 48 | private ArrayList mMoveAnimations = new ArrayList<>(); 49 | protected ArrayList mRemoveAnimations = new ArrayList<>(); 50 | private ArrayList mChangeAnimations = new ArrayList<>(); 51 | 52 | protected Interpolator mInterpolator = new LinearInterpolator(); 53 | 54 | private static class MoveInfo { 55 | 56 | public ViewHolder holder; 57 | public int fromX, fromY, toX, toY; 58 | 59 | private MoveInfo(ViewHolder holder, int fromX, int fromY, int toX, int toY) { 60 | this.holder = holder; 61 | this.fromX = fromX; 62 | this.fromY = fromY; 63 | this.toX = toX; 64 | this.toY = toY; 65 | } 66 | } 67 | 68 | private static class ChangeInfo { 69 | 70 | public ViewHolder oldHolder, newHolder; 71 | public int fromX, fromY, toX, toY; 72 | 73 | private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder) { 74 | this.oldHolder = oldHolder; 75 | this.newHolder = newHolder; 76 | } 77 | 78 | private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder, int fromX, int fromY, int toX, 79 | int toY) { 80 | this(oldHolder, newHolder); 81 | this.fromX = fromX; 82 | this.fromY = fromY; 83 | this.toX = toX; 84 | this.toY = toY; 85 | } 86 | 87 | @Override public String toString() { 88 | return "ChangeInfo{" + 89 | "oldHolder=" + oldHolder + 90 | ", newHolder=" + newHolder + 91 | ", fromX=" + fromX + 92 | ", fromY=" + fromY + 93 | ", toX=" + toX + 94 | ", toY=" + toY + 95 | '}'; 96 | } 97 | } 98 | 99 | public BaseItemAnimator() { 100 | super(); 101 | setSupportsChangeAnimations(false); 102 | } 103 | 104 | public void setInterpolator(Interpolator mInterpolator) { 105 | this.mInterpolator = mInterpolator; 106 | } 107 | 108 | @Override public void runPendingAnimations() { 109 | boolean removalsPending = !mPendingRemovals.isEmpty(); 110 | boolean movesPending = !mPendingMoves.isEmpty(); 111 | boolean changesPending = !mPendingChanges.isEmpty(); 112 | boolean additionsPending = !mPendingAdditions.isEmpty(); 113 | if (!removalsPending && !movesPending && !additionsPending && !changesPending) { 114 | // nothing to animate 115 | return; 116 | } 117 | // First, remove stuff 118 | for (ViewHolder holder : mPendingRemovals) { 119 | doAnimateRemove(holder); 120 | } 121 | mPendingRemovals.clear(); 122 | // Next, move stuff 123 | if (movesPending) { 124 | final ArrayList moves = new ArrayList(); 125 | moves.addAll(mPendingMoves); 126 | mMovesList.add(moves); 127 | mPendingMoves.clear(); 128 | Runnable mover = new Runnable() { 129 | @Override public void run() { 130 | for (MoveInfo moveInfo : moves) { 131 | animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY, moveInfo.toX, 132 | moveInfo.toY); 133 | } 134 | moves.clear(); 135 | mMovesList.remove(moves); 136 | } 137 | }; 138 | if (removalsPending) { 139 | View view = moves.get(0).holder.itemView; 140 | ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration()); 141 | } else { 142 | mover.run(); 143 | } 144 | } 145 | // Next, change stuff, to run in parallel with move animations 146 | if (changesPending) { 147 | final ArrayList changes = new ArrayList(); 148 | changes.addAll(mPendingChanges); 149 | mChangesList.add(changes); 150 | mPendingChanges.clear(); 151 | Runnable changer = new Runnable() { 152 | @Override public void run() { 153 | for (ChangeInfo change : changes) { 154 | animateChangeImpl(change); 155 | } 156 | changes.clear(); 157 | mChangesList.remove(changes); 158 | } 159 | }; 160 | if (removalsPending) { 161 | ViewHolder holder = changes.get(0).oldHolder; 162 | ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration()); 163 | } else { 164 | changer.run(); 165 | } 166 | } 167 | // Next, add stuff 168 | if (additionsPending) { 169 | final ArrayList additions = new ArrayList(); 170 | additions.addAll(mPendingAdditions); 171 | mAdditionsList.add(additions); 172 | mPendingAdditions.clear(); 173 | Runnable adder = new Runnable() { 174 | public void run() { 175 | for (ViewHolder holder : additions) { 176 | doAnimateAdd(holder); 177 | } 178 | additions.clear(); 179 | mAdditionsList.remove(additions); 180 | } 181 | }; 182 | if (removalsPending || movesPending || changesPending) { 183 | long removeDuration = removalsPending ? getRemoveDuration() : 0; 184 | long moveDuration = movesPending ? getMoveDuration() : 0; 185 | long changeDuration = changesPending ? getChangeDuration() : 0; 186 | long totalDelay = removeDuration + Math.max(moveDuration, changeDuration); 187 | View view = additions.get(0).itemView; 188 | ViewCompat.postOnAnimationDelayed(view, adder, totalDelay); 189 | } else { 190 | adder.run(); 191 | } 192 | } 193 | } 194 | 195 | protected void preAnimateRemoveImpl(final RecyclerView.ViewHolder holder) { 196 | } 197 | 198 | protected void preAnimateAddImpl(final RecyclerView.ViewHolder holder) { 199 | } 200 | 201 | protected abstract void animateRemoveImpl(final RecyclerView.ViewHolder holder); 202 | 203 | protected abstract void animateAddImpl(final RecyclerView.ViewHolder holder); 204 | 205 | private void preAnimateRemove(final RecyclerView.ViewHolder holder) { 206 | ViewHelper.clear(holder.itemView); 207 | 208 | if (holder instanceof AnimateViewHolder) { 209 | ((AnimateViewHolder) holder).preAnimateRemoveImpl(); 210 | } else { 211 | preAnimateRemoveImpl(holder); 212 | } 213 | } 214 | 215 | private void preAnimateAdd(final RecyclerView.ViewHolder holder) { 216 | ViewHelper.clear(holder.itemView); 217 | 218 | if (holder instanceof AnimateViewHolder) { 219 | ((AnimateViewHolder) holder).preAnimateAddImpl(); 220 | } else { 221 | preAnimateAddImpl(holder); 222 | } 223 | } 224 | 225 | private void doAnimateRemove(final RecyclerView.ViewHolder holder) { 226 | if (holder instanceof AnimateViewHolder) { 227 | ((AnimateViewHolder) holder).animateRemoveImpl(new DefaultRemoveVpaListener(holder)); 228 | } else { 229 | animateRemoveImpl(holder); 230 | } 231 | 232 | mRemoveAnimations.add(holder); 233 | } 234 | 235 | private void doAnimateAdd(final RecyclerView.ViewHolder holder) { 236 | if (holder instanceof AnimateViewHolder) { 237 | ((AnimateViewHolder) holder).animateAddImpl(new DefaultAddVpaListener(holder)); 238 | } else { 239 | animateAddImpl(holder); 240 | } 241 | 242 | mAddAnimations.add(holder); 243 | } 244 | 245 | @Override public boolean animateRemove(final ViewHolder holder) { 246 | endAnimation(holder); 247 | preAnimateRemove(holder); 248 | mPendingRemovals.add(holder); 249 | return true; 250 | } 251 | 252 | @Override public boolean animateAdd(final ViewHolder holder) { 253 | endAnimation(holder); 254 | preAnimateAdd(holder); 255 | mPendingAdditions.add(holder); 256 | return true; 257 | } 258 | 259 | @Override 260 | public boolean animateMove(final ViewHolder holder, int fromX, int fromY, int toX, int toY) { 261 | final View view = holder.itemView; 262 | fromX += ViewCompat.getTranslationX(holder.itemView); 263 | fromY += ViewCompat.getTranslationY(holder.itemView); 264 | endAnimation(holder); 265 | int deltaX = toX - fromX; 266 | int deltaY = toY - fromY; 267 | if (deltaX == 0 && deltaY == 0) { 268 | dispatchMoveFinished(holder); 269 | return false; 270 | } 271 | if (deltaX != 0) { 272 | ViewCompat.setTranslationX(view, -deltaX); 273 | } 274 | if (deltaY != 0) { 275 | ViewCompat.setTranslationY(view, -deltaY); 276 | } 277 | mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY)); 278 | return true; 279 | } 280 | 281 | private void animateMoveImpl(final ViewHolder holder, int fromX, int fromY, int toX, int toY) { 282 | final View view = holder.itemView; 283 | final int deltaX = toX - fromX; 284 | final int deltaY = toY - fromY; 285 | if (deltaX != 0) { 286 | ViewCompat.animate(view).translationX(0); 287 | } 288 | if (deltaY != 0) { 289 | ViewCompat.animate(view).translationY(0); 290 | } 291 | // TODO: make EndActions end listeners instead, since end actions aren't called when 292 | // vpas are canceled (and can't end them. why?) 293 | // need listener functionality in VPACompat for this. Ick. 294 | mMoveAnimations.add(holder); 295 | final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view); 296 | animation.setDuration(getMoveDuration()).setListener(new VpaListenerAdapter() { 297 | @Override public void onAnimationStart(View view) { 298 | dispatchMoveStarting(holder); 299 | } 300 | 301 | @Override public void onAnimationCancel(View view) { 302 | if (deltaX != 0) { 303 | ViewCompat.setTranslationX(view, 0); 304 | } 305 | if (deltaY != 0) { 306 | ViewCompat.setTranslationY(view, 0); 307 | } 308 | } 309 | 310 | @Override public void onAnimationEnd(View view) { 311 | animation.setListener(null); 312 | dispatchMoveFinished(holder); 313 | mMoveAnimations.remove(holder); 314 | dispatchFinishedWhenDone(); 315 | } 316 | }).start(); 317 | } 318 | 319 | @Override public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, 320 | ItemHolderInfo preLayoutInfo, ItemHolderInfo postLayoutInfo) { 321 | return false; 322 | } 323 | 324 | @Override 325 | public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, int fromX, int fromY, 326 | int toX, int toY) { 327 | final float prevTranslationX = ViewCompat.getTranslationX(oldHolder.itemView); 328 | final float prevTranslationY = ViewCompat.getTranslationY(oldHolder.itemView); 329 | final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView); 330 | endAnimation(oldHolder); 331 | int deltaX = (int) (toX - fromX - prevTranslationX); 332 | int deltaY = (int) (toY - fromY - prevTranslationY); 333 | // recover prev translation state after ending animation 334 | ViewCompat.setTranslationX(oldHolder.itemView, prevTranslationX); 335 | ViewCompat.setTranslationY(oldHolder.itemView, prevTranslationY); 336 | ViewCompat.setAlpha(oldHolder.itemView, prevAlpha); 337 | if (newHolder != null && newHolder.itemView != null) { 338 | // carry over translation values 339 | endAnimation(newHolder); 340 | ViewCompat.setTranslationX(newHolder.itemView, -deltaX); 341 | ViewCompat.setTranslationY(newHolder.itemView, -deltaY); 342 | ViewCompat.setAlpha(newHolder.itemView, 0); 343 | } 344 | mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY)); 345 | return true; 346 | } 347 | 348 | private void animateChangeImpl(final ChangeInfo changeInfo) { 349 | final ViewHolder holder = changeInfo.oldHolder; 350 | final View view = holder == null ? null : holder.itemView; 351 | final ViewHolder newHolder = changeInfo.newHolder; 352 | final View newView = newHolder != null ? newHolder.itemView : null; 353 | if (view != null) { 354 | mChangeAnimations.add(changeInfo.oldHolder); 355 | final ViewPropertyAnimatorCompat oldViewAnim = 356 | ViewCompat.animate(view).setDuration(getChangeDuration()); 357 | oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX); 358 | oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY); 359 | oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() { 360 | @Override public void onAnimationStart(View view) { 361 | dispatchChangeStarting(changeInfo.oldHolder, true); 362 | } 363 | 364 | @Override public void onAnimationEnd(View view) { 365 | oldViewAnim.setListener(null); 366 | ViewCompat.setAlpha(view, 1); 367 | ViewCompat.setTranslationX(view, 0); 368 | ViewCompat.setTranslationY(view, 0); 369 | dispatchChangeFinished(changeInfo.oldHolder, true); 370 | mChangeAnimations.remove(changeInfo.oldHolder); 371 | dispatchFinishedWhenDone(); 372 | } 373 | }).start(); 374 | } 375 | if (newView != null) { 376 | mChangeAnimations.add(changeInfo.newHolder); 377 | final ViewPropertyAnimatorCompat newViewAnimation = ViewCompat.animate(newView); 378 | newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()). 379 | alpha(1).setListener(new VpaListenerAdapter() { 380 | @Override public void onAnimationStart(View view) { 381 | dispatchChangeStarting(changeInfo.newHolder, false); 382 | } 383 | 384 | @Override public void onAnimationEnd(View view) { 385 | newViewAnimation.setListener(null); 386 | ViewCompat.setAlpha(newView, 1); 387 | ViewCompat.setTranslationX(newView, 0); 388 | ViewCompat.setTranslationY(newView, 0); 389 | dispatchChangeFinished(changeInfo.newHolder, false); 390 | mChangeAnimations.remove(changeInfo.newHolder); 391 | dispatchFinishedWhenDone(); 392 | } 393 | }).start(); 394 | } 395 | } 396 | 397 | private void endChangeAnimation(List infoList, ViewHolder item) { 398 | for (int i = infoList.size() - 1; i >= 0; i--) { 399 | ChangeInfo changeInfo = infoList.get(i); 400 | if (endChangeAnimationIfNecessary(changeInfo, item)) { 401 | if (changeInfo.oldHolder == null && changeInfo.newHolder == null) { 402 | infoList.remove(changeInfo); 403 | } 404 | } 405 | } 406 | } 407 | 408 | private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) { 409 | if (changeInfo.oldHolder != null) { 410 | endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder); 411 | } 412 | if (changeInfo.newHolder != null) { 413 | endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder); 414 | } 415 | } 416 | 417 | private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, ViewHolder item) { 418 | boolean oldItem = false; 419 | if (changeInfo.newHolder == item) { 420 | changeInfo.newHolder = null; 421 | } else if (changeInfo.oldHolder == item) { 422 | changeInfo.oldHolder = null; 423 | oldItem = true; 424 | } else { 425 | return false; 426 | } 427 | ViewCompat.setAlpha(item.itemView, 1); 428 | ViewCompat.setTranslationX(item.itemView, 0); 429 | ViewCompat.setTranslationY(item.itemView, 0); 430 | dispatchChangeFinished(item, oldItem); 431 | return true; 432 | } 433 | 434 | @Override public void endAnimation(ViewHolder item) { 435 | final View view = item.itemView; 436 | // this will trigger end callback which should set properties to their target values. 437 | ViewCompat.animate(view).cancel(); 438 | // TODO if some other animations are chained to end, how do we cancel them as well? 439 | for (int i = mPendingMoves.size() - 1; i >= 0; i--) { 440 | MoveInfo moveInfo = mPendingMoves.get(i); 441 | if (moveInfo.holder == item) { 442 | ViewCompat.setTranslationY(view, 0); 443 | ViewCompat.setTranslationX(view, 0); 444 | dispatchMoveFinished(item); 445 | mPendingMoves.remove(i); 446 | } 447 | } 448 | endChangeAnimation(mPendingChanges, item); 449 | if (mPendingRemovals.remove(item)) { 450 | ViewHelper.clear(item.itemView); 451 | dispatchRemoveFinished(item); 452 | } 453 | if (mPendingAdditions.remove(item)) { 454 | ViewHelper.clear(item.itemView); 455 | dispatchAddFinished(item); 456 | } 457 | 458 | for (int i = mChangesList.size() - 1; i >= 0; i--) { 459 | ArrayList changes = mChangesList.get(i); 460 | endChangeAnimation(changes, item); 461 | if (changes.isEmpty()) { 462 | mChangesList.remove(i); 463 | } 464 | } 465 | for (int i = mMovesList.size() - 1; i >= 0; i--) { 466 | ArrayList moves = mMovesList.get(i); 467 | for (int j = moves.size() - 1; j >= 0; j--) { 468 | MoveInfo moveInfo = moves.get(j); 469 | if (moveInfo.holder == item) { 470 | ViewCompat.setTranslationY(view, 0); 471 | ViewCompat.setTranslationX(view, 0); 472 | dispatchMoveFinished(item); 473 | moves.remove(j); 474 | if (moves.isEmpty()) { 475 | mMovesList.remove(i); 476 | } 477 | break; 478 | } 479 | } 480 | } 481 | for (int i = mAdditionsList.size() - 1; i >= 0; i--) { 482 | ArrayList additions = mAdditionsList.get(i); 483 | if (additions.remove(item)) { 484 | ViewHelper.clear(item.itemView); 485 | dispatchAddFinished(item); 486 | if (additions.isEmpty()) { 487 | mAdditionsList.remove(i); 488 | } 489 | } 490 | } 491 | 492 | // animations should be ended by the cancel above. 493 | if (mRemoveAnimations.remove(item) && DEBUG) { 494 | throw new IllegalStateException( 495 | "after animation is cancelled, item should not be in " + "mRemoveAnimations list"); 496 | } 497 | 498 | if (mAddAnimations.remove(item) && DEBUG) { 499 | throw new IllegalStateException( 500 | "after animation is cancelled, item should not be in " + "mAddAnimations list"); 501 | } 502 | 503 | if (mChangeAnimations.remove(item) && DEBUG) { 504 | throw new IllegalStateException( 505 | "after animation is cancelled, item should not be in " + "mChangeAnimations list"); 506 | } 507 | 508 | if (mMoveAnimations.remove(item) && DEBUG) { 509 | throw new IllegalStateException( 510 | "after animation is cancelled, item should not be in " + "mMoveAnimations list"); 511 | } 512 | dispatchFinishedWhenDone(); 513 | } 514 | 515 | @Override public boolean isRunning() { 516 | return (!mPendingAdditions.isEmpty() || 517 | !mPendingChanges.isEmpty() || 518 | !mPendingMoves.isEmpty() || 519 | !mPendingRemovals.isEmpty() || 520 | !mMoveAnimations.isEmpty() || 521 | !mRemoveAnimations.isEmpty() || 522 | !mAddAnimations.isEmpty() || 523 | !mChangeAnimations.isEmpty() || 524 | !mMovesList.isEmpty() || 525 | !mAdditionsList.isEmpty() || 526 | !mChangesList.isEmpty()); 527 | } 528 | 529 | /** 530 | * Check the state of currently pending and running animations. If there are none 531 | * pending/running, call #dispatchAnimationsFinished() to notify any 532 | * listeners. 533 | */ 534 | private void dispatchFinishedWhenDone() { 535 | if (!isRunning()) { 536 | dispatchAnimationsFinished(); 537 | } 538 | } 539 | 540 | @Override public void endAnimations() { 541 | int count = mPendingMoves.size(); 542 | for (int i = count - 1; i >= 0; i--) { 543 | MoveInfo item = mPendingMoves.get(i); 544 | View view = item.holder.itemView; 545 | ViewCompat.setTranslationY(view, 0); 546 | ViewCompat.setTranslationX(view, 0); 547 | dispatchMoveFinished(item.holder); 548 | mPendingMoves.remove(i); 549 | } 550 | count = mPendingRemovals.size(); 551 | for (int i = count - 1; i >= 0; i--) { 552 | ViewHolder item = mPendingRemovals.get(i); 553 | dispatchRemoveFinished(item); 554 | mPendingRemovals.remove(i); 555 | } 556 | count = mPendingAdditions.size(); 557 | for (int i = count - 1; i >= 0; i--) { 558 | ViewHolder item = mPendingAdditions.get(i); 559 | ViewHelper.clear(item.itemView); 560 | dispatchAddFinished(item); 561 | mPendingAdditions.remove(i); 562 | } 563 | count = mPendingChanges.size(); 564 | for (int i = count - 1; i >= 0; i--) { 565 | endChangeAnimationIfNecessary(mPendingChanges.get(i)); 566 | } 567 | mPendingChanges.clear(); 568 | if (!isRunning()) { 569 | return; 570 | } 571 | 572 | int listCount = mMovesList.size(); 573 | for (int i = listCount - 1; i >= 0; i--) { 574 | ArrayList moves = mMovesList.get(i); 575 | count = moves.size(); 576 | for (int j = count - 1; j >= 0; j--) { 577 | MoveInfo moveInfo = moves.get(j); 578 | ViewHolder item = moveInfo.holder; 579 | View view = item.itemView; 580 | ViewCompat.setTranslationY(view, 0); 581 | ViewCompat.setTranslationX(view, 0); 582 | dispatchMoveFinished(moveInfo.holder); 583 | moves.remove(j); 584 | if (moves.isEmpty()) { 585 | mMovesList.remove(moves); 586 | } 587 | } 588 | } 589 | listCount = mAdditionsList.size(); 590 | for (int i = listCount - 1; i >= 0; i--) { 591 | ArrayList additions = mAdditionsList.get(i); 592 | count = additions.size(); 593 | for (int j = count - 1; j >= 0; j--) { 594 | ViewHolder item = additions.get(j); 595 | View view = item.itemView; 596 | ViewCompat.setAlpha(view, 1); 597 | dispatchAddFinished(item); 598 | additions.remove(j); 599 | if (additions.isEmpty()) { 600 | mAdditionsList.remove(additions); 601 | } 602 | } 603 | } 604 | listCount = mChangesList.size(); 605 | for (int i = listCount - 1; i >= 0; i--) { 606 | ArrayList changes = mChangesList.get(i); 607 | count = changes.size(); 608 | for (int j = count - 1; j >= 0; j--) { 609 | endChangeAnimationIfNecessary(changes.get(j)); 610 | if (changes.isEmpty()) { 611 | mChangesList.remove(changes); 612 | } 613 | } 614 | } 615 | 616 | cancelAll(mRemoveAnimations); 617 | cancelAll(mMoveAnimations); 618 | cancelAll(mAddAnimations); 619 | cancelAll(mChangeAnimations); 620 | 621 | dispatchAnimationsFinished(); 622 | } 623 | 624 | void cancelAll(List viewHolders) { 625 | for (int i = viewHolders.size() - 1; i >= 0; i--) { 626 | ViewCompat.animate(viewHolders.get(i).itemView).cancel(); 627 | } 628 | } 629 | 630 | private static class VpaListenerAdapter implements ViewPropertyAnimatorListener { 631 | 632 | @Override public void onAnimationStart(View view) { 633 | } 634 | 635 | @Override public void onAnimationEnd(View view) { 636 | } 637 | 638 | @Override public void onAnimationCancel(View view) { 639 | } 640 | } 641 | 642 | protected class DefaultAddVpaListener extends VpaListenerAdapter { 643 | 644 | RecyclerView.ViewHolder mViewHolder; 645 | 646 | public DefaultAddVpaListener(final RecyclerView.ViewHolder holder) { 647 | mViewHolder = holder; 648 | } 649 | 650 | @Override public void onAnimationStart(View view) { 651 | dispatchAddStarting(mViewHolder); 652 | } 653 | 654 | @Override public void onAnimationCancel(View view) { 655 | ViewHelper.clear(view); 656 | } 657 | 658 | @Override public void onAnimationEnd(View view) { 659 | ViewHelper.clear(view); 660 | dispatchAddFinished(mViewHolder); 661 | mAddAnimations.remove(mViewHolder); 662 | dispatchFinishedWhenDone(); 663 | } 664 | } 665 | 666 | protected class DefaultRemoveVpaListener extends VpaListenerAdapter { 667 | 668 | RecyclerView.ViewHolder mViewHolder; 669 | 670 | public DefaultRemoveVpaListener(final RecyclerView.ViewHolder holder) { 671 | mViewHolder = holder; 672 | } 673 | 674 | @Override public void onAnimationStart(View view) { 675 | dispatchRemoveStarting(mViewHolder); 676 | } 677 | 678 | @Override public void onAnimationCancel(View view) { 679 | ViewHelper.clear(view); 680 | } 681 | 682 | @Override public void onAnimationEnd(View view) { 683 | ViewHelper.clear(view); 684 | dispatchRemoveFinished(mViewHolder); 685 | mRemoveAnimations.remove(mViewHolder); 686 | dispatchFinishedWhenDone(); 687 | } 688 | } 689 | } 690 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/FadeInAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class FadeInAnimator extends BaseItemAnimator { 24 | 25 | public FadeInAnimator() { 26 | } 27 | 28 | public FadeInAnimator(Interpolator interpolator) { 29 | mInterpolator = interpolator; 30 | } 31 | 32 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 33 | ViewCompat.animate(holder.itemView) 34 | .alpha(0) 35 | .setDuration(getRemoveDuration()) 36 | .setInterpolator(mInterpolator) 37 | .setListener(new DefaultRemoveVpaListener(holder)) 38 | .start(); 39 | } 40 | 41 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 42 | ViewCompat.setAlpha(holder.itemView, 0); 43 | } 44 | 45 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 46 | ViewCompat.animate(holder.itemView) 47 | .alpha(1) 48 | .setDuration(getAddDuration()) 49 | .setInterpolator(mInterpolator) 50 | .setListener(new DefaultAddVpaListener(holder)) 51 | .start(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/FadeInDownAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class FadeInDownAnimator extends BaseItemAnimator { 24 | 25 | public FadeInDownAnimator() { 26 | } 27 | 28 | public FadeInDownAnimator(Interpolator interpolator) { 29 | mInterpolator = interpolator; 30 | } 31 | 32 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 33 | ViewCompat.animate(holder.itemView) 34 | .translationY(-holder.itemView.getHeight() * .25f) 35 | .alpha(0) 36 | .setDuration(getRemoveDuration()) 37 | .setInterpolator(mInterpolator) 38 | .setListener(new DefaultRemoveVpaListener(holder)) 39 | .start(); 40 | } 41 | 42 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 43 | ViewCompat.setTranslationY(holder.itemView, -holder.itemView.getHeight() * .25f); 44 | ViewCompat.setAlpha(holder.itemView, 0); 45 | } 46 | 47 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 48 | ViewCompat.animate(holder.itemView) 49 | .translationY(0) 50 | .alpha(1) 51 | .setDuration(getAddDuration()) 52 | .setInterpolator(mInterpolator) 53 | .setListener(new DefaultAddVpaListener(holder)) 54 | .start(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/FadeInLeftAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class FadeInLeftAnimator extends BaseItemAnimator { 24 | 25 | public FadeInLeftAnimator() { 26 | } 27 | 28 | public FadeInLeftAnimator(Interpolator interpolator) { 29 | mInterpolator = interpolator; 30 | } 31 | 32 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 33 | ViewCompat.animate(holder.itemView) 34 | .translationX(-holder.itemView.getRootView().getWidth() * .25f) 35 | .alpha(0) 36 | .setDuration(getRemoveDuration()) 37 | .setInterpolator(mInterpolator) 38 | .setListener(new DefaultRemoveVpaListener(holder)) 39 | .start(); 40 | } 41 | 42 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 43 | ViewCompat.setTranslationX(holder.itemView, -holder.itemView.getRootView().getWidth() * .25f); 44 | ViewCompat.setAlpha(holder.itemView, 0); 45 | } 46 | 47 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 48 | ViewCompat.animate(holder.itemView) 49 | .translationX(0) 50 | .alpha(1) 51 | .setDuration(getAddDuration()) 52 | .setInterpolator(mInterpolator) 53 | .setListener(new DefaultAddVpaListener(holder)) 54 | .start(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/FadeInRightAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class FadeInRightAnimator extends BaseItemAnimator { 24 | 25 | public FadeInRightAnimator() { 26 | } 27 | 28 | public FadeInRightAnimator(Interpolator interpolator) { 29 | mInterpolator = interpolator; 30 | } 31 | 32 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 33 | ViewCompat.animate(holder.itemView) 34 | .translationX(holder.itemView.getRootView().getWidth() * .25f) 35 | .alpha(0) 36 | .setDuration(getRemoveDuration()) 37 | .setInterpolator(mInterpolator) 38 | .setListener(new DefaultRemoveVpaListener(holder)) 39 | .start(); 40 | } 41 | 42 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 43 | ViewCompat.setTranslationX(holder.itemView, holder.itemView.getRootView().getWidth() * .25f); 44 | ViewCompat.setAlpha(holder.itemView, 0); 45 | } 46 | 47 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 48 | ViewCompat.animate(holder.itemView) 49 | .translationX(0) 50 | .alpha(1) 51 | .setDuration(getAddDuration()) 52 | .setInterpolator(mInterpolator) 53 | .setListener(new DefaultAddVpaListener(holder)) 54 | .start(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/FadeInUpAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class FadeInUpAnimator extends BaseItemAnimator { 24 | 25 | public FadeInUpAnimator() { 26 | } 27 | 28 | public FadeInUpAnimator(Interpolator interpolator) { 29 | mInterpolator = interpolator; 30 | } 31 | 32 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 33 | ViewCompat.animate(holder.itemView) 34 | .translationY(holder.itemView.getHeight() * .25f) 35 | .alpha(0) 36 | .setDuration(getRemoveDuration()) 37 | .setInterpolator(mInterpolator) 38 | .setListener(new DefaultRemoveVpaListener(holder)) 39 | .start(); 40 | } 41 | 42 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 43 | ViewCompat.setTranslationY(holder.itemView, holder.itemView.getHeight() * .25f); 44 | ViewCompat.setAlpha(holder.itemView, 0); 45 | } 46 | 47 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 48 | ViewCompat.animate(holder.itemView) 49 | .translationY(0) 50 | .alpha(1) 51 | .setDuration(getAddDuration()) 52 | .setInterpolator(mInterpolator) 53 | .setListener(new DefaultAddVpaListener(holder)) 54 | .start(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/FlipInBottomXAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class FlipInBottomXAnimator extends BaseItemAnimator { 24 | 25 | public FlipInBottomXAnimator() { 26 | } 27 | 28 | public FlipInBottomXAnimator(Interpolator interpolator) { 29 | mInterpolator = interpolator; 30 | } 31 | 32 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 33 | ViewCompat.animate(holder.itemView) 34 | .rotationX(-90) 35 | .setDuration(getRemoveDuration()) 36 | .setInterpolator(mInterpolator) 37 | .setListener(new DefaultRemoveVpaListener(holder)) 38 | .start(); 39 | } 40 | 41 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 42 | ViewCompat.setRotationX(holder.itemView, -90); 43 | } 44 | 45 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 46 | ViewCompat.animate(holder.itemView) 47 | .rotationX(0) 48 | .setDuration(getAddDuration()) 49 | .setInterpolator(mInterpolator) 50 | .setListener(new DefaultAddVpaListener(holder)) 51 | .start(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/FlipInLeftYAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class FlipInLeftYAnimator extends BaseItemAnimator { 24 | 25 | public FlipInLeftYAnimator() { 26 | } 27 | 28 | public FlipInLeftYAnimator(Interpolator interpolator) { 29 | mInterpolator = interpolator; 30 | } 31 | 32 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 33 | ViewCompat.animate(holder.itemView) 34 | .rotationY(90) 35 | .setDuration(getRemoveDuration()) 36 | .setInterpolator(mInterpolator) 37 | .setListener(new DefaultRemoveVpaListener(holder)) 38 | .start(); 39 | } 40 | 41 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 42 | ViewCompat.setRotationY(holder.itemView, 90); 43 | } 44 | 45 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 46 | ViewCompat.animate(holder.itemView) 47 | .rotationY(0) 48 | .setDuration(getAddDuration()) 49 | .setInterpolator(mInterpolator) 50 | .setListener(new DefaultAddVpaListener(holder)) 51 | .start(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/FlipInRightYAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class FlipInRightYAnimator extends BaseItemAnimator { 24 | 25 | public FlipInRightYAnimator() { 26 | } 27 | 28 | public FlipInRightYAnimator(Interpolator interpolator) { 29 | mInterpolator = interpolator; 30 | } 31 | 32 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 33 | ViewCompat.animate(holder.itemView) 34 | .rotationY(-90) 35 | .setDuration(getRemoveDuration()) 36 | .setInterpolator(mInterpolator) 37 | .setListener(new DefaultRemoveVpaListener(holder)) 38 | .start(); 39 | } 40 | 41 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 42 | ViewCompat.setRotationY(holder.itemView, -90); 43 | } 44 | 45 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 46 | ViewCompat.animate(holder.itemView) 47 | .rotationY(0) 48 | .setDuration(getAddDuration()) 49 | .setInterpolator(mInterpolator) 50 | .setListener(new DefaultAddVpaListener(holder)) 51 | .start(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/FlipInTopXAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class FlipInTopXAnimator extends BaseItemAnimator { 24 | 25 | public FlipInTopXAnimator() { 26 | } 27 | 28 | public FlipInTopXAnimator(Interpolator interpolator) { 29 | mInterpolator = interpolator; 30 | } 31 | 32 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 33 | ViewCompat.animate(holder.itemView) 34 | .rotationX(90) 35 | .setDuration(getRemoveDuration()) 36 | .setInterpolator(mInterpolator) 37 | .setListener(new DefaultRemoveVpaListener(holder)) 38 | .start(); 39 | } 40 | 41 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 42 | ViewCompat.setRotationX(holder.itemView, 90); 43 | } 44 | 45 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 46 | ViewCompat.animate(holder.itemView) 47 | .rotationX(0) 48 | .setDuration(getAddDuration()) 49 | .setInterpolator(mInterpolator) 50 | .setListener(new DefaultAddVpaListener(holder)) 51 | .start(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/LandingAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class LandingAnimator extends BaseItemAnimator { 24 | 25 | public LandingAnimator() { 26 | } 27 | 28 | public LandingAnimator(Interpolator interpolator) { 29 | mInterpolator = interpolator; 30 | } 31 | 32 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 33 | ViewCompat.animate(holder.itemView) 34 | .alpha(0) 35 | .scaleX(1.5f) 36 | .scaleY(1.5f) 37 | .setDuration(getRemoveDuration()) 38 | .setInterpolator(mInterpolator) 39 | .setListener(new DefaultRemoveVpaListener(holder)) 40 | .start(); 41 | } 42 | 43 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 44 | ViewCompat.setAlpha(holder.itemView, 0); 45 | ViewCompat.setScaleX(holder.itemView, 1.5f); 46 | ViewCompat.setScaleY(holder.itemView, 1.5f); 47 | } 48 | 49 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 50 | ViewCompat.animate(holder.itemView) 51 | .alpha(1) 52 | .scaleX(1) 53 | .scaleY(1) 54 | .setDuration(getAddDuration()) 55 | .setInterpolator(mInterpolator) 56 | .setListener(new DefaultAddVpaListener(holder)) 57 | .start(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/OvershootInLeftAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.OvershootInterpolator; 22 | 23 | public class OvershootInLeftAnimator extends BaseItemAnimator { 24 | 25 | private final float mTension; 26 | 27 | public OvershootInLeftAnimator() { 28 | mTension = 2.0f; 29 | } 30 | 31 | public OvershootInLeftAnimator(float mTension) { 32 | this.mTension = mTension; 33 | } 34 | 35 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 36 | ViewCompat.animate(holder.itemView) 37 | .translationX(-holder.itemView.getRootView().getWidth()) 38 | .setDuration(getRemoveDuration()) 39 | .setListener(new DefaultRemoveVpaListener(holder)) 40 | .start(); 41 | } 42 | 43 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 44 | ViewCompat.setTranslationX(holder.itemView, -holder.itemView.getRootView().getWidth()); 45 | } 46 | 47 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 48 | ViewCompat.animate(holder.itemView) 49 | .translationX(0) 50 | .setDuration(getAddDuration()) 51 | .setListener(new DefaultAddVpaListener(holder)) 52 | .setInterpolator(new OvershootInterpolator(mTension)) 53 | .start(); 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/OvershootInRightAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.OvershootInterpolator; 22 | 23 | public class OvershootInRightAnimator extends BaseItemAnimator { 24 | 25 | private final float mTension; 26 | 27 | public OvershootInRightAnimator() { 28 | mTension = 2.0f; 29 | } 30 | 31 | public OvershootInRightAnimator(float mTension) { 32 | this.mTension = mTension; 33 | } 34 | 35 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 36 | ViewCompat.animate(holder.itemView) 37 | .translationX(holder.itemView.getRootView().getWidth()) 38 | .setDuration(getRemoveDuration()) 39 | .setListener(new DefaultRemoveVpaListener(holder)) 40 | .start(); 41 | } 42 | 43 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 44 | ViewCompat.setTranslationX(holder.itemView, holder.itemView.getRootView().getWidth()); 45 | } 46 | 47 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 48 | ViewCompat.animate(holder.itemView) 49 | .translationX(0) 50 | .setDuration(getAddDuration()) 51 | .setInterpolator(new OvershootInterpolator(mTension)) 52 | .setListener(new DefaultAddVpaListener(holder)) 53 | .start(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/ScaleInAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class ScaleInAnimator extends BaseItemAnimator { 24 | 25 | public ScaleInAnimator() { 26 | } 27 | 28 | public ScaleInAnimator(Interpolator interpolator) { 29 | mInterpolator = interpolator; 30 | } 31 | 32 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 33 | ViewCompat.animate(holder.itemView) 34 | .scaleX(0) 35 | .scaleY(0) 36 | .setDuration(getRemoveDuration()) 37 | .setInterpolator(mInterpolator) 38 | .setListener(new DefaultRemoveVpaListener(holder)) 39 | .start(); 40 | } 41 | 42 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 43 | ViewCompat.setScaleX(holder.itemView, 0); 44 | ViewCompat.setScaleY(holder.itemView, 0); 45 | } 46 | 47 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 48 | ViewCompat.animate(holder.itemView) 49 | .scaleX(1) 50 | .scaleY(1) 51 | .setDuration(getAddDuration()) 52 | .setInterpolator(mInterpolator) 53 | .setListener(new DefaultAddVpaListener(holder)) 54 | .start(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/ScaleInBottomAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class ScaleInBottomAnimator extends BaseItemAnimator { 24 | 25 | public ScaleInBottomAnimator() { 26 | } 27 | 28 | public ScaleInBottomAnimator(Interpolator interpolator) { 29 | mInterpolator = interpolator; 30 | } 31 | 32 | @Override protected void preAnimateRemoveImpl(RecyclerView.ViewHolder holder) { 33 | // @TODO https://code.google.com/p/android/issues/detail?id=80863 34 | // ViewCompat.setPivotY(holder.itemView, holder.itemView.getHeight()); 35 | holder.itemView.setPivotY(holder.itemView.getHeight()); 36 | } 37 | 38 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 39 | ViewCompat.animate(holder.itemView) 40 | .scaleX(0) 41 | .scaleY(0) 42 | .setDuration(getRemoveDuration()) 43 | .setInterpolator(mInterpolator) 44 | .setListener(new DefaultRemoveVpaListener(holder)) 45 | .start(); 46 | } 47 | 48 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 49 | // @TODO https://code.google.com/p/android/issues/detail?id=80863 50 | // ViewCompat.setPivotY(holder.itemView, holder.itemView.getHeight()); 51 | holder.itemView.setPivotY(holder.itemView.getHeight()); 52 | ViewCompat.setScaleX(holder.itemView, 0); 53 | ViewCompat.setScaleY(holder.itemView, 0); 54 | } 55 | 56 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 57 | ViewCompat.animate(holder.itemView) 58 | .scaleX(1) 59 | .scaleY(1) 60 | .setDuration(getAddDuration()) 61 | .setInterpolator(mInterpolator) 62 | .setListener(new DefaultAddVpaListener(holder)) 63 | .start(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/ScaleInLeftAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class ScaleInLeftAnimator extends BaseItemAnimator { 24 | 25 | public ScaleInLeftAnimator() { 26 | } 27 | 28 | public ScaleInLeftAnimator(Interpolator interpolator) { 29 | mInterpolator = interpolator; 30 | } 31 | 32 | @Override protected void preAnimateRemoveImpl(RecyclerView.ViewHolder holder) { 33 | ViewCompat.setPivotX(holder.itemView, 0); 34 | } 35 | 36 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 37 | ViewCompat.animate(holder.itemView) 38 | .scaleX(0) 39 | .scaleY(0) 40 | .setDuration(getRemoveDuration()) 41 | .setInterpolator(mInterpolator) 42 | .setListener(new DefaultRemoveVpaListener(holder)) 43 | .start(); 44 | } 45 | 46 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 47 | ViewCompat.setPivotX(holder.itemView, 0); 48 | ViewCompat.setScaleX(holder.itemView, 0); 49 | ViewCompat.setScaleY(holder.itemView, 0); 50 | } 51 | 52 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 53 | ViewCompat.animate(holder.itemView) 54 | .scaleX(1) 55 | .scaleY(1) 56 | .setDuration(getAddDuration()) 57 | .setInterpolator(mInterpolator) 58 | .setListener(new DefaultAddVpaListener(holder)) 59 | .start(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/ScaleInRightAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class ScaleInRightAnimator extends BaseItemAnimator { 24 | 25 | public ScaleInRightAnimator() { 26 | } 27 | 28 | public ScaleInRightAnimator(Interpolator interpolator) { 29 | mInterpolator = interpolator; 30 | } 31 | 32 | @Override protected void preAnimateRemoveImpl(RecyclerView.ViewHolder holder) { 33 | ViewCompat.setPivotX(holder.itemView, holder.itemView.getWidth()); 34 | } 35 | 36 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 37 | ViewCompat.animate(holder.itemView) 38 | .scaleX(0) 39 | .scaleY(0) 40 | .setDuration(getRemoveDuration()) 41 | .setInterpolator(mInterpolator) 42 | .setListener(new DefaultRemoveVpaListener(holder)) 43 | .start(); 44 | } 45 | 46 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 47 | ViewCompat.setPivotX(holder.itemView, holder.itemView.getWidth()); 48 | ViewCompat.setScaleX(holder.itemView, 0); 49 | ViewCompat.setScaleY(holder.itemView, 0); 50 | } 51 | 52 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 53 | ViewCompat.animate(holder.itemView) 54 | .scaleX(1) 55 | .scaleY(1) 56 | .setDuration(getAddDuration()) 57 | .setInterpolator(mInterpolator) 58 | .setListener(new DefaultAddVpaListener(holder)) 59 | .start(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/ScaleInTopAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class ScaleInTopAnimator extends BaseItemAnimator { 24 | 25 | public ScaleInTopAnimator() { 26 | } 27 | 28 | public ScaleInTopAnimator(Interpolator interpolator) { 29 | mInterpolator = interpolator; 30 | } 31 | 32 | @Override protected void preAnimateRemoveImpl(RecyclerView.ViewHolder holder) { 33 | // @TODO https://code.google.com/p/android/issues/detail?id=80863 34 | // ViewCompat.setPivotY(holder.itemView, 0); 35 | holder.itemView.setPivotY(0); 36 | } 37 | 38 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 39 | ViewCompat.animate(holder.itemView) 40 | .scaleX(0) 41 | .scaleY(0) 42 | .setDuration(getRemoveDuration()) 43 | .setInterpolator(mInterpolator) 44 | .setListener(new DefaultRemoveVpaListener(holder)) 45 | .start(); 46 | } 47 | 48 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 49 | // @TODO https://code.google.com/p/android/issues/detail?id=80863 50 | // ViewCompat.setPivotY(holder.itemView, 0); 51 | holder.itemView.setPivotY(0); 52 | ViewCompat.setScaleX(holder.itemView, 0); 53 | ViewCompat.setScaleY(holder.itemView, 0); 54 | } 55 | 56 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 57 | ViewCompat.animate(holder.itemView) 58 | .scaleX(1) 59 | .scaleY(1) 60 | .setDuration(getAddDuration()) 61 | .setInterpolator(mInterpolator) 62 | .setListener(new DefaultAddVpaListener(holder)) 63 | .start(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/SlideInDownAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class SlideInDownAnimator extends BaseItemAnimator { 24 | 25 | public SlideInDownAnimator() { 26 | 27 | } 28 | 29 | public SlideInDownAnimator(Interpolator interpolator) { 30 | mInterpolator = interpolator; 31 | } 32 | 33 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 34 | ViewCompat.animate(holder.itemView) 35 | .translationY(-holder.itemView.getHeight()) 36 | .alpha(0) 37 | .setDuration(getRemoveDuration()) 38 | .setInterpolator(mInterpolator) 39 | .setListener(new DefaultRemoveVpaListener(holder)) 40 | .start(); 41 | } 42 | 43 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 44 | ViewCompat.setTranslationY(holder.itemView, -holder.itemView.getHeight()); 45 | ViewCompat.setAlpha(holder.itemView, 0); 46 | } 47 | 48 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 49 | ViewCompat.animate(holder.itemView) 50 | .translationY(0) 51 | .alpha(1) 52 | .setDuration(getAddDuration()) 53 | .setInterpolator(mInterpolator) 54 | .setListener(new DefaultAddVpaListener(holder)) 55 | .start(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/SlideInLeftAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class SlideInLeftAnimator extends BaseItemAnimator { 24 | 25 | public SlideInLeftAnimator() { 26 | 27 | } 28 | 29 | public SlideInLeftAnimator(Interpolator interpolator) { 30 | mInterpolator = interpolator; 31 | } 32 | 33 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 34 | ViewCompat.animate(holder.itemView) 35 | .translationX(-holder.itemView.getRootView().getWidth()) 36 | .setDuration(getRemoveDuration()) 37 | .setInterpolator(mInterpolator) 38 | .setListener(new DefaultRemoveVpaListener(holder)) 39 | .start(); 40 | } 41 | 42 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 43 | ViewCompat.setTranslationX(holder.itemView, -holder.itemView.getRootView().getWidth()); 44 | } 45 | 46 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 47 | ViewCompat.animate(holder.itemView) 48 | .translationX(0) 49 | .setDuration(getAddDuration()) 50 | .setInterpolator(mInterpolator) 51 | .setListener(new DefaultAddVpaListener(holder)) 52 | .start(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/SlideInRightAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class SlideInRightAnimator extends BaseItemAnimator { 24 | 25 | public SlideInRightAnimator() { 26 | 27 | } 28 | 29 | public SlideInRightAnimator(Interpolator interpolator) { 30 | mInterpolator = interpolator; 31 | } 32 | 33 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 34 | ViewCompat.animate(holder.itemView) 35 | .translationX(holder.itemView.getRootView().getWidth()) 36 | .setDuration(getRemoveDuration()) 37 | .setInterpolator(mInterpolator) 38 | .setListener(new DefaultRemoveVpaListener(holder)) 39 | .start(); 40 | } 41 | 42 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 43 | ViewCompat.setTranslationX(holder.itemView, holder.itemView.getRootView().getWidth()); 44 | } 45 | 46 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 47 | ViewCompat.animate(holder.itemView) 48 | .translationX(0) 49 | .setDuration(getAddDuration()) 50 | .setInterpolator(mInterpolator) 51 | .setListener(new DefaultAddVpaListener(holder)) 52 | .start(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/SlideInUpAnimator.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators; 2 | 3 | /** 4 | * Copyright (C) 2015 Wasabeef 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v4.view.ViewCompat; 20 | import android.support.v7.widget.RecyclerView; 21 | import android.view.animation.Interpolator; 22 | 23 | public class SlideInUpAnimator extends BaseItemAnimator { 24 | 25 | public SlideInUpAnimator() { 26 | 27 | } 28 | 29 | public SlideInUpAnimator(Interpolator interpolator) { 30 | mInterpolator = interpolator; 31 | } 32 | 33 | @Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) { 34 | ViewCompat.animate(holder.itemView) 35 | .translationY(holder.itemView.getHeight()) 36 | .alpha(0) 37 | .setDuration(getRemoveDuration()) 38 | .setInterpolator(mInterpolator) 39 | .setListener(new DefaultRemoveVpaListener(holder)) 40 | .start(); 41 | } 42 | 43 | @Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) { 44 | ViewCompat.setTranslationY(holder.itemView, holder.itemView.getHeight()); 45 | ViewCompat.setAlpha(holder.itemView, 0); 46 | } 47 | 48 | @Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) { 49 | ViewCompat.animate(holder.itemView) 50 | .translationY(0) 51 | .alpha(1) 52 | .setDuration(getAddDuration()) 53 | .setInterpolator(mInterpolator) 54 | .setListener(new DefaultAddVpaListener(holder)) 55 | .start(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/animators/holder/AnimateViewHolder.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.animators.holder; 2 | 3 | import android.support.v4.view.ViewPropertyAnimatorListener; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.View; 6 | 7 | public abstract class AnimateViewHolder extends RecyclerView.ViewHolder { 8 | 9 | public AnimateViewHolder(View itemView) { 10 | super(itemView); 11 | } 12 | 13 | public void preAnimateAddImpl() { 14 | } 15 | 16 | public void preAnimateRemoveImpl() { 17 | } 18 | 19 | public abstract void animateAddImpl(ViewPropertyAnimatorListener listener); 20 | 21 | public abstract void animateRemoveImpl(ViewPropertyAnimatorListener listener); 22 | } 23 | -------------------------------------------------------------------------------- /animators/src/main/java/jp/wasabeef/recyclerview/internal/ViewHelper.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.recyclerview.internal; 2 | 3 | import android.support.v4.view.ViewCompat; 4 | import android.view.View; 5 | 6 | /** 7 | * Copyright (C) 2015 Wasabeef 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | */ 21 | 22 | public final class ViewHelper { 23 | 24 | public static void clear(View v) { 25 | ViewCompat.setAlpha(v, 1); 26 | ViewCompat.setScaleY(v, 1); 27 | ViewCompat.setScaleX(v, 1); 28 | ViewCompat.setTranslationY(v, 0); 29 | ViewCompat.setTranslationX(v, 0); 30 | ViewCompat.setRotation(v, 0); 31 | ViewCompat.setRotationY(v, 0); 32 | ViewCompat.setRotationX(v, 0); 33 | // @TODO https://code.google.com/p/android/issues/detail?id=80863 34 | // ViewCompat.setPivotY(v, v.getMeasuredHeight() / 2); 35 | v.setPivotY(v.getMeasuredHeight() / 2); 36 | ViewCompat.setPivotX(v, v.getMeasuredWidth() / 2); 37 | ViewCompat.animate(v).setInterpolator(null); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /art/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepenz/recyclerview-animators/672db32c775adfe11ee51521ef344828880a9507/art/demo.gif -------------------------------------------------------------------------------- /art/demo2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepenz/recyclerview-animators/672db32c775adfe11ee51521ef344828880a9507/art/demo2.gif -------------------------------------------------------------------------------- /art/demo3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepenz/recyclerview-animators/672db32c775adfe11ee51521ef344828880a9507/art/demo3.gif -------------------------------------------------------------------------------- /art/demo4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepenz/recyclerview-animators/672db32c775adfe11ee51521ef344828880a9507/art/demo4.gif -------------------------------------------------------------------------------- /art/demo5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepenz/recyclerview-animators/672db32c775adfe11ee51521ef344828880a9507/art/demo5.gif -------------------------------------------------------------------------------- /art/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepenz/recyclerview-animators/672db32c775adfe11ee51521ef344828880a9507/art/logo.jpg -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.0.0-alpha1' 9 | classpath 'com.novoda:bintray-release:0.3.4' 10 | } 11 | } 12 | 13 | allprojects { 14 | repositories { 15 | jcenter() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /example/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion COMPILE_SDK_VERSION as int 5 | buildToolsVersion BUILD_TOOLS_VERSION 6 | 7 | defaultConfig { 8 | minSdkVersion MIN_SDK_VERSION as int 9 | targetSdkVersion TARGET_SDK_VERSION as int 10 | versionCode "git rev-list origin/master --count".execute().text.toInteger() 11 | versionName VERSION_NAME 12 | } 13 | 14 | signingConfigs { 15 | release { 16 | storeFile file(keyStoreProperty) 17 | keyAlias keyAliasProperty 18 | storePassword keyStorePasswordProperty 19 | keyPassword keyAliasPasswordProperty 20 | } 21 | } 22 | 23 | buildTypes { 24 | debug { 25 | debuggable true 26 | zipAlignEnabled true 27 | } 28 | release { 29 | debuggable false 30 | zipAlignEnabled true 31 | signingConfig signingConfigs.release 32 | } 33 | } 34 | } 35 | 36 | def getKeyStoreProperty() { 37 | return hasProperty('WASABEEF_KEYSTORE') ? WASABEEF_KEYSTORE : "debug.keystore" 38 | } 39 | 40 | def getKeyAliasProperty() { 41 | return hasProperty('WASABEEF_KEYALIAS') ? WASABEEF_KEYALIAS : "android" 42 | } 43 | 44 | def getKeyStorePasswordProperty() { 45 | return hasProperty('WASABEEF_KEYSTOREPASSWORD') ? WASABEEF_KEYSTOREPASSWORD : "androiddebugkey" 46 | } 47 | 48 | def getKeyAliasPasswordProperty() { 49 | return hasProperty('WASABEEF_KEYALIASPASSWORD') ? WASABEEF_KEYALIASPASSWORD : "android" 50 | } 51 | 52 | dependencies { 53 | compile project(':animators') 54 | compile "com.android.support:appcompat-v7:${SUPPORT_PACKAGE_VERSION}" 55 | compile "com.android.support:recyclerview-v7:${SUPPORT_PACKAGE_VERSION}" 56 | compile 'com.squareup.picasso:picasso:2.5.2' 57 | } 58 | -------------------------------------------------------------------------------- /example/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /example/src/main/java/jp/wasabeef/example/recyclerview/AdapterSampleActivity.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.example.recyclerview; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.support.v7.widget.GridLayoutManager; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import jp.wasabeef.recyclerview.animators.FadeInAnimator; 11 | import jp.wasabeef.recyclerview.adapters.AlphaInAnimationAdapter; 12 | import jp.wasabeef.recyclerview.adapters.ScaleInAnimationAdapter; 13 | 14 | /** 15 | * Created by Wasabeef on 2015/01/03. 16 | */ 17 | public class AdapterSampleActivity extends AppCompatActivity { 18 | 19 | private static String[] data = new String[] { 20 | "Apple", "Ball", "Camera", "Day", "Egg", "Foo", "Google", "Hello", "Iron", "Japan", "Coke", 21 | "Dog", "Cat", "Yahoo", "Sony", "Canon", "Fujitsu", "USA", "Nexus", "LINE", "Haskell", "C++", 22 | "Java", "Go", "Swift", "Objective-c", "Ruby", "PHP", "Bash", "ksh", "C", "Groovy", "Kotlin", 23 | "Chip", "Japan", "U.S.A", "San Francisco", "Paris", "Tokyo", "Silicon Valley", "London", 24 | "Spain", "China", "Taiwan", "Asia", "New York", "France", "Kyoto", "Android", "Google", 25 | "iPhone", "iPad", "iPod", "Wasabeef" 26 | }; 27 | 28 | @Override protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_adapter_sample); 31 | 32 | RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list); 33 | 34 | if (getIntent().getBooleanExtra("GRID", true)) { 35 | recyclerView.setLayoutManager(new GridLayoutManager(this, 2)); 36 | } else { 37 | recyclerView.setLayoutManager(new LinearLayoutManager(this)); 38 | } 39 | 40 | recyclerView.setItemAnimator(new FadeInAnimator()); 41 | MainAdapter adapter = new MainAdapter(this, new ArrayList<>(Arrays.asList(data))); 42 | AlphaInAnimationAdapter alphaAdapter = new AlphaInAnimationAdapter(adapter); 43 | ScaleInAnimationAdapter scaleAdapter = new ScaleInAnimationAdapter(alphaAdapter); 44 | // scaleAdapter.setFirstOnly(false); 45 | // scaleAdapter.setInterpolator(new OvershootInterpolator()); 46 | recyclerView.setAdapter(scaleAdapter); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /example/src/main/java/jp/wasabeef/example/recyclerview/AnimatorSampleActivity.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.example.recyclerview; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.support.v7.widget.GridLayoutManager; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.support.v7.widget.Toolbar; 9 | import android.view.View; 10 | import android.view.animation.OvershootInterpolator; 11 | import android.widget.AdapterView; 12 | import android.widget.ArrayAdapter; 13 | import android.widget.Spinner; 14 | import java.util.ArrayList; 15 | import java.util.Arrays; 16 | import jp.wasabeef.recyclerview.animators.BaseItemAnimator; 17 | import jp.wasabeef.recyclerview.animators.FadeInAnimator; 18 | import jp.wasabeef.recyclerview.animators.FadeInDownAnimator; 19 | import jp.wasabeef.recyclerview.animators.FadeInLeftAnimator; 20 | import jp.wasabeef.recyclerview.animators.FadeInRightAnimator; 21 | import jp.wasabeef.recyclerview.animators.FadeInUpAnimator; 22 | import jp.wasabeef.recyclerview.animators.FlipInBottomXAnimator; 23 | import jp.wasabeef.recyclerview.animators.FlipInLeftYAnimator; 24 | import jp.wasabeef.recyclerview.animators.FlipInRightYAnimator; 25 | import jp.wasabeef.recyclerview.animators.FlipInTopXAnimator; 26 | import jp.wasabeef.recyclerview.animators.LandingAnimator; 27 | import jp.wasabeef.recyclerview.animators.OvershootInLeftAnimator; 28 | import jp.wasabeef.recyclerview.animators.OvershootInRightAnimator; 29 | import jp.wasabeef.recyclerview.animators.ScaleInAnimator; 30 | import jp.wasabeef.recyclerview.animators.ScaleInBottomAnimator; 31 | import jp.wasabeef.recyclerview.animators.ScaleInLeftAnimator; 32 | import jp.wasabeef.recyclerview.animators.ScaleInRightAnimator; 33 | import jp.wasabeef.recyclerview.animators.ScaleInTopAnimator; 34 | import jp.wasabeef.recyclerview.animators.SlideInDownAnimator; 35 | import jp.wasabeef.recyclerview.animators.SlideInLeftAnimator; 36 | import jp.wasabeef.recyclerview.animators.SlideInRightAnimator; 37 | import jp.wasabeef.recyclerview.animators.SlideInUpAnimator; 38 | 39 | /** 40 | * Created by Wasabeef on 2015/01/03. 41 | */ 42 | public class AnimatorSampleActivity extends AppCompatActivity { 43 | 44 | enum Type { 45 | FadeIn(new FadeInAnimator(new OvershootInterpolator(1f))), 46 | FadeInDown(new FadeInDownAnimator(new OvershootInterpolator(1f))), 47 | FadeInUp(new FadeInUpAnimator(new OvershootInterpolator(1f))), 48 | FadeInLeft(new FadeInLeftAnimator(new OvershootInterpolator(1f))), 49 | FadeInRight(new FadeInRightAnimator(new OvershootInterpolator(1f))), 50 | Landing(new LandingAnimator(new OvershootInterpolator(1f))), 51 | ScaleIn(new ScaleInAnimator(new OvershootInterpolator(1f))), 52 | ScaleInTop(new ScaleInTopAnimator(new OvershootInterpolator(1f))), 53 | ScaleInBottom(new ScaleInBottomAnimator(new OvershootInterpolator(1f))), 54 | ScaleInLeft(new ScaleInLeftAnimator(new OvershootInterpolator(1f))), 55 | ScaleInRight(new ScaleInRightAnimator(new OvershootInterpolator(1f))), 56 | FlipInTopX(new FlipInTopXAnimator(new OvershootInterpolator(1f))), 57 | FlipInBottomX(new FlipInBottomXAnimator(new OvershootInterpolator(1f))), 58 | FlipInLeftY(new FlipInLeftYAnimator(new OvershootInterpolator(1f))), 59 | FlipInRightY(new FlipInRightYAnimator(new OvershootInterpolator(1f))), 60 | SlideInLeft(new SlideInLeftAnimator(new OvershootInterpolator(1f))), 61 | SlideInRight(new SlideInRightAnimator(new OvershootInterpolator(1f))), 62 | SlideInDown(new SlideInDownAnimator(new OvershootInterpolator(1f))), 63 | SlideInUp(new SlideInUpAnimator(new OvershootInterpolator(1f))), 64 | OvershootInRight(new OvershootInRightAnimator(1.0f)), 65 | OvershootInLeft(new OvershootInLeftAnimator(1.0f)); 66 | 67 | private BaseItemAnimator mAnimator; 68 | 69 | Type(BaseItemAnimator animator) { 70 | mAnimator = animator; 71 | } 72 | 73 | public BaseItemAnimator getAnimator() { 74 | return mAnimator; 75 | } 76 | } 77 | 78 | private static String[] data = new String[] { 79 | "Apple", "Ball", "Camera", "Day", "Egg", "Foo", "Google", "Hello", "Iron", "Japan", "Coke", 80 | "Dog", "Cat", "Yahoo", "Sony", "Canon", "Fujitsu", "USA", "Nexus", "LINE", "Haskell", "C++", 81 | "Java", "Go", "Swift", "Objective-c", "Ruby", "PHP", "Bash", "ksh", "C", "Groovy", "Kotlin" 82 | }; 83 | 84 | @Override protected void onCreate(Bundle savedInstanceState) { 85 | super.onCreate(savedInstanceState); 86 | setContentView(R.layout.activity_animator_sample); 87 | 88 | Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar); 89 | setSupportActionBar(toolbar); 90 | getSupportActionBar().setDisplayShowTitleEnabled(false); 91 | 92 | final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list); 93 | 94 | if (getIntent().getBooleanExtra("GRID", true)) { 95 | recyclerView.setLayoutManager(new GridLayoutManager(this, 2)); 96 | } else { 97 | recyclerView.setLayoutManager(new LinearLayoutManager(this)); 98 | } 99 | 100 | recyclerView.setItemAnimator(new SlideInLeftAnimator()); 101 | 102 | final MainAdapter adapter = new MainAdapter(this, new ArrayList<>(Arrays.asList(data))); 103 | recyclerView.setAdapter(adapter); 104 | 105 | Spinner spinner = (Spinner) findViewById(R.id.spinner); 106 | ArrayAdapter spinnerAdapter = 107 | new ArrayAdapter<>(this, android.R.layout.simple_list_item_1); 108 | for (Type type : Type.values()) { 109 | spinnerAdapter.add(type.name()); 110 | } 111 | spinner.setAdapter(spinnerAdapter); 112 | spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 113 | @Override 114 | public void onItemSelected(AdapterView parent, View view, int position, long id) { 115 | recyclerView.setItemAnimator(Type.values()[position].getAnimator()); 116 | recyclerView.getItemAnimator().setAddDuration(500); 117 | recyclerView.getItemAnimator().setRemoveDuration(500); 118 | } 119 | 120 | @Override public void onNothingSelected(AdapterView parent) { 121 | 122 | } 123 | }); 124 | 125 | findViewById(R.id.add).setOnClickListener(new View.OnClickListener() { 126 | @Override public void onClick(View v) { 127 | adapter.add("newly added item", 1); 128 | } 129 | }); 130 | 131 | findViewById(R.id.del).setOnClickListener(new View.OnClickListener() { 132 | @Override public void onClick(View v) { 133 | adapter.remove(1); 134 | } 135 | }); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /example/src/main/java/jp/wasabeef/example/recyclerview/MainActivity.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.example.recyclerview; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.support.v7.widget.SwitchCompat; 7 | import android.view.View; 8 | import android.widget.CompoundButton; 9 | 10 | /** 11 | * Created by Wasabeef on 2015/03/08. 12 | */ 13 | public class MainActivity extends AppCompatActivity { 14 | 15 | private boolean enabledGrid = false; 16 | 17 | @Override protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_main); 20 | 21 | findViewById(R.id.btn_animator_sample).setOnClickListener(new View.OnClickListener() { 22 | @Override public void onClick(View v) { 23 | Intent i = new Intent(MainActivity.this, AnimatorSampleActivity.class); 24 | i.putExtra("GRID", enabledGrid); 25 | startActivity(i); 26 | } 27 | }); 28 | 29 | findViewById(R.id.btn_adapter_sample).setOnClickListener(new View.OnClickListener() { 30 | @Override public void onClick(View v) { 31 | Intent i = new Intent(MainActivity.this, AdapterSampleActivity.class); 32 | i.putExtra("GRID", enabledGrid); 33 | startActivity(i); 34 | } 35 | }); 36 | 37 | ((SwitchCompat) findViewById(R.id.grid)).setOnCheckedChangeListener( 38 | new CompoundButton.OnCheckedChangeListener() { 39 | @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 40 | enabledGrid = isChecked; 41 | } 42 | }); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /example/src/main/java/jp/wasabeef/example/recyclerview/MainAdapter.java: -------------------------------------------------------------------------------- 1 | package jp.wasabeef.example.recyclerview; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | import com.squareup.picasso.Picasso; 11 | import java.util.List; 12 | 13 | /** 14 | * Created by Wasabeef on 2015/01/03. 15 | */ 16 | public class MainAdapter extends RecyclerView.Adapter { 17 | 18 | private Context mContext; 19 | private List mDataSet; 20 | 21 | public MainAdapter(Context context, List dataSet) { 22 | mContext = context; 23 | mDataSet = dataSet; 24 | } 25 | 26 | @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 27 | View v = LayoutInflater.from(mContext).inflate(R.layout.layout_list_item, parent, false); 28 | return new ViewHolder(v); 29 | } 30 | 31 | @Override public void onBindViewHolder(ViewHolder holder, int position) { 32 | Picasso.with(mContext).load(R.drawable.chip).into(holder.image); 33 | holder.text.setText(mDataSet.get(position)); 34 | } 35 | 36 | @Override public int getItemCount() { 37 | return mDataSet.size(); 38 | } 39 | 40 | public void remove(int position) { 41 | mDataSet.remove(position); 42 | notifyItemRemoved(position); 43 | } 44 | 45 | public void add(String text, int position) { 46 | mDataSet.add(position, text); 47 | notifyItemInserted(position); 48 | } 49 | 50 | static class ViewHolder extends RecyclerView.ViewHolder { 51 | 52 | public ImageView image; 53 | public TextView text; 54 | 55 | public ViewHolder(View itemView) { 56 | super(itemView); 57 | image = (ImageView) itemView.findViewById(R.id.image); 58 | text = (TextView) itemView.findViewById(R.id.text); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /example/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepenz/recyclerview-animators/672db32c775adfe11ee51521ef344828880a9507/example/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepenz/recyclerview-animators/672db32c775adfe11ee51521ef344828880a9507/example/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/drawable-xhdpi/chip.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepenz/recyclerview-animators/672db32c775adfe11ee51521ef344828880a9507/example/src/main/res/drawable-xhdpi/chip.jpg -------------------------------------------------------------------------------- /example/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepenz/recyclerview-animators/672db32c775adfe11ee51521ef344828880a9507/example/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/drawable-xxhdpi/ic_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepenz/recyclerview-animators/672db32c775adfe11ee51521ef344828880a9507/example/src/main/res/drawable-xxhdpi/ic_github.png -------------------------------------------------------------------------------- /example/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikepenz/recyclerview-animators/672db32c775adfe11ee51521ef344828880a9507/example/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/layout/activity_adapter_sample.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example/src/main/res/layout/activity_animator_sample.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | 15 | 19 | 20 | 25 | 26 | 36 | 37 | 47 | 48 | 49 | 50 | 51 | 52 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /example/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 |