12 |
13 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Change Log
2 | ==========
3 |
4 | Version 4.0.0 *(2020-08-27)*
5 | ----------------------------
6 |
7 | Update:
8 | - Convert from all Java codes to Kotlin 1.3.72
9 | - The minSdkVersion from 14 to 21
10 | - The targetSdkVersion from 28 to 30
11 | - The compileSdkVersion from 28 to 30
12 | - Update project settings
13 | - Disable Jetifier
14 | - Add CodeStyle settings
15 |
16 | Version 3.0.0 *(2018-11-15)*
17 | ----------------------------
18 |
19 | Update:
20 | - Migrate to AndroidX
21 | - Remove novoda-bintray-plugin
22 | - Fix a buf [#161](https://github.com/wasabeef/recyclerview-animators/pull/161)
23 |
24 | Version 2.3.0 *(2018-02-07)*
25 | ----------------------------
26 |
27 | Update:
28 | - Compile & Target SDK Version 25 -> 27
29 | - Build Tools 26.0.1 -> 27.0.3
30 | - Support Library 25.3.1 -> 27.0.2
31 |
32 | Version 2.2.7 *(2017-06-29)*
33 | ----------------------------
34 |
35 | Update:
36 | - Support Library 25.3.0 -> 25.4.0
37 |
38 | Version 2.2.6 *(2017-03-17)*
39 | ----------------------------
40 |
41 | Feature:
42 | - [Changed Interpolator to DecelerateInterpolator #125](https://github.com/wasabeef/recyclerview-animators/pull/125)
43 |
44 | Update:
45 | - Build Tools 25 -> 25.0.2
46 | - Support Library 24.2.0 -> 25.3.0
47 |
48 | Bugfix:
49 | - [Fix animations not fully canceled on endAnimations() #86](https://github.com/wasabeef/recyclerview-animators/pull/86)
50 |
51 |
52 | Version 2.2.5 *(2016-12-02)*
53 | ----------------------------
54 |
55 | Update:
56 | - Build Tools 24.0.2 -> 25
57 | - Support Library 23.4.0 -> 24.2.0
58 |
59 |
60 | Version 2.2.4 *(2016-08-03)*
61 | ----------------------------
62 |
63 | Update:
64 | - Build Tools 23.0.1 -> 24.0.2
65 | - Support Library 23.0.1 -> 23.4.0
66 |
67 |
68 | Version 2.2.3 *(2016-04-19)*
69 | ----------------------------
70 |
71 | Bug fix:
72 | [Dispatch onViewRecycled event to wrapped adapter #80](https://github.com/wasabeef/recyclerview-animators/pull/80)
73 | [Fix setStartDelay() is not reset by clear() #82](https://github.com/wasabeef/recyclerview-animators/pull/82)
74 |
75 | Update:
76 | Support library 23.2.1
77 |
78 | Version 2.2.2 *(2016-04-05)*
79 | ----------------------------
80 |
81 | Bug fix
82 |
83 | Version 2.2.1 *(2016-02-28)*
84 | ----------------------------
85 |
86 | Bug fix: firstOnly
87 |
88 | Version 2.2.0 *(2016-01-29)*
89 | ----------------------------
90 |
91 | Bug fix: [issue #64](https://github.com/wasabeef/recyclerview-animators/issues/64) by [@emartynov](https://github.com/wasabeef/recyclerview-animators/issues/64)
92 | Feature: [Motion Delay](https://github.com/wasabeef/recyclerview-animators/pull/66) by [@aphexcx](https://github.com/aphexcx)
93 |
94 | Version 2.1.0 *(2015-11-25)*
95 | ----------------------------
96 |
97 | Move the adapters of the package.
98 | Added BaseItemAnimator#setInterpolator.
99 |
100 | Version 2.0.2 *(2015-11-24)*
101 | ----------------------------
102 |
103 | Added AnimationAdapter#getIemId
104 | Fixed the getItemId() to return the nested adapter item id
105 |
106 | Version 2.0.1 *(2015-11-10)*
107 | ----------------------------
108 |
109 | Bug fix registerAdapterDataObserver, unregisterAdapterDataObserver
110 |
111 | Version 2.0.0 *(2015-10-16)*
112 | ----------------------------
113 |
114 | Support RecyclerView 23.1.0+
115 |
116 | **Use 1.3.0 If you are using a 23.0.1 or below.**
117 |
118 | Version 1.3.0 *(2015-09-11)*
119 | ----------------------------
120 |
121 | Added in ability to pass in interpolators to the four ItemAnimators.
122 | Thanks to [@craya1982](https://github.com/craya1982)
123 |
124 | Version 1.2.3 *(2015-09-07)*
125 | ----------------------------
126 |
127 | Update support library.
128 |
129 | Version 1.2.2 *(2015-08-19)*
130 | ----------------------------
131 |
132 | Add tension in OvershootAnimators.
133 |
134 | Version 1.2.1 *(2015-07-07)*
135 | ----------------------------
136 |
137 | Update AnimationAdapter to allow grabbing the wrappedAdapter.
138 |
139 | Version 1.2.0 *(2015-04-15)*
140 | ----------------------------
141 |
142 | Support Multiple animators for ViewHolders.
143 |
144 | Version 1.1.3 *(2015-04-08)*
145 | ----------------------------
146 |
147 | Support Interpolator in AnimationAdapter.
148 |
149 | Version 1.1.2 *(2015-03-23)*
150 | ----------------------------
151 |
152 | Supports multiple viewTypes.
153 |
154 | Version 1.1.1 *(2015-03-17)*
155 | ----------------------------
156 |
157 | Improved reliability and speed.
158 |
159 | Version 1.1.0 *(2015-01-21)*
160 | ----------------------------
161 |
162 | add RecyclerView.Adapter support.
163 |
164 |
165 | Version 1.0.3 *(2015-01-21)*
166 | ----------------------------
167 |
168 | fix setting of pom.xml
169 |
170 | Version 1.0.2 *(2015-01-20)*
171 | ----------------------------
172 |
173 | fix setting of pom.xml
174 |
175 | Version 1.0.1 *(2015-01-10)*
176 | ----------------------------
177 |
178 | Attach a jar for non-Gradle Android users.
179 |
180 | Version 1.0.0 *(2015-01-05)*
181 | ----------------------------
182 |
183 | Initial release.
184 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at dadadada.chop@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/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 | [](https://android-arsenal.com/details/1/1327)
8 | [](https://www.apache.org/licenses/LICENSE-2.0)
9 | [](https://search.maven.org/artifact/jp.wasabeef/recyclerview-animators)
10 |
11 | RecyclerView Animators is an Android library that allows developers to easily create RecyclerView with animations.
12 |
13 | Please feel free to use this.
14 |
15 | # Features
16 |
17 | * Animate addition and removal of [`ItemAnimator`](#itemanimator-1)
18 | * Appearance animations for items in [`RecyclerView.Adapter`](#recyclerviewadapter)
19 |
20 | # Demo
21 |
22 | ### ItemAnimator
23 |
24 |
25 | ### Adapters
26 |
27 |
28 | # How do I use it?
29 |
30 | ## Setup
31 |
32 | #### Gradle
33 |
34 | On your module's `build.gradle` file add this implementation statement to the `dependencies` section:
35 |
36 | ```groovy
37 | dependencies {
38 | // Kotlin
39 | implementation 'jp.wasabeef:recyclerview-animators:4.0.2'
40 | }
41 | ```
42 |
43 | Also make sure that the `repositories` section includes not only `"mavenCentral()"` but also a `maven` section with the `"google()"` endpoint.
44 |
45 | ```
46 | repositories {
47 | google()
48 | mavenCentral()
49 | jcenter()
50 | }
51 | ```
52 |
53 | ## ItemAnimator
54 | ### Step 1
55 |
56 | Set RecyclerView ItemAnimator.
57 |
58 | ```kotlin
59 | val recyclerView = findViewById(R.id.list)
60 | recyclerView.itemAnimator = SlideInLeftAnimator()
61 | ```
62 |
63 | ```kotlin
64 | val recyclerView = findViewById(R.id.list)
65 | recyclerView.itemAnimator = SlideInUpAnimator(OvershootInterpolator(1f))
66 | ```
67 |
68 | ## Step 2
69 | Please use the following
70 | `notifyItemChanged(int)`
71 | `notifyItemInserted(int)`
72 | `notifyItemRemoved(int)`
73 | `notifyItemRangeChanged(int, int)`
74 | `notifyItemRangeInserted(int, int)`
75 | `notifyItemRangeRemoved(int, int)`
76 |
77 | > If you want your animations to work, do not rely on calling `notifyDataSetChanged()`;
78 | > as it is the RecyclerView's default behavior, animations are not triggered to start inside this method.
79 |
80 | ```kotlin
81 | fun remove(position: Int) {
82 | dataSet.removeAt(position)
83 | notifyItemRemoved(position)
84 | }
85 |
86 | fun add(text: String, position: Int) {
87 | dataSet.add(position, text)
88 | notifyItemInserted(position)
89 | }
90 | ```
91 |
92 | ### Advanced Step 3
93 |
94 | You can change the durations.
95 |
96 | ```kotlin
97 | recyclerView.itemAnimator?.apply {
98 | addDuration = 1000
99 | removeDuration = 100
100 | moveDuration = 1000
101 | changeDuration = 100
102 | }
103 | ```
104 |
105 | ### Advanced Step 4
106 |
107 | Change the interpolator.
108 |
109 | ```kotlin
110 | recyclerView.itemAnimator = SlideInLeftAnimator().apply {
111 | setInterpolator(OvershootInterpolator())
112 | }
113 | ```
114 |
115 | ### Advanced Step 5
116 |
117 | By implementing AnimateViewHolder, you can override preset animation.
118 | So, custom animation can be set depending on view holder.
119 |
120 | ```kotlin
121 | class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), AnimateViewHolder {
122 |
123 | override fun preAnimateRemoveImpl(holder: RecyclerView.ViewHolder) {
124 | // do something
125 | }
126 |
127 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder, listener: ViewPropertyAnimatorListener) {
128 | itemView.animate().apply {
129 | translationY(-itemView.height * 0.3f)
130 | alpha(0f)
131 | duration = 300
132 | setListener(listener)
133 | }.start()
134 | }
135 |
136 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
137 | itemView.setTranslationY(-itemView.height * 0.3f)
138 | itemView.setAlpha(0f)
139 | }
140 |
141 | override fun animateAddImpl(holder: RecyclerView.ViewHolder, listener: ViewPropertyAnimatorListener) {
142 | itemView.animate().apply {
143 | translationY(0f)
144 | alpha(1f)
145 | duration = 300
146 | setListener(listener)
147 | }.start()
148 | }
149 | }
150 | ```
151 |
152 | ### Animators
153 |
154 | #### Cool
155 | `LandingAnimator`
156 |
157 | ##### Scale
158 | `ScaleInAnimator`, `ScaleInTopAnimator`, `ScaleInBottomAnimator`
159 | `ScaleInLeftAnimator`, `ScaleInRightAnimator`
160 |
161 |
162 | ##### Fade
163 | `FadeInAnimator`, `FadeInDownAnimator`, `FadeInUpAnimator`
164 | `FadeInLeftAnimator`, `FadeInRightAnimator`
165 |
166 | ##### Flip
167 | `FlipInTopXAnimator`, `FlipInBottomXAnimator`
168 | `FlipInLeftYAnimator`, `FlipInRightYAnimator`
169 |
170 | ##### Slide
171 | `SlideInLeftAnimator`, `SlideInRightAnimator`, `OvershootInLeftAnimator`, `OvershootInRightAnimator`
172 | `SlideInUpAnimator`, `SlideInDownAnimator`
173 |
174 | ## RecyclerView.Adapter
175 | ### Step 1
176 |
177 | Set RecyclerView ItemAnimator.
178 |
179 | ```kotlin
180 | val recyclerView = findViewById(R.id.list)
181 | recyclerView.adapter = AlphaInAnimationAdapter(MyAdapter())
182 | ```
183 |
184 | #### Java
185 | ```java
186 | RecyclerView recyclerView = findViewById(R.id.list);
187 | recyclerView.setAdapter(new AlphaInAnimationAdapter(MyAdapter());
188 | ```
189 |
190 | ### Advanced Step 2
191 |
192 | ```kotlin
193 | recyclerView.adapter = AlphaInAnimationAdapter(MyAdapter()).apply {
194 | // Change the durations.
195 | setDuration(1000)
196 | // Change the interpolator.
197 | setInterpolator(vershootInterpolator())
198 | // Disable the first scroll mode.
199 | setFirstOnly(false)
200 | }
201 | ```
202 |
203 | #### Java
204 | ```java
205 | AlphaInAnimationAdapter alphaInAnimationAdapter = new AlphaInAnimationAdapter(new MyAdapter());
206 | alphaInAnimationAdapter.setDuration(1000);
207 | alphaInAnimationAdapter.setInterpolator(new OvershootInterpolator());
208 | alphaInAnimationAdapter.setFirstOnly(false);
209 | ```
210 |
211 | ### Advanced Step 3
212 |
213 | Multiple Animations
214 |
215 | ```kotlin
216 | val alphaAdapter = AlphaInAnimationAdapter(MyAdapter())
217 | recyclerView.adapter = ScaleInAnimationAdapter(alphaAdapter)
218 | ```
219 |
220 | #### Java
221 | ```java
222 | recyclerView.setAdapter(new ScaleInAnimationAdapter(alphaInAnimationAdapter));
223 | ```
224 |
225 | ### Adapters
226 |
227 | #### Alpha
228 | `AlphaInAnimationAdapter`
229 |
230 | #### Scale
231 | `ScaleInAnimationAdapter`
232 |
233 | #### Slide
234 | `SlideInBottomAnimationAdapter`
235 | `SlideInRightAnimationAdapter`, `SlideInLeftAnimationAdapter`
236 |
237 | Applications using RecyclerView Animators
238 | ---
239 |
240 | Please [ping](mailto:dadadada.chop@gmail.com) me or send a pull request if you would like to be added here.
241 |
242 | Icon | Application
243 | ------------ | -------------
244 | | [Ameba Ownd](https://play.google.com/store/apps/details?id=jp.co.cyberagent.madrid)
245 | | [QuitNow!](https://play.google.com/store/apps/details?id=com.EAGINsoftware.dejaloYa)
246 | | [AbemaTV](https://play.google.com/store/apps/details?id=tv.abema)
247 | | [CL](https://play.google.com/store/apps/details?id=com.cllive)
248 |
249 | Developed By
250 | -------
251 | Daichi Furiya (Wasabeef) -
252 |
253 |
254 |
256 |
257 |
258 | Contributions
259 | -------
260 |
261 | Any contributions are welcome!
262 |
263 | Contributers
264 | -------
265 |
266 | * [craya1982](https://github.com/craya1982)
267 |
268 | Thanks
269 | -------
270 |
271 | * Inspired by `AndroidViewAnimations` in [daimajia](https://github.com/daimajia).
272 |
273 | License
274 | -------
275 |
276 | Copyright 2020 Daichi Furiya / Wasabeef
277 |
278 | Licensed under the Apache License, Version 2.0 (the "License");
279 | you may not use this file except in compliance with the License.
280 | You may obtain a copy of the License at
281 |
282 | http://www.apache.org/licenses/LICENSE-2.0
283 |
284 | Unless required by applicable law or agreed to in writing, software
285 | distributed under the License is distributed on an "AS IS" BASIS,
286 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
287 | See the License for the specific language governing permissions and
288 | limitations under the License.
289 |
--------------------------------------------------------------------------------
/animators/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android'
3 |
4 | android {
5 | compileSdkVersion COMPILE_SDK_VERSION as int
6 |
7 | defaultConfig {
8 | minSdkVersion MIN_SDK_VERSION as int
9 | targetSdkVersion TARGET_SDK_VERSION as int
10 | }
11 | }
12 |
13 | dependencies {
14 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
15 | implementation "androidx.recyclerview:recyclerview:1.1.0"
16 | }
17 |
18 | ext {
19 | bintrayRepo = 'maven'
20 | bintrayName = 'recyclerview-animators'
21 | bintrayUserOrg = 'wasabeef'
22 | publishedGroupId = 'jp.wasabeef'
23 | libraryName = 'recyclerview-animators'
24 | artifact = 'recyclerview-animators'
25 | libraryDescription = 'Which provides simple Item animations to RecyclerView items'
26 | siteUrl = 'https://github.com/wasabeef/recyclerview-animators'
27 | gitUrl = 'https://github.com/wasabeef/recyclerview-animators.git'
28 | issueUrl = 'https://github.com/wasabeef/recyclerview-animators/issues'
29 | libraryVersion = VERSION_NAME
30 | developerId = 'wasabeef'
31 | developerName = 'Wasabeef'
32 | developerEmail = 'dadadada.chop@gmail.com'
33 | licenseName = 'The Apache Software License, Version 2.0'
34 | licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
35 | allLicenses = ["Apache-2.0"]
36 | }
37 |
38 | // TODO: Close JCenter on May 1st https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/
39 | // apply from: 'https://gist.githubusercontent.com/wasabeef/cf14805bee509baf7461974582f17d26/raw/bintray-v1.gradle'
40 | // apply from: 'https://gist.githubusercontent.com/wasabeef/cf14805bee509baf7461974582f17d26/raw/install-v1.gradle'
41 |
42 | apply from: 'https://gist.githubusercontent.com/wasabeef/2f2ae8d97b429e7d967128125dc47854/raw/maven-central-v1.gradle'
--------------------------------------------------------------------------------
/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 |
2 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/adapters/AlphaInAnimationAdapter.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.adapters
2 |
3 | import android.animation.Animator
4 | import android.animation.ObjectAnimator
5 | import android.view.View
6 | import androidx.recyclerview.widget.RecyclerView
7 |
8 | /**
9 | * Copyright (C) 2021 Daichi Furiya / 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 | open class AlphaInAnimationAdapter @JvmOverloads constructor(
24 | adapter: RecyclerView.Adapter,
25 | private val from: Float = DEFAULT_ALPHA_FROM
26 | ) : AnimationAdapter(adapter) {
27 |
28 | override fun getAnimators(view: View): Array =
29 | arrayOf(ObjectAnimator.ofFloat(view, "alpha", from, 1f))
30 |
31 | companion object {
32 | private const val DEFAULT_ALPHA_FROM = 0f
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/adapters/AnimationAdapter.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.adapters
2 |
3 | import android.animation.Animator
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import android.view.animation.Interpolator
7 | import android.view.animation.LinearInterpolator
8 | import androidx.recyclerview.widget.RecyclerView
9 | import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver
10 | import jp.wasabeef.recyclerview.internal.ViewHelper.clear
11 |
12 | /**
13 | * Copyright (C) 2021 Daichi Furiya / 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 | abstract class AnimationAdapter(wrapped: RecyclerView.Adapter) :
28 | RecyclerView.Adapter() {
29 |
30 | private var duration = 300
31 | private var interpolator: Interpolator = LinearInterpolator()
32 | private var lastPosition = -1
33 | private var isFirstOnly = true
34 |
35 | protected var adapter: RecyclerView.Adapter
36 |
37 | init {
38 | @Suppress("UNCHECKED_CAST")
39 | this.adapter = wrapped as RecyclerView.Adapter
40 | super.setHasStableIds(this.adapter.hasStableIds())
41 | }
42 |
43 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
44 | return adapter.onCreateViewHolder(parent, viewType)
45 | }
46 |
47 | override fun registerAdapterDataObserver(observer: AdapterDataObserver) {
48 | super.registerAdapterDataObserver(observer)
49 | adapter.registerAdapterDataObserver(observer)
50 | }
51 |
52 | override fun unregisterAdapterDataObserver(observer: AdapterDataObserver) {
53 | super.unregisterAdapterDataObserver(observer)
54 | adapter.unregisterAdapterDataObserver(observer)
55 | }
56 |
57 | override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
58 | super.onAttachedToRecyclerView(recyclerView)
59 | adapter.onAttachedToRecyclerView(recyclerView)
60 | }
61 |
62 | override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
63 | super.onDetachedFromRecyclerView(recyclerView)
64 | adapter.onDetachedFromRecyclerView(recyclerView)
65 | }
66 |
67 | override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
68 | super.onViewAttachedToWindow(holder)
69 | adapter.onViewAttachedToWindow(holder)
70 | }
71 |
72 | override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
73 | super.onViewDetachedFromWindow(holder)
74 | adapter.onViewDetachedFromWindow(holder)
75 | }
76 |
77 | override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
78 | adapter.onBindViewHolder(holder, position)
79 | val adapterPosition = holder.adapterPosition
80 | if (!isFirstOnly || adapterPosition > lastPosition) {
81 | for (anim in getAnimators(holder.itemView)) {
82 | anim.setDuration(duration.toLong()).start()
83 | anim.interpolator = interpolator
84 | }
85 | lastPosition = adapterPosition
86 | } else {
87 | clear(holder.itemView)
88 | }
89 | }
90 |
91 | override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
92 | adapter.onViewRecycled(holder)
93 | super.onViewRecycled(holder)
94 | }
95 |
96 | override fun getItemCount(): Int {
97 | return adapter.itemCount
98 | }
99 |
100 | fun setDuration(duration: Int) {
101 | this.duration = duration
102 | }
103 |
104 | fun setInterpolator(interpolator: Interpolator) {
105 | this.interpolator = interpolator
106 | }
107 |
108 | fun setStartPosition(start: Int) {
109 | lastPosition = start
110 | }
111 |
112 | protected abstract fun getAnimators(view: View): Array
113 | fun setFirstOnly(firstOnly: Boolean) {
114 | isFirstOnly = firstOnly
115 | }
116 |
117 | override fun getItemViewType(position: Int): Int {
118 | return adapter.getItemViewType(position)
119 | }
120 |
121 | val wrappedAdapter: RecyclerView.Adapter
122 | get() = adapter
123 |
124 | override fun setHasStableIds(hasStableIds: Boolean) {
125 | super.setHasStableIds(hasStableIds)
126 | adapter.setHasStableIds(hasStableIds)
127 | }
128 |
129 | override fun getItemId(position: Int): Long {
130 | return adapter.getItemId(position)
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/adapters/ScaleInAnimationAdapter.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.adapters
2 |
3 | import android.animation.Animator
4 | import android.animation.ObjectAnimator
5 | import android.view.View
6 | import androidx.recyclerview.widget.RecyclerView
7 |
8 | /**
9 | * Copyright (C) 2021 Daichi Furiya / 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 | open class ScaleInAnimationAdapter @JvmOverloads constructor(
24 | adapter: RecyclerView.Adapter,
25 | private val from: Float = DEFAULT_SCALE_FROM
26 | ) : AnimationAdapter(adapter) {
27 |
28 | override fun getAnimators(view: View): Array {
29 | val scaleX = ObjectAnimator.ofFloat(view, "scaleX", from, 1f)
30 | val scaleY = ObjectAnimator.ofFloat(view, "scaleY", from, 1f)
31 | return arrayOf(scaleX, scaleY)
32 | }
33 |
34 | companion object {
35 | private const val DEFAULT_SCALE_FROM = .5f
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/adapters/SlideInBottomAnimationAdapter.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.adapters
2 |
3 | import android.animation.Animator
4 | import android.animation.ObjectAnimator
5 | import android.view.View
6 | import androidx.recyclerview.widget.RecyclerView
7 |
8 | /**
9 | * Copyright (C) 2021 Daichi Furiya / 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 | open class SlideInBottomAnimationAdapter(
24 | adapter: RecyclerView.Adapter
25 | ) : AnimationAdapter(adapter) {
26 |
27 | override fun getAnimators(view: View): Array = arrayOf(
28 | ObjectAnimator.ofFloat(view, "translationY", view.measuredHeight.toFloat(), 0f)
29 | )
30 | }
31 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/adapters/SlideInLeftAnimationAdapter.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.adapters
2 |
3 | import android.animation.Animator
4 | import android.animation.ObjectAnimator
5 | import android.view.View
6 | import androidx.recyclerview.widget.RecyclerView
7 |
8 | /**
9 | * Copyright (C) 2021 Daichi Furiya / 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 | open class SlideInLeftAnimationAdapter(
24 | adapter: RecyclerView.Adapter
25 | ) : AnimationAdapter(adapter) {
26 |
27 | override fun getAnimators(view: View): Array = arrayOf(
28 | ObjectAnimator.ofFloat(view, "translationX", -view.rootView.width.toFloat(), 0f)
29 | )
30 | }
31 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/adapters/SlideInRightAnimationAdapter.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.adapters
2 |
3 | import android.animation.Animator
4 | import android.animation.ObjectAnimator
5 | import android.view.View
6 | import androidx.recyclerview.widget.RecyclerView
7 |
8 | /**
9 | * Copyright (C) 2021 Daichi Furiya / 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 | open class SlideInRightAnimationAdapter(
24 | adapter: RecyclerView.Adapter
25 | ) : AnimationAdapter(adapter) {
26 |
27 | override fun getAnimators(view: View): Array = arrayOf(
28 | ObjectAnimator.ofFloat(view, "translationX", view.rootView.width.toFloat(), 0f)
29 | )
30 | }
31 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/BaseItemAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.animation.Animator
4 | import android.view.animation.DecelerateInterpolator
5 | import android.view.animation.Interpolator
6 | import androidx.recyclerview.widget.RecyclerView
7 | import androidx.recyclerview.widget.SimpleItemAnimator
8 | import jp.wasabeef.recyclerview.animators.holder.AnimateViewHolder
9 | import jp.wasabeef.recyclerview.internal.ViewHelper.clear
10 | import java.util.ArrayList
11 | import kotlin.math.abs
12 |
13 | /*
14 | * Copyright (C) 2021 Daichi Furiya / Wasabeef
15 | *
16 | * Licensed under the Apache License, Version 2.0 (the "License");
17 | * you may not use this file except in compliance with the License.
18 | * You may obtain a copy of the License at
19 | *
20 | * http://www.apache.org/licenses/LICENSE-2.0
21 | *
22 | * Unless required by applicable law or agreed to in writing, software
23 | * distributed under the License is distributed on an "AS IS" BASIS,
24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 | * See the License for the specific language governing permissions and
26 | * limitations under the License.
27 | *
28 | */
29 | abstract class BaseItemAnimator : SimpleItemAnimator() {
30 |
31 | private val pendingRemovals = ArrayList()
32 | private val pendingAdditions = ArrayList()
33 | private val pendingMoves = ArrayList()
34 | private val pendingChanges = ArrayList()
35 | private val additionsList = ArrayList>()
36 | private val movesList = ArrayList>()
37 | private val changesList = ArrayList>()
38 | protected var addAnimations = ArrayList()
39 | private val moveAnimations = ArrayList()
40 | protected var removeAnimations = ArrayList()
41 | private val changeAnimations = ArrayList()
42 | protected var interpolator: Interpolator = DecelerateInterpolator()
43 |
44 | companion object {
45 | private const val DEBUG = false
46 | }
47 |
48 | init {
49 | supportsChangeAnimations = false
50 | }
51 |
52 | private class MoveInfo(
53 | var holder: RecyclerView.ViewHolder,
54 | var fromX: Int,
55 | var fromY: Int,
56 | var toX: Int,
57 | var toY: Int
58 | )
59 |
60 | private class ChangeInfo private constructor(
61 | oldHolder: RecyclerView.ViewHolder,
62 | newHolder: RecyclerView.ViewHolder
63 | ) {
64 | var oldHolder: RecyclerView.ViewHolder? = oldHolder
65 | var newHolder: RecyclerView.ViewHolder? = newHolder
66 | var fromX = 0
67 | var fromY = 0
68 | var toX = 0
69 | var toY = 0
70 |
71 | constructor(
72 | oldHolder: RecyclerView.ViewHolder,
73 | newHolder: RecyclerView.ViewHolder,
74 | fromX: Int,
75 | fromY: Int,
76 | toX: Int,
77 | toY: Int
78 | ) : this(oldHolder, newHolder) {
79 | this.fromX = fromX
80 | this.fromY = fromY
81 | this.toX = toX
82 | this.toY = toY
83 | }
84 |
85 | override fun toString(): String {
86 | return ("ChangeInfo{" + "oldHolder=" + oldHolder + ", newHolder=" + newHolder + ", fromX="
87 | + fromX + ", fromY=" + fromY + ", toX=" + toX + ", toY=" + toY + '}')
88 | }
89 | }
90 |
91 | override fun runPendingAnimations() {
92 | val removalsPending = pendingRemovals.isNotEmpty()
93 | val movesPending = pendingMoves.isNotEmpty()
94 | val changesPending = pendingChanges.isNotEmpty()
95 | val additionsPending = pendingAdditions.isNotEmpty()
96 | if (!removalsPending && !movesPending && !additionsPending && !changesPending) {
97 | // nothing to animate
98 | return
99 | }
100 | // First, remove stuff
101 | for (holder in pendingRemovals) {
102 | doAnimateRemove(holder)
103 | }
104 | pendingRemovals.clear()
105 | // Next, move stuff
106 | if (movesPending) {
107 | val moves = ArrayList(pendingMoves)
108 | movesList.add(moves)
109 | pendingMoves.clear()
110 | val mover = Runnable {
111 | val removed = movesList.remove(moves)
112 | if (!removed) {
113 | // already canceled
114 | return@Runnable
115 | }
116 | for (moveInfo in moves) {
117 | animateMoveImpl(
118 | moveInfo.holder, moveInfo.fromX, moveInfo.fromY, moveInfo.toX,
119 | moveInfo.toY
120 | )
121 | }
122 | moves.clear()
123 | }
124 | if (removalsPending) {
125 | val view = moves[0].holder.itemView
126 | view.postOnAnimationDelayed(mover, removeDuration)
127 | } else {
128 | mover.run()
129 | }
130 | }
131 | // Next, change stuff, to run in parallel with move animations
132 | if (changesPending) {
133 | val changes = ArrayList(pendingChanges)
134 | changesList.add(changes)
135 | pendingChanges.clear()
136 | val changer = Runnable {
137 | val removed = changesList.remove(changes)
138 | if (!removed) {
139 | // already canceled
140 | return@Runnable
141 | }
142 | for (change in changes) {
143 | animateChangeImpl(change)
144 | }
145 | changes.clear()
146 | }
147 | if (removalsPending) {
148 | val holder = changes[0].oldHolder
149 | holder!!.itemView.postOnAnimationDelayed(changer, removeDuration)
150 | } else {
151 | changer.run()
152 | }
153 | }
154 | // Next, add stuff
155 | if (additionsPending) {
156 | val additions = ArrayList(pendingAdditions)
157 | additionsList.add(additions)
158 | pendingAdditions.clear()
159 | val adder = Runnable {
160 | val removed = additionsList.remove(additions)
161 | if (!removed) {
162 | // already canceled
163 | return@Runnable
164 | }
165 | for (holder in additions) {
166 | doAnimateAdd(holder)
167 | }
168 | additions.clear()
169 | }
170 | if (removalsPending || movesPending || changesPending) {
171 | val removeDuration = if (removalsPending) removeDuration else 0
172 | val moveDuration = if (movesPending) moveDuration else 0
173 | val changeDuration = if (changesPending) changeDuration else 0
174 | val totalDelay = removeDuration + moveDuration.coerceAtLeast(changeDuration)
175 | val view = additions[0].itemView
176 | view.postOnAnimationDelayed(adder, totalDelay)
177 | } else {
178 | adder.run()
179 | }
180 | }
181 | }
182 |
183 | protected open fun preAnimateRemoveImpl(holder: RecyclerView.ViewHolder) {}
184 |
185 | protected open fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {}
186 |
187 | protected abstract fun animateRemoveImpl(holder: RecyclerView.ViewHolder)
188 |
189 | protected abstract fun animateAddImpl(holder: RecyclerView.ViewHolder)
190 |
191 | private fun preAnimateRemove(holder: RecyclerView.ViewHolder) {
192 | clear(holder.itemView)
193 | if (holder is AnimateViewHolder) {
194 | holder.preAnimateRemoveImpl(holder)
195 | } else {
196 | preAnimateRemoveImpl(holder)
197 | }
198 | }
199 |
200 | private fun preAnimateAdd(holder: RecyclerView.ViewHolder) {
201 | clear(holder.itemView)
202 | if (holder is AnimateViewHolder) {
203 | holder.preAnimateAddImpl(holder)
204 | } else {
205 | preAnimateAddImpl(holder)
206 | }
207 | }
208 |
209 | private fun doAnimateRemove(holder: RecyclerView.ViewHolder) {
210 | if (holder is AnimateViewHolder) {
211 | holder.animateRemoveImpl(holder, DefaultRemoveAnimatorListener(holder))
212 | } else {
213 | animateRemoveImpl(holder)
214 | }
215 | removeAnimations.add(holder)
216 | }
217 |
218 | private fun doAnimateAdd(holder: RecyclerView.ViewHolder) {
219 | if (holder is AnimateViewHolder) {
220 | holder.animateAddImpl(holder, DefaultAddAnimatorListener(holder))
221 | } else {
222 | animateAddImpl(holder)
223 | }
224 | addAnimations.add(holder)
225 | }
226 |
227 | override fun animateRemove(holder: RecyclerView.ViewHolder): Boolean {
228 | endAnimation(holder)
229 | preAnimateRemove(holder)
230 | pendingRemovals.add(holder)
231 | return true
232 | }
233 |
234 | protected fun getRemoveDelay(holder: RecyclerView.ViewHolder): Long {
235 | return abs(holder.oldPosition * removeDuration / 4)
236 | }
237 |
238 | override fun animateAdd(holder: RecyclerView.ViewHolder): Boolean {
239 | endAnimation(holder)
240 | preAnimateAdd(holder)
241 | pendingAdditions.add(holder)
242 | return true
243 | }
244 |
245 | protected fun getAddDelay(holder: RecyclerView.ViewHolder): Long {
246 | return abs(holder.adapterPosition * addDuration / 4)
247 | }
248 |
249 | override fun animateMove(
250 | holder: RecyclerView.ViewHolder,
251 | fromX: Int,
252 | fromY: Int,
253 | toX: Int,
254 | toY: Int
255 | ): Boolean {
256 | var fX = fromX
257 | var fY = fromY
258 | val view = holder.itemView
259 | fX += holder.itemView.translationX.toInt()
260 | fY += holder.itemView.translationY.toInt()
261 | endAnimation(holder)
262 | val deltaX = toX - fX
263 | val deltaY = toY - fY
264 | if (deltaX == 0 && deltaY == 0) {
265 | dispatchMoveFinished(holder)
266 | return false
267 | }
268 | if (deltaX != 0) {
269 | view.translationX = -deltaX.toFloat()
270 | }
271 | if (deltaY != 0) {
272 | view.translationY = -deltaY.toFloat()
273 | }
274 | pendingMoves.add(MoveInfo(holder, fX, fY, toX, toY))
275 | return true
276 | }
277 |
278 | private fun animateMoveImpl(
279 | holder: RecyclerView.ViewHolder,
280 | fromX: Int,
281 | fromY: Int,
282 | toX: Int,
283 | toY: Int
284 | ) {
285 | val view = holder.itemView
286 | val deltaX = toX - fromX
287 | val deltaY = toY - fromY
288 | if (deltaX != 0) {
289 | view.animate().translationX(0f)
290 | }
291 | if (deltaY != 0) {
292 | view.animate().translationY(0f)
293 | }
294 | // TODO: make EndActions end listeners instead, since end actions aren't called when
295 | // vpas are canceled (and can't end them. why?)
296 | // need listener functionality in VPACompat for this. Ick.
297 | moveAnimations.add(holder)
298 | val animation = view.animate()
299 | animation.setDuration(moveDuration).setListener(object : AnimatorListenerAdapter() {
300 | override fun onAnimationStart(animator: Animator) {
301 | dispatchMoveStarting(holder)
302 | }
303 |
304 | override fun onAnimationCancel(animator: Animator) {
305 | if (deltaX != 0) {
306 | view.translationX = 0f
307 | }
308 | if (deltaY != 0) {
309 | view.translationY = 0f
310 | }
311 | }
312 |
313 | override fun onAnimationEnd(animator: Animator) {
314 | animation.setListener(null)
315 | dispatchMoveFinished(holder)
316 | moveAnimations.remove(holder)
317 | dispatchFinishedWhenDone()
318 | }
319 | }).start()
320 | }
321 |
322 | override fun animateChange(
323 | oldHolder: RecyclerView.ViewHolder, newHolder: RecyclerView.ViewHolder, fromX: Int, fromY: Int,
324 | toX: Int, toY: Int
325 | ): Boolean {
326 | if (oldHolder === newHolder) {
327 | // Don't know how to run change animations when the same view holder is re-used.
328 | // run a move animation to handle position changes.
329 | return animateMove(oldHolder, fromX, fromY, toX, toY)
330 | }
331 | val prevTranslationX = oldHolder.itemView.translationX
332 | val prevTranslationY = oldHolder.itemView.translationY
333 | val prevAlpha = oldHolder.itemView.alpha
334 | endAnimation(oldHolder)
335 | val deltaX = (toX - fromX - prevTranslationX).toInt()
336 | val deltaY = (toY - fromY - prevTranslationY).toInt()
337 | // recover prev translation state after ending animation
338 | oldHolder.itemView.translationX = prevTranslationX
339 | oldHolder.itemView.translationY = prevTranslationY
340 | oldHolder.itemView.alpha = prevAlpha
341 | // carry over translation values
342 | endAnimation(newHolder)
343 | newHolder.itemView.translationX = -deltaX.toFloat()
344 | newHolder.itemView.translationY = -deltaY.toFloat()
345 | newHolder.itemView.alpha = 0f
346 | pendingChanges.add(ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY))
347 | return true
348 | }
349 |
350 | private fun animateChangeImpl(changeInfo: ChangeInfo) {
351 | val holder = changeInfo.oldHolder
352 | val view = holder?.itemView
353 | val newHolder = changeInfo.newHolder
354 | val newView = newHolder?.itemView
355 | if (view != null) {
356 | if (changeInfo.oldHolder != null) changeAnimations.add(changeInfo.oldHolder!!)
357 | val oldViewAnim = view.animate().setDuration(
358 | changeDuration
359 | )
360 | oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX.toFloat())
361 | oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY.toFloat())
362 | oldViewAnim.alpha(0f).setListener(object : AnimatorListenerAdapter() {
363 | override fun onAnimationStart(animator: Animator) {
364 | dispatchChangeStarting(changeInfo.oldHolder, true)
365 | }
366 |
367 | override fun onAnimationEnd(animator: Animator) {
368 | oldViewAnim.setListener(null)
369 | view.alpha = 1f
370 | view.translationX = 0f
371 | view.translationY = 0f
372 | dispatchChangeFinished(changeInfo.oldHolder, true)
373 | if (changeInfo.oldHolder != null) changeAnimations.remove(changeInfo.oldHolder!!)
374 | dispatchFinishedWhenDone()
375 | }
376 | }).start()
377 | }
378 | if (newView != null) {
379 | if (changeInfo.newHolder != null) changeAnimations.add(changeInfo.newHolder!!)
380 | val newViewAnimation = newView.animate()
381 | newViewAnimation.translationX(0f).translationY(0f).setDuration(changeDuration).alpha(1f)
382 | .setListener(object : AnimatorListenerAdapter() {
383 | override fun onAnimationStart(animator: Animator) {
384 | dispatchChangeStarting(changeInfo.newHolder, false)
385 | }
386 |
387 | override fun onAnimationEnd(animator: Animator) {
388 | newViewAnimation.setListener(null)
389 | newView.alpha = 1f
390 | newView.translationX = 0f
391 | newView.translationY = 0f
392 | dispatchChangeFinished(changeInfo.newHolder, false)
393 | if (changeInfo.newHolder != null) changeAnimations.remove(changeInfo.newHolder!!)
394 | dispatchFinishedWhenDone()
395 | }
396 | }).start()
397 | }
398 | }
399 |
400 | private fun endChangeAnimation(infoList: MutableList, item: RecyclerView.ViewHolder) {
401 | for (i in infoList.indices.reversed()) {
402 | val changeInfo = infoList[i]
403 | if (endChangeAnimationIfNecessary(changeInfo, item)) {
404 | if (changeInfo.oldHolder == null && changeInfo.newHolder == null) {
405 | infoList.remove(changeInfo)
406 | }
407 | }
408 | }
409 | }
410 |
411 | private fun endChangeAnimationIfNecessary(changeInfo: ChangeInfo) {
412 | if (changeInfo.oldHolder != null) {
413 | endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder)
414 | }
415 | if (changeInfo.newHolder != null) {
416 | endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder)
417 | }
418 | }
419 |
420 | private fun endChangeAnimationIfNecessary(
421 | changeInfo: ChangeInfo,
422 | item: RecyclerView.ViewHolder?
423 | ): Boolean {
424 | var oldItem = false
425 | when {
426 | changeInfo.newHolder === item -> {
427 | changeInfo.newHolder = null
428 | }
429 | changeInfo.oldHolder === item -> {
430 | changeInfo.oldHolder = null
431 | oldItem = true
432 | }
433 | else -> {
434 | return false
435 | }
436 | }
437 | item!!.itemView.alpha = 1f
438 | item.itemView.translationX = 0f
439 | item.itemView.translationY = 0f
440 | dispatchChangeFinished(item, oldItem)
441 | return true
442 | }
443 |
444 | override fun endAnimation(item: RecyclerView.ViewHolder) {
445 | val view = item.itemView
446 | // this will trigger end callback which should set properties to their target values.
447 | view.animate().cancel()
448 | // TODO if some other animations are chained to end, how do we cancel them as well?
449 | for (i in pendingMoves.indices.reversed()) {
450 | val moveInfo = pendingMoves[i]
451 | if (moveInfo.holder === item) {
452 | view.translationY = 0f
453 | view.translationX = 0f
454 | dispatchMoveFinished(item)
455 | pendingMoves.removeAt(i)
456 | }
457 | }
458 | endChangeAnimation(pendingChanges, item)
459 | if (pendingRemovals.remove(item)) {
460 | clear(item.itemView)
461 | dispatchRemoveFinished(item)
462 | }
463 | if (pendingAdditions.remove(item)) {
464 | clear(item.itemView)
465 | dispatchAddFinished(item)
466 | }
467 | for (i in changesList.indices.reversed()) {
468 | val changes = changesList[i]
469 | endChangeAnimation(changes, item)
470 | if (changes.isEmpty()) {
471 | changesList.removeAt(i)
472 | }
473 | }
474 | for (i in movesList.indices.reversed()) {
475 | val moves = movesList[i]
476 | for (j in moves.indices.reversed()) {
477 | val moveInfo = moves[j]
478 | if (moveInfo.holder === item) {
479 | view.translationY = 0f
480 | view.translationX = 0f
481 | dispatchMoveFinished(item)
482 | moves.removeAt(j)
483 | if (moves.isEmpty()) {
484 | movesList.removeAt(i)
485 | }
486 | break
487 | }
488 | }
489 | }
490 | for (i in additionsList.indices.reversed()) {
491 | val additions = additionsList[i]
492 | if (additions.remove(item)) {
493 | clear(item.itemView)
494 | dispatchAddFinished(item)
495 | if (additions.isEmpty()) {
496 | additionsList.removeAt(i)
497 | }
498 | }
499 | }
500 |
501 | // animations should be ended by the cancel above.
502 | check(!(removeAnimations.remove(item) && DEBUG)) { "after animation is cancelled, item should not be in " + "mRemoveAnimations list" }
503 | check(!(addAnimations.remove(item) && DEBUG)) { "after animation is cancelled, item should not be in " + "mAddAnimations list" }
504 | check(!(changeAnimations.remove(item) && DEBUG)) { "after animation is cancelled, item should not be in " + "mChangeAnimations list" }
505 | check(!(moveAnimations.remove(item) && DEBUG)) { "after animation is cancelled, item should not be in " + "mMoveAnimations list" }
506 | dispatchFinishedWhenDone()
507 | }
508 |
509 | override fun isRunning(): Boolean {
510 | return (pendingAdditions.isNotEmpty() || pendingChanges.isNotEmpty() || pendingMoves.isNotEmpty()
511 | || pendingRemovals.isNotEmpty() || moveAnimations.isNotEmpty() || removeAnimations.isNotEmpty()
512 | || addAnimations.isNotEmpty() || changeAnimations.isNotEmpty() || movesList.isNotEmpty()
513 | || additionsList.isNotEmpty() || changesList.isNotEmpty())
514 | }
515 |
516 | /**
517 | * Check the state of currently pending and running animations. If there are none
518 | * pending/running, call #dispatchAnimationsFinished() to notify any
519 | * listeners.
520 | */
521 | private fun dispatchFinishedWhenDone() {
522 | if (!isRunning) {
523 | dispatchAnimationsFinished()
524 | }
525 | }
526 |
527 | override fun endAnimations() {
528 | var count = pendingMoves.size
529 | for (i in count - 1 downTo 0) {
530 | val item = pendingMoves[i]
531 | val view = item.holder.itemView
532 | view.translationY = 0f
533 | view.translationX = 0f
534 | dispatchMoveFinished(item.holder)
535 | pendingMoves.removeAt(i)
536 | }
537 | count = pendingRemovals.size
538 | for (i in count - 1 downTo 0) {
539 | val item = pendingRemovals[i]
540 | dispatchRemoveFinished(item)
541 | pendingRemovals.removeAt(i)
542 | }
543 | count = pendingAdditions.size
544 | for (i in count - 1 downTo 0) {
545 | val item = pendingAdditions[i]
546 | clear(item.itemView)
547 | dispatchAddFinished(item)
548 | pendingAdditions.removeAt(i)
549 | }
550 | count = pendingChanges.size
551 | for (i in count - 1 downTo 0) {
552 | endChangeAnimationIfNecessary(pendingChanges[i])
553 | }
554 | pendingChanges.clear()
555 | if (!isRunning) {
556 | return
557 | }
558 | var listCount = movesList.size
559 | for (i in listCount - 1 downTo 0) {
560 | val moves = movesList[i]
561 | count = moves.size
562 | for (j in count - 1 downTo 0) {
563 | val moveInfo = moves[j]
564 | val item = moveInfo.holder
565 | val view = item.itemView
566 | view.translationY = 0f
567 | view.translationX = 0f
568 | dispatchMoveFinished(moveInfo.holder)
569 | moves.removeAt(j)
570 | if (moves.isEmpty()) {
571 | movesList.remove(moves)
572 | }
573 | }
574 | }
575 | listCount = additionsList.size
576 | for (i in listCount - 1 downTo 0) {
577 | val additions = additionsList[i]
578 | count = additions.size
579 | for (j in count - 1 downTo 0) {
580 | val item = additions[j]
581 | val view = item.itemView
582 | view.alpha = 1f
583 | dispatchAddFinished(item)
584 | //this check prevent exception when removal already happened during finishing animation
585 | if (j < additions.size) {
586 | additions.removeAt(j)
587 | }
588 | if (additions.isEmpty()) {
589 | additionsList.remove(additions)
590 | }
591 | }
592 | }
593 | listCount = changesList.size
594 | for (i in listCount - 1 downTo 0) {
595 | val changes = changesList[i]
596 | count = changes.size
597 | for (j in count - 1 downTo 0) {
598 | endChangeAnimationIfNecessary(changes[j])
599 | if (changes.isEmpty()) {
600 | changesList.remove(changes)
601 | }
602 | }
603 | }
604 | cancelAll(removeAnimations)
605 | cancelAll(moveAnimations)
606 | cancelAll(addAnimations)
607 | cancelAll(changeAnimations)
608 | dispatchAnimationsFinished()
609 | }
610 |
611 | private fun cancelAll(viewHolders: List) {
612 | for (i in viewHolders.indices.reversed()) {
613 | viewHolders[i].itemView.animate().cancel()
614 | }
615 | }
616 |
617 | open class AnimatorListenerAdapter : Animator.AnimatorListener {
618 | override fun onAnimationStart(animator: Animator) {}
619 | override fun onAnimationEnd(animator: Animator) {}
620 | override fun onAnimationCancel(animator: Animator) {}
621 | override fun onAnimationRepeat(animator: Animator) {}
622 | }
623 |
624 | inner class DefaultAddAnimatorListener(var viewHolder: RecyclerView.ViewHolder) :
625 | AnimatorListenerAdapter() {
626 | override fun onAnimationStart(animator: Animator) {
627 | dispatchAddStarting(viewHolder)
628 | }
629 |
630 | override fun onAnimationCancel(animator: Animator) {
631 | clear(viewHolder.itemView)
632 | }
633 |
634 | override fun onAnimationEnd(animator: Animator) {
635 | clear(viewHolder.itemView)
636 | dispatchAddFinished(viewHolder)
637 | addAnimations.remove(viewHolder)
638 | dispatchFinishedWhenDone()
639 | }
640 | }
641 |
642 | protected inner class DefaultRemoveAnimatorListener(var viewHolder: RecyclerView.ViewHolder) :
643 | AnimatorListenerAdapter() {
644 | override fun onAnimationStart(animator: Animator) {
645 | dispatchRemoveStarting(viewHolder)
646 | }
647 |
648 | override fun onAnimationCancel(animator: Animator) {
649 | clear(viewHolder.itemView)
650 | }
651 |
652 | override fun onAnimationEnd(animator: Animator) {
653 | clear(viewHolder.itemView)
654 | dispatchRemoveFinished(viewHolder)
655 | removeAnimations.remove(viewHolder)
656 | dispatchFinishedWhenDone()
657 | }
658 | }
659 | }
660 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/FadeInAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class FadeInAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.animate().apply {
29 | alpha(0f)
30 | duration = removeDuration
31 | interpolator = interpolator
32 | setListener(DefaultRemoveAnimatorListener(holder))
33 | startDelay = getRemoveDelay(holder)
34 | }.start()
35 | }
36 |
37 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
38 | holder.itemView.alpha = 0f
39 | }
40 |
41 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
42 | holder.itemView.animate().apply {
43 | alpha(1f)
44 | duration = addDuration
45 | interpolator = interpolator
46 | setListener(DefaultAddAnimatorListener(holder))
47 | startDelay = getAddDelay(holder)
48 | }.start()
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/FadeInDownAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class FadeInDownAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.animate().apply {
29 | translationY(-holder.itemView.height * .25f)
30 | alpha(0f)
31 | duration = removeDuration
32 | interpolator = interpolator
33 | setListener(DefaultRemoveAnimatorListener(holder))
34 | startDelay = getRemoveDelay(holder)
35 | }.start()
36 | }
37 |
38 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
39 | holder.itemView.translationY = -holder.itemView.height * .25f
40 | holder.itemView.alpha = 0f
41 | }
42 |
43 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
44 | holder.itemView.animate().apply {
45 | translationY(0f)
46 | alpha(1f)
47 | duration = addDuration
48 | interpolator = interpolator
49 | setListener(DefaultAddAnimatorListener(holder))
50 | startDelay = getAddDelay(holder)
51 | }.start()
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/FadeInLeftAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class FadeInLeftAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.animate().apply {
29 | translationX(-holder.itemView.rootView.width * .25f)
30 | alpha(0f)
31 | duration = removeDuration
32 | interpolator = interpolator
33 | setListener(DefaultRemoveAnimatorListener(holder))
34 | startDelay = getRemoveDelay(holder)
35 | }.start()
36 | }
37 |
38 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
39 | holder.itemView.translationX = -holder.itemView.rootView.width * .25f
40 | holder.itemView.alpha = 0f
41 | }
42 |
43 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
44 | holder.itemView.animate().apply {
45 | translationX(0f)
46 | alpha(1f)
47 | duration = addDuration
48 | interpolator = interpolator
49 | setListener(DefaultAddAnimatorListener(holder))
50 | startDelay = getAddDelay(holder)
51 | }.start()
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/FadeInRightAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class FadeInRightAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.animate().apply {
29 | translationX(holder.itemView.rootView.width * .25f)
30 | alpha(0f)
31 | duration = removeDuration
32 | interpolator = interpolator
33 | setListener(DefaultRemoveAnimatorListener(holder))
34 | startDelay = getRemoveDelay(holder)
35 | }.start()
36 | }
37 |
38 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
39 | holder.itemView.translationX = holder.itemView.rootView.width * .25f
40 | holder.itemView.alpha = 0f
41 | }
42 |
43 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
44 | holder.itemView.animate().apply {
45 | translationX(0f)
46 | alpha(1f)
47 | duration = addDuration
48 | interpolator = interpolator
49 | setListener(DefaultAddAnimatorListener(holder))
50 | startDelay = getAddDelay(holder)
51 | }.start()
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/FadeInUpAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class FadeInUpAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.animate().apply {
29 | translationY(holder.itemView.height * .25f)
30 | alpha(0f)
31 | duration = removeDuration
32 | interpolator = interpolator
33 | setListener(DefaultRemoveAnimatorListener(holder))
34 | startDelay = getRemoveDelay(holder)
35 | }.start()
36 | }
37 |
38 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
39 | holder.itemView.translationY = holder.itemView.height * .25f
40 | holder.itemView.alpha = 0f
41 | }
42 |
43 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
44 | holder.itemView.animate().apply {
45 | translationY(0f)
46 | alpha(1f)
47 | duration = addDuration
48 | interpolator = interpolator
49 | setListener(DefaultAddAnimatorListener(holder))
50 | startDelay = getAddDelay(holder)
51 | }.start()
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/FlipInBottomXAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class FlipInBottomXAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.animate().apply {
29 | rotationX(-90f)
30 | duration = removeDuration
31 | interpolator = interpolator
32 | setListener(DefaultRemoveAnimatorListener(holder))
33 | startDelay = getRemoveDelay(holder)
34 | }.start()
35 | }
36 |
37 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
38 | holder.itemView.rotationX = -90f
39 | }
40 |
41 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
42 | holder.itemView.animate().apply {
43 | rotationX(0f)
44 | duration = addDuration
45 | interpolator = interpolator
46 | setListener(DefaultAddAnimatorListener(holder))
47 | startDelay = getAddDelay(holder)
48 | }.start()
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/FlipInLeftYAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class FlipInLeftYAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.animate().apply {
29 | rotationY(90f)
30 | duration = removeDuration
31 | interpolator = interpolator
32 | setListener(DefaultRemoveAnimatorListener(holder))
33 | startDelay = getRemoveDelay(holder)
34 | }.start()
35 | }
36 |
37 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
38 | holder.itemView.rotationY = 90f
39 | }
40 |
41 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
42 | holder.itemView.animate().apply {
43 | rotationY(0f)
44 | duration = addDuration
45 | interpolator = interpolator
46 | setListener(DefaultAddAnimatorListener(holder))
47 | startDelay = getAddDelay(holder)
48 | }.start()
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/FlipInRightYAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class FlipInRightYAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.animate().apply {
29 | rotationY(-90f)
30 | duration = removeDuration
31 | interpolator = interpolator
32 | setListener(DefaultRemoveAnimatorListener(holder))
33 | startDelay = getRemoveDelay(holder)
34 | }.start()
35 | }
36 |
37 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
38 | holder.itemView.rotationY = -90f
39 | }
40 |
41 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
42 | holder.itemView.animate().apply {
43 | rotationY(0f)
44 | duration = addDuration
45 | interpolator = interpolator
46 | setListener(DefaultAddAnimatorListener(holder))
47 | startDelay = getAddDelay(holder)
48 | }.start()
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/FlipInTopXAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class FlipInTopXAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.animate().apply {
29 | rotationX(90f)
30 | duration = removeDuration
31 | interpolator = interpolator
32 | setListener(DefaultRemoveAnimatorListener(holder))
33 | startDelay = getRemoveDelay(holder)
34 | }.start()
35 | }
36 |
37 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
38 | holder.itemView.rotationX = 90f
39 | }
40 |
41 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
42 | holder.itemView.animate().apply {
43 | rotationX(0f)
44 | duration = addDuration
45 | interpolator = interpolator
46 | setListener(DefaultAddAnimatorListener(holder))
47 | startDelay = getAddDelay(holder)
48 | }.start()
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/LandingAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class LandingAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.animate().apply {
29 | alpha(0f)
30 | .scaleX(1.5f)
31 | .scaleY(1.5f)
32 | duration = removeDuration
33 | interpolator = interpolator
34 | setListener(DefaultRemoveAnimatorListener(holder))
35 | startDelay = getRemoveDelay(holder)
36 | }.start()
37 | }
38 |
39 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
40 | holder.itemView.alpha = 0f
41 | holder.itemView.scaleX = 1.5f
42 | holder.itemView.scaleY = 1.5f
43 | }
44 |
45 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
46 | holder.itemView.animate().apply {
47 | alpha(1f)
48 | scaleX(1f)
49 | scaleY(1f)
50 | duration = addDuration
51 | interpolator = interpolator
52 | setListener(DefaultAddAnimatorListener(holder))
53 | startDelay = getAddDelay(holder)
54 | }.start()
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/OvershootInLeftAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.OvershootInterpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class OvershootInLeftAnimator : BaseItemAnimator {
22 | private val tension: Float
23 |
24 | constructor() {
25 | tension = 2.0f
26 | }
27 |
28 | constructor(tension: Float) {
29 | this.tension = tension
30 | }
31 |
32 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
33 | holder.itemView.animate().apply {
34 | translationX(-holder.itemView.rootView.width.toFloat())
35 | duration = removeDuration
36 | setListener(DefaultRemoveAnimatorListener(holder))
37 | startDelay = getRemoveDelay(holder)
38 | }.start()
39 | }
40 |
41 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
42 | holder.itemView.translationX = -holder.itemView.rootView.width.toFloat()
43 | }
44 |
45 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
46 | holder.itemView.animate().apply {
47 | translationX(0f)
48 | duration = addDuration
49 | setListener(DefaultAddAnimatorListener(holder))
50 | interpolator = OvershootInterpolator(tension)
51 | startDelay = getAddDelay(holder)
52 | }.start()
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/OvershootInRightAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.OvershootInterpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class OvershootInRightAnimator : BaseItemAnimator {
22 | private val tension: Float
23 |
24 | constructor() {
25 | tension = 2.0f
26 | }
27 |
28 | constructor(tension: Float) {
29 | this.tension = tension
30 | }
31 |
32 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
33 | holder.itemView.animate().apply {
34 | translationX(holder.itemView.rootView.width.toFloat())
35 | duration = removeDuration
36 | setListener(DefaultRemoveAnimatorListener(holder))
37 | startDelay = getRemoveDelay(holder)
38 | }.start()
39 | }
40 |
41 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
42 | holder.itemView.translationX = holder.itemView.rootView.width.toFloat()
43 | }
44 |
45 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
46 | holder.itemView.animate().apply {
47 | translationX(0f)
48 | duration = addDuration
49 | interpolator = OvershootInterpolator(tension)
50 | setListener(DefaultAddAnimatorListener(holder))
51 | startDelay = getAddDelay(holder)
52 | }.start()
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/ScaleInAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class ScaleInAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.animate().apply {
29 | scaleX(0f)
30 | scaleY(0f)
31 | duration = removeDuration
32 | interpolator = interpolator
33 | setListener(DefaultRemoveAnimatorListener(holder))
34 | startDelay = getRemoveDelay(holder)
35 | }.start()
36 | }
37 |
38 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
39 | holder.itemView.scaleX = 0f
40 | holder.itemView.scaleY = 0f
41 | }
42 |
43 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
44 | holder.itemView.animate().apply {
45 | scaleX(1f)
46 | scaleY(1f)
47 | duration = addDuration
48 | interpolator = interpolator
49 | setListener(DefaultAddAnimatorListener(holder))
50 | startDelay = getAddDelay(holder)
51 | }.start()
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/ScaleInBottomAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class ScaleInBottomAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun preAnimateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.pivotY = holder.itemView.height.toFloat()
29 | }
30 |
31 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
32 | holder.itemView.animate().apply {
33 | scaleX(0f)
34 | scaleY(0f)
35 | duration = removeDuration
36 | interpolator = interpolator
37 | setListener(DefaultRemoveAnimatorListener(holder))
38 | startDelay = getRemoveDelay(holder)
39 | }.start()
40 | }
41 |
42 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
43 | holder.itemView.pivotY = holder.itemView.height.toFloat()
44 | holder.itemView.scaleX = 0f
45 | holder.itemView.scaleY = 0f
46 | }
47 |
48 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
49 | holder.itemView.animate().apply {
50 | scaleX(1f)
51 | scaleY(1f)
52 | duration = addDuration
53 | interpolator = interpolator
54 | setListener(DefaultAddAnimatorListener(holder))
55 | startDelay = getAddDelay(holder)
56 | }.start()
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/ScaleInLeftAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class ScaleInLeftAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun preAnimateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.pivotX = 0f
29 | }
30 |
31 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
32 | holder.itemView.animate().apply {
33 | scaleX(0f)
34 | scaleY(0f)
35 | duration = removeDuration
36 | interpolator = interpolator
37 | setListener(DefaultRemoveAnimatorListener(holder))
38 | startDelay = getRemoveDelay(holder)
39 | }.start()
40 | }
41 |
42 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
43 | holder.itemView.pivotX = 0f
44 | holder.itemView.scaleX = 0f
45 | holder.itemView.scaleY = 0f
46 | }
47 |
48 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
49 | holder.itemView.animate().apply {
50 | scaleX(1f)
51 | scaleY(1f)
52 | duration = addDuration
53 | interpolator = interpolator
54 | setListener(DefaultAddAnimatorListener(holder))
55 | startDelay = getAddDelay(holder)
56 | }.start()
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/ScaleInRightAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class ScaleInRightAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun preAnimateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.pivotX = holder.itemView.width.toFloat()
29 | }
30 |
31 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
32 | holder.itemView.animate().apply {
33 | scaleX(0f)
34 | scaleY(0f)
35 | duration = removeDuration
36 | interpolator = interpolator
37 | setListener(DefaultRemoveAnimatorListener(holder))
38 | startDelay = getRemoveDelay(holder)
39 | }.start()
40 | }
41 |
42 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
43 | holder.itemView.pivotX = holder.itemView.width.toFloat()
44 | holder.itemView.scaleX = 0f
45 | holder.itemView.scaleY = 0f
46 | }
47 |
48 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
49 | holder.itemView.animate().apply {
50 | scaleX(1f)
51 | scaleY(1f)
52 | duration = addDuration
53 | interpolator = interpolator
54 | setListener(DefaultAddAnimatorListener(holder))
55 | startDelay = getAddDelay(holder)
56 | }.start()
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/ScaleInTopAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class ScaleInTopAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun preAnimateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.pivotY = 0f
29 | }
30 |
31 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
32 | holder.itemView.animate().apply {
33 | scaleX(0f)
34 | scaleY(0f)
35 | duration = removeDuration
36 | interpolator = interpolator
37 | setListener(DefaultRemoveAnimatorListener(holder))
38 | startDelay = getRemoveDelay(holder)
39 | }.start()
40 | }
41 |
42 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
43 | holder.itemView.pivotY = 0f
44 | holder.itemView.scaleX = 0f
45 | holder.itemView.scaleY = 0f
46 | }
47 |
48 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
49 | holder.itemView.animate().apply {
50 | scaleX(1f)
51 | scaleY(1f)
52 | duration = addDuration
53 | interpolator = interpolator
54 | setListener(DefaultAddAnimatorListener(holder))
55 | startDelay = getAddDelay(holder)
56 | }.start()
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/SlideInDownAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class SlideInDownAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.animate().apply {
29 | translationY(-holder.itemView.height.toFloat())
30 | alpha(0f)
31 | duration = removeDuration
32 | interpolator = interpolator
33 | setListener(DefaultRemoveAnimatorListener(holder))
34 | startDelay = getRemoveDelay(holder)
35 | }.start()
36 | }
37 |
38 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
39 | holder.itemView.translationY = -holder.itemView.height.toFloat()
40 | holder.itemView.alpha = 0f
41 | }
42 |
43 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
44 | holder.itemView.animate().apply {
45 | translationY(0f)
46 | alpha(1f)
47 | duration = addDuration
48 | interpolator = interpolator
49 | setListener(DefaultAddAnimatorListener(holder))
50 | startDelay = getAddDelay(holder)
51 | }.start()
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/SlideInLeftAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class SlideInLeftAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.animate().apply {
29 | translationX(-holder.itemView.rootView.width.toFloat())
30 | duration = removeDuration
31 | interpolator = interpolator
32 | setListener(DefaultRemoveAnimatorListener(holder))
33 | startDelay = getRemoveDelay(holder)
34 | }.start()
35 | }
36 |
37 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
38 | holder.itemView.translationX = -holder.itemView.rootView.width.toFloat()
39 | }
40 |
41 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
42 | holder.itemView.animate().apply {
43 | translationX(0f)
44 | duration = addDuration
45 | interpolator = interpolator
46 | setListener(DefaultAddAnimatorListener(holder))
47 | startDelay = getAddDelay(holder)
48 | }.start()
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/SlideInRightAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class SlideInRightAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.animate().apply {
29 | translationX(holder.itemView.rootView.width.toFloat())
30 | duration = removeDuration
31 | interpolator = interpolator
32 | setListener(DefaultRemoveAnimatorListener(holder))
33 | startDelay = getRemoveDelay(holder)
34 | }.start()
35 | }
36 |
37 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
38 | holder.itemView.translationX = holder.itemView.rootView.width.toFloat()
39 | }
40 |
41 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
42 | holder.itemView.animate().apply {
43 | translationX(0f)
44 | duration = addDuration
45 | interpolator = interpolator
46 | setListener(DefaultAddAnimatorListener(holder))
47 | startDelay = getAddDelay(holder)
48 | }.start()
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/SlideInUpAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * Copyright (C) 2021 Daichi Furiya / 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 | open class SlideInUpAnimator : BaseItemAnimator {
22 | constructor()
23 | constructor(interpolator: Interpolator) {
24 | this.interpolator = interpolator
25 | }
26 |
27 | override fun animateRemoveImpl(holder: RecyclerView.ViewHolder) {
28 | holder.itemView.animate().apply {
29 | translationY(holder.itemView.height.toFloat())
30 | alpha(0f)
31 | duration = removeDuration
32 | interpolator = interpolator
33 | setListener(DefaultRemoveAnimatorListener(holder))
34 | startDelay = getRemoveDelay(holder)
35 | }.start()
36 | }
37 |
38 | override fun preAnimateAddImpl(holder: RecyclerView.ViewHolder) {
39 | holder.itemView.translationY = holder.itemView.height.toFloat()
40 | holder.itemView.alpha = 0f
41 | }
42 |
43 | override fun animateAddImpl(holder: RecyclerView.ViewHolder) {
44 | holder.itemView.animate().apply {
45 | translationY(0f)
46 | alpha(1f)
47 | duration = addDuration
48 | interpolator = interpolator
49 | setListener(DefaultAddAnimatorListener(holder))
50 | startDelay = getAddDelay(holder)
51 | }.start()
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/animators/holder/AnimateViewHolder.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.animators.holder
2 |
3 | import android.animation.Animator
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | interface AnimateViewHolder {
7 | fun preAnimateAddImpl(holder: RecyclerView.ViewHolder)
8 | fun preAnimateRemoveImpl(holder: RecyclerView.ViewHolder)
9 | fun animateAddImpl(holder: RecyclerView.ViewHolder, listener: Animator.AnimatorListener)
10 | fun animateRemoveImpl(
11 | holder: RecyclerView.ViewHolder,
12 | listener: Animator.AnimatorListener
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/animators/src/main/java/jp/wasabeef/recyclerview/internal/ViewHelper.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.recyclerview.internal
2 |
3 | import android.view.View
4 |
5 | /**
6 | * Copyright (C) 2021 Daichi Furiya / Wasabeef
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | object ViewHelper {
21 | @JvmStatic
22 | fun clear(v: View) {
23 | v.apply {
24 | alpha = 1f
25 | scaleY = 1f
26 | scaleX = 1f
27 | translationY = 0f
28 | translationX = 0f
29 | rotation = 0f
30 | rotationY = 0f
31 | rotationX = 0f
32 | pivotY = v.measuredHeight / 2f
33 | pivotX = v.measuredWidth / 2f
34 | animate().setInterpolator(null).startDelay = 0
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/art/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/recyclerview-animators/6c5c7748e86f43d3d03f7b3122f473e1fd807681/art/demo.gif
--------------------------------------------------------------------------------
/art/demo2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/recyclerview-animators/6c5c7748e86f43d3d03f7b3122f473e1fd807681/art/demo2.gif
--------------------------------------------------------------------------------
/art/demo3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/recyclerview-animators/6c5c7748e86f43d3d03f7b3122f473e1fd807681/art/demo3.gif
--------------------------------------------------------------------------------
/art/demo4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/recyclerview-animators/6c5c7748e86f43d3d03f7b3122f473e1fd807681/art/demo4.gif
--------------------------------------------------------------------------------
/art/demo5.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/recyclerview-animators/6c5c7748e86f43d3d03f7b3122f473e1fd807681/art/demo5.gif
--------------------------------------------------------------------------------
/art/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/recyclerview-animators/6c5c7748e86f43d3d03f7b3122f473e1fd807681/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 | ext.kotlin_version = '1.3.72'
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5'
11 | classpath 'com.android.tools.build:gradle:4.2.0-beta04'
12 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | google()
20 | mavenCentral()
21 | jcenter()
22 | }
23 | tasks.withType(Javadoc) {
24 | enabled = false
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/example/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 |
4 | android {
5 | compileSdkVersion COMPILE_SDK_VERSION as int
6 |
7 | defaultConfig {
8 | minSdkVersion MIN_SDK_VERSION as int
9 | targetSdkVersion TARGET_SDK_VERSION as int
10 | versionCode VERSION_CODE as int
11 | versionName VERSION_NAME
12 | }
13 |
14 | // SigningConfigs
15 | apply from: '../signingConfigs/debug.gradle', to: android
16 |
17 | buildTypes {
18 | debug {
19 | debuggable true
20 | signingConfig signingConfigs.debug
21 | }
22 | release {
23 | debuggable false
24 | zipAlignEnabled true
25 | }
26 | }
27 | }
28 |
29 | repositories {
30 | // maven { url = "https://oss.sonatype.org/content/repositories/snapshots"}
31 | }
32 |
33 | dependencies {
34 | implementation project(':animators')
35 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
36 | implementation "androidx.appcompat:appcompat:1.2.0"
37 | implementation "androidx.recyclerview:recyclerview:1.1.0"
38 | implementation 'com.squareup.picasso:picasso:2.8'
39 | }
40 |
--------------------------------------------------------------------------------
/example/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
14 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/example/src/main/java/jp/wasabeef/example/recyclerview/AdapterSampleActivity.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.example.recyclerview
2 |
3 | import android.content.Context
4 | import android.os.Bundle
5 | import android.view.View
6 | import android.view.animation.OvershootInterpolator
7 | import android.widget.AdapterView
8 | import android.widget.ArrayAdapter
9 | import android.widget.Spinner
10 | import androidx.appcompat.app.AppCompatActivity
11 | import androidx.recyclerview.widget.GridLayoutManager
12 | import androidx.recyclerview.widget.LinearLayoutManager
13 | import androidx.recyclerview.widget.RecyclerView
14 | import jp.wasabeef.recyclerview.adapters.AlphaInAnimationAdapter
15 | import jp.wasabeef.recyclerview.adapters.AnimationAdapter
16 | import jp.wasabeef.recyclerview.adapters.ScaleInAnimationAdapter
17 | import jp.wasabeef.recyclerview.adapters.SlideInBottomAnimationAdapter
18 | import jp.wasabeef.recyclerview.adapters.SlideInLeftAnimationAdapter
19 | import jp.wasabeef.recyclerview.adapters.SlideInRightAnimationAdapter
20 | import jp.wasabeef.recyclerview.animators.FadeInAnimator
21 |
22 | /**
23 | * Created by Daichi Furiya / Wasabeef on 2020/08/26.
24 | */
25 | class AdapterSampleActivity : AppCompatActivity() {
26 |
27 | internal enum class Type {
28 | AlphaIn {
29 | override operator fun get(context: Context): AnimationAdapter {
30 | return AlphaInAnimationAdapter(MainAdapter(context, SampleData.LIST.toMutableList()))
31 | }
32 | },
33 | ScaleIn {
34 | override operator fun get(context: Context): AnimationAdapter {
35 | return ScaleInAnimationAdapter(MainAdapter(context, SampleData.LIST.toMutableList()))
36 | }
37 | },
38 | SlideInBottom {
39 | override operator fun get(context: Context): AnimationAdapter {
40 | return SlideInBottomAnimationAdapter(MainAdapter(context, SampleData.LIST.toMutableList()))
41 | }
42 | },
43 | SlideInLeft {
44 | override operator fun get(context: Context): AnimationAdapter {
45 | return SlideInLeftAnimationAdapter(MainAdapter(context, SampleData.LIST.toMutableList()))
46 | }
47 | },
48 | SlideInRight {
49 | override operator fun get(context: Context): AnimationAdapter {
50 | return SlideInRightAnimationAdapter(MainAdapter(context, SampleData.LIST.toMutableList()))
51 | }
52 | };
53 |
54 | abstract operator fun get(context: Context): AnimationAdapter
55 | }
56 |
57 | override fun onCreate(savedInstanceState: Bundle?) {
58 | super.onCreate(savedInstanceState)
59 | setContentView(R.layout.activity_adapter_sample)
60 |
61 | setSupportActionBar(findViewById(R.id.tool_bar))
62 | supportActionBar?.setDisplayShowTitleEnabled(false)
63 |
64 | val recyclerView = findViewById(R.id.list)
65 | recyclerView.layoutManager = if (intent.getBooleanExtra(MainActivity.KEY_GRID, true)) {
66 | GridLayoutManager(this, 2)
67 | } else {
68 | LinearLayoutManager(this)
69 | }
70 |
71 | val spinner = findViewById(R.id.spinner)
72 | spinner.adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1).apply {
73 | for (type in Type.values()) add(type.name)
74 | }
75 | spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
76 | override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
77 | recyclerView.adapter = Type.values()[position][view.context].apply {
78 | setFirstOnly(true)
79 | setDuration(500)
80 | setInterpolator(OvershootInterpolator(.5f))
81 | }
82 | }
83 |
84 | override fun onNothingSelected(parent: AdapterView<*>) {
85 | // no-op
86 | }
87 | }
88 |
89 | recyclerView.itemAnimator = FadeInAnimator()
90 | val adapter = MainAdapter(this, SampleData.LIST.toMutableList())
91 | recyclerView.adapter = AlphaInAnimationAdapter(adapter).apply {
92 | setFirstOnly(true)
93 | setDuration(500)
94 | setInterpolator(OvershootInterpolator(.5f))
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/example/src/main/java/jp/wasabeef/example/recyclerview/AnimatorSampleActivity.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.example.recyclerview
2 |
3 | import android.os.Bundle
4 | import android.view.View
5 | import android.widget.AdapterView
6 | import android.widget.ArrayAdapter
7 | import android.widget.Spinner
8 | import androidx.appcompat.app.AppCompatActivity
9 | import androidx.recyclerview.widget.GridLayoutManager
10 | import androidx.recyclerview.widget.LinearLayoutManager
11 | import androidx.recyclerview.widget.RecyclerView
12 | import jp.wasabeef.recyclerview.animators.BaseItemAnimator
13 | import jp.wasabeef.recyclerview.animators.FadeInAnimator
14 | import jp.wasabeef.recyclerview.animators.FadeInDownAnimator
15 | import jp.wasabeef.recyclerview.animators.FadeInLeftAnimator
16 | import jp.wasabeef.recyclerview.animators.FadeInRightAnimator
17 | import jp.wasabeef.recyclerview.animators.FadeInUpAnimator
18 | import jp.wasabeef.recyclerview.animators.FlipInBottomXAnimator
19 | import jp.wasabeef.recyclerview.animators.FlipInLeftYAnimator
20 | import jp.wasabeef.recyclerview.animators.FlipInRightYAnimator
21 | import jp.wasabeef.recyclerview.animators.FlipInTopXAnimator
22 | import jp.wasabeef.recyclerview.animators.LandingAnimator
23 | import jp.wasabeef.recyclerview.animators.OvershootInLeftAnimator
24 | import jp.wasabeef.recyclerview.animators.OvershootInRightAnimator
25 | import jp.wasabeef.recyclerview.animators.ScaleInAnimator
26 | import jp.wasabeef.recyclerview.animators.ScaleInBottomAnimator
27 | import jp.wasabeef.recyclerview.animators.ScaleInLeftAnimator
28 | import jp.wasabeef.recyclerview.animators.ScaleInRightAnimator
29 | import jp.wasabeef.recyclerview.animators.ScaleInTopAnimator
30 | import jp.wasabeef.recyclerview.animators.SlideInDownAnimator
31 | import jp.wasabeef.recyclerview.animators.SlideInLeftAnimator
32 | import jp.wasabeef.recyclerview.animators.SlideInRightAnimator
33 | import jp.wasabeef.recyclerview.animators.SlideInUpAnimator
34 |
35 | /**
36 | * Created by Daichi Furiya / Wasabeef on 2020/08/26.
37 | */
38 | class AnimatorSampleActivity : AppCompatActivity() {
39 |
40 | internal enum class Type(val animator: BaseItemAnimator) {
41 | FadeIn(FadeInAnimator()),
42 | FadeInDown(FadeInDownAnimator()),
43 | FadeInUp(FadeInUpAnimator()),
44 | FadeInLeft(FadeInLeftAnimator()),
45 | FadeInRight(FadeInRightAnimator()),
46 | Landing(LandingAnimator()),
47 | ScaleIn(ScaleInAnimator()),
48 | ScaleInTop(ScaleInTopAnimator()),
49 | ScaleInBottom(ScaleInBottomAnimator()),
50 | ScaleInLeft(ScaleInLeftAnimator()),
51 | ScaleInRight(ScaleInRightAnimator()),
52 | FlipInTopX(FlipInTopXAnimator()),
53 | FlipInBottomX(FlipInBottomXAnimator()),
54 | FlipInLeftY(FlipInLeftYAnimator()),
55 | FlipInRightY(FlipInRightYAnimator()),
56 | SlideInLeft(SlideInLeftAnimator()),
57 | SlideInRight(SlideInRightAnimator()),
58 | SlideInDown(SlideInDownAnimator()),
59 | SlideInUp(SlideInUpAnimator()),
60 | OvershootInRight(OvershootInRightAnimator(1.0f)),
61 | OvershootInLeft(OvershootInLeftAnimator(1.0f))
62 | }
63 |
64 | private val adapter = MainAdapter(this, SampleData.LIST.toMutableList())
65 |
66 | override fun onCreate(savedInstanceState: Bundle?) {
67 | super.onCreate(savedInstanceState)
68 | setContentView(R.layout.activity_animator_sample)
69 |
70 | setSupportActionBar(findViewById(R.id.tool_bar))
71 | supportActionBar?.setDisplayShowTitleEnabled(false)
72 |
73 | val recyclerView = findViewById(R.id.list)
74 | recyclerView.apply {
75 | itemAnimator = SlideInLeftAnimator()
76 | adapter = this@AnimatorSampleActivity.adapter
77 |
78 | layoutManager = if (intent.getBooleanExtra(MainActivity.KEY_GRID, true)) {
79 | GridLayoutManager(context, 2)
80 | } else {
81 | LinearLayoutManager(context)
82 | }
83 | }
84 |
85 |
86 | val spinner = findViewById(R.id.spinner)
87 | val spinnerAdapter = ArrayAdapter(this, android.R.layout.simple_list_item_1)
88 | for (type in Type.values()) {
89 | spinnerAdapter.add(type.name)
90 | }
91 | spinner.adapter = spinnerAdapter
92 | spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
93 | override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
94 | recyclerView.itemAnimator = Type.values()[position].animator
95 | recyclerView.itemAnimator?.addDuration = 500
96 | recyclerView.itemAnimator?.removeDuration = 500
97 | }
98 |
99 | override fun onNothingSelected(parent: AdapterView<*>) {
100 | // no-op
101 | }
102 | }
103 |
104 | findViewById(R.id.add).setOnClickListener { adapter.add("newly added item", 1) }
105 |
106 | findViewById(R.id.del).setOnClickListener { adapter.remove(1) }
107 | }
108 |
109 | }
110 |
--------------------------------------------------------------------------------
/example/src/main/java/jp/wasabeef/example/recyclerview/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.example.recyclerview
2 |
3 | import android.content.Intent
4 | import android.os.Bundle
5 | import android.view.View
6 | import androidx.appcompat.app.AppCompatActivity
7 | import androidx.appcompat.widget.SwitchCompat
8 |
9 | /**
10 | * Created by Daichi Furiya / Wasabeef on 2020/08/26.
11 | */
12 | class MainActivity : AppCompatActivity() {
13 |
14 | companion object {
15 | const val KEY_GRID = "GRID"
16 | }
17 |
18 | private var enabledGrid = false
19 |
20 | override fun onCreate(savedInstanceState: Bundle?) {
21 | super.onCreate(savedInstanceState)
22 | setContentView(R.layout.activity_main)
23 |
24 | findViewById(R.id.btn_animator_sample).setOnClickListener {
25 | startActivity(Intent(this, AnimatorSampleActivity::class.java).apply {
26 | putExtra(KEY_GRID, enabledGrid)
27 | })
28 | }
29 |
30 | findViewById(R.id.btn_adapter_sample).setOnClickListener {
31 | startActivity(Intent(this, AdapterSampleActivity::class.java).apply {
32 | putExtra(KEY_GRID, enabledGrid)
33 | })
34 | }
35 |
36 | findViewById(R.id.grid).setOnCheckedChangeListener { _, isChecked ->
37 | enabledGrid = isChecked
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/example/src/main/java/jp/wasabeef/example/recyclerview/MainAdapter.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.example.recyclerview
2 |
3 | import android.content.Context
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import android.widget.ImageView
8 | import android.widget.TextView
9 | import androidx.recyclerview.widget.RecyclerView
10 | import com.squareup.picasso.Picasso
11 |
12 | /**
13 | * Created by Daichi Furiya / Wasabeef on 2020/08/26.
14 | */
15 | class MainAdapter(private val context: Context, private val dataSet: MutableList) :
16 | RecyclerView.Adapter() {
17 |
18 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
19 | val v = LayoutInflater.from(context).inflate(R.layout.layout_list_item, parent, false)
20 | return ViewHolder(v)
21 | }
22 |
23 | override fun onBindViewHolder(holder: ViewHolder, position: Int) {
24 | Picasso.get().load(R.drawable.chip).into(holder.image)
25 | holder.text.text = dataSet[position]
26 | }
27 |
28 | override fun getItemCount(): Int {
29 | return dataSet.size
30 | }
31 |
32 | fun remove(position: Int) {
33 | dataSet.removeAt(position)
34 | notifyItemRemoved(position)
35 | }
36 |
37 | fun add(text: String, position: Int) {
38 | dataSet.add(position, text)
39 | notifyItemInserted(position)
40 | }
41 |
42 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
43 |
44 | var image: ImageView = itemView.findViewById(R.id.image) as ImageView
45 | var text: TextView = itemView.findViewById(R.id.text) as TextView
46 |
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/example/src/main/java/jp/wasabeef/example/recyclerview/MyAnimationAdapter.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.example.recyclerview
2 |
3 | import androidx.recyclerview.widget.RecyclerView
4 | import jp.wasabeef.recyclerview.adapters.AlphaInAnimationAdapter
5 |
6 | class MyAnimatorAdapter constructor(
7 | adapter: RecyclerView.Adapter,
8 | from: Float = 0.5f
9 | ) : AlphaInAnimationAdapter(adapter, from) {
10 | }
11 |
--------------------------------------------------------------------------------
/example/src/main/java/jp/wasabeef/example/recyclerview/MyAnimator.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.example.recyclerview
2 |
3 | import android.view.animation.Interpolator
4 | import androidx.interpolator.view.animation.LinearOutSlowInInterpolator
5 | import jp.wasabeef.recyclerview.animators.ScaleInRightAnimator
6 |
7 | class MyAnimator(
8 | interpolator: Interpolator = LinearOutSlowInInterpolator()
9 | ) : ScaleInRightAnimator(interpolator) {
10 | }
11 |
--------------------------------------------------------------------------------
/example/src/main/java/jp/wasabeef/example/recyclerview/SampleData.kt:
--------------------------------------------------------------------------------
1 | package jp.wasabeef.example.recyclerview
2 |
3 | /**
4 | * Created by Daichi Furiya / Wasabeef on 2020/08/26.
5 | */
6 | interface SampleData {
7 | companion object {
8 | val LIST = arrayOf(
9 | "Apple", "Ball", "Camera", "Day", "Egg", "Foo", "Google", "Hello",
10 | "Iron", "Japan", "Coke", "Dog", "Cat", "Yahoo", "Sony", "Canon", "Fujitsu", "USA", "Nexus",
11 | "LINE", "Haskell", "C++", "Java", "Go", "Swift", "Objective-c", "Ruby", "PHP", "Bash", "ksh",
12 | "C", "Groovy", "Kotlin", "Chip", "Japan", "U.S.A", "San Francisco", "Paris", "Tokyo",
13 | "Silicon Valley", "London", "Spain", "China", "Taiwan", "Asia", "New York", "France", "Kyoto",
14 | "Android", "Google", "iPhone", "iPad", "iPod", "Wasabeef"
15 | )
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/example/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/recyclerview-animators/6c5c7748e86f43d3d03f7b3122f473e1fd807681/example/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/recyclerview-animators/6c5c7748e86f43d3d03f7b3122f473e1fd807681/example/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/drawable-xhdpi/chip.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/recyclerview-animators/6c5c7748e86f43d3d03f7b3122f473e1fd807681/example/src/main/res/drawable-xhdpi/chip.jpg
--------------------------------------------------------------------------------
/example/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/recyclerview-animators/6c5c7748e86f43d3d03f7b3122f473e1fd807681/example/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/drawable-xxhdpi/ic_github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/recyclerview-animators/6c5c7748e86f43d3d03f7b3122f473e1fd807681/example/src/main/res/drawable-xxhdpi/ic_github.png
--------------------------------------------------------------------------------
/example/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/recyclerview-animators/6c5c7748e86f43d3d03f7b3122f473e1fd807681/example/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/layout/activity_adapter_sample.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
14 |
15 |
19 |
20 |
25 |
26 |
27 |
28 |
29 |
30 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/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 |
14 |
15 |
21 |
22 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/example/src/main/res/layout/layout_list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
24 |
25 |
--------------------------------------------------------------------------------
/example/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/example/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | RecyclerViewAnimators
5 |
6 |
7 |
--------------------------------------------------------------------------------
/example/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | org.gradle.parallel=true
14 | org.gradle.daemon=true
15 | org.gradle.configureondemand=true
16 | org.gradle.caching=true
17 | android.enableBuildCache=true
18 | android.useAndroidX=true
19 | android.enableJetifier=false
20 |
21 | # Use R8 instead of ProGuard for code shrinking.
22 | android.enableR8=true
23 | android.enableR8.fullMode=true
24 |
25 | VERSION_NAME=4.0.1
26 | VERSION_CODE=401
27 | GROUP=jp.wasabeef
28 |
29 | COMPILE_SDK_VERSION=30
30 | TARGET_SDK_VERSION=30
31 | MIN_SDK_VERSION=21
32 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/recyclerview-animators/6c5c7748e86f43d3d03f7b3122f473e1fd807681/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https://services.gradle.org/distributions/gradle-6.7.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
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 | # https://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 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':example', ':animators'
2 |
--------------------------------------------------------------------------------
/signingConfigs/debug.gradle:
--------------------------------------------------------------------------------
1 | signingConfigs {
2 | debug {
3 | storeFile file("debug.keystore")
4 | storePassword "android"
5 | keyAlias "androiddebugkey"
6 | keyPassword "android"
7 | }
8 | }
9 |
10 | // $ keytool -v -list -keystore
11 | // Certificate fingerprints:
12 | // MD5: 28:22:7C:A4:B9:2F:6E:C7:D5:58:62:48:EB:7E:82:C3
13 | // SHA1: 94:25:A9:50:9C:0E:AE:AA:00:37:5E:D6:71:E3:BC:ED:17:E5:0C:A3
14 | // SHA256: 04:92:39:09:3D:1C:B6:16:BE:55:58:A3:5F:3B:BB:CB:0B:E7:F1:DA:AA:26:C5:2D:BD:2F:44:CF:AE:47:CF:87
--------------------------------------------------------------------------------
/signingConfigs/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wasabeef/recyclerview-animators/6c5c7748e86f43d3d03f7b3122f473e1fd807681/signingConfigs/debug.keystore
--------------------------------------------------------------------------------