├── .github
├── CODEOWNERS
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── Bug_report.md
│ └── Feature_request.md
└── pull_request_template.md
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── skydoves
│ │ └── elasticviewsdemo
│ │ ├── ExampleActivity0.kt
│ │ ├── ExampleActivity1.kt
│ │ ├── ExampleActivity2.kt
│ │ └── MainActivity.kt
│ └── res
│ ├── drawable
│ ├── ic_add.png
│ └── ic_question.png
│ ├── layout
│ ├── activity_example0.xml
│ ├── activity_example1.xml
│ ├── activity_example2.xml
│ ├── activity_main.xml
│ └── item.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── dependencies.gradle
├── elasticviews
├── .gitignore
├── api
│ └── elasticviews.api
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── skydoves
│ │ └── elasticviews
│ │ ├── Definitions.kt
│ │ ├── ElasticAnimation.kt
│ │ ├── ElasticButton.kt
│ │ ├── ElasticCardView.kt
│ │ ├── ElasticCheckButton.kt
│ │ ├── ElasticExtensions.kt
│ │ ├── ElasticFinishListener.kt
│ │ ├── ElasticFloatingActionButton.kt
│ │ ├── ElasticImageView.kt
│ │ ├── ElasticInterface.kt
│ │ ├── ElasticLayout.kt
│ │ └── ElasticView.kt
│ └── res
│ └── values
│ └── attrs.xml
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
├── spotless.gradle
└── spotless.license.kt
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # Lines starting with '#' are comments.
2 | # Each line is a file pattern followed by one or more owners.
3 |
4 | # More details are here: https://help.github.com/articles/about-codeowners/
5 |
6 | # The '*' pattern is global owners.
7 | # Not adding in this PR, but I'd like to try adding a global owner set with the entire team.
8 | # One interpretation of their docs is that global owners are added only if not removed
9 | # by a more local rule.
10 |
11 | # Order is important. The last matching pattern has the most precedence.
12 | # The folders are ordered as follows:
13 |
14 | # In each subsection folders are ordered first by depth, then alphabetically.
15 | # This should make it easy to add new rules without breaking existing ones.
16 | * @skydoves
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: skydoves
2 | custom: ["https://www.paypal.me/skydoves", "https://www.buymeacoffee.com/skydoves"]
3 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/Bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Something is crashing or not working as intended
4 |
5 | ---
6 |
7 | **Please complete the following information:**
8 | - Library Version [e.g. v2.0.3]
9 | - Affected Device(s) [e.g. Samsung Galaxy s10 with Android 9.0]
10 |
11 | **Describe the Bug:**
12 |
13 | Add a clear description about the problem.
14 |
15 | **Expected Behavior:**
16 |
17 | A clear description of what you expected to happen.
18 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/Feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | **Is your feature request related to a problem?**
8 |
9 | A clear and concise description of what the problem is.
10 |
11 | **Describe the solution you'd like:**
12 |
13 | A clear and concise description of what you want to happen.
14 |
15 | **Describe alternatives you've considered:**
16 |
17 | A clear description of any alternative solutions you've considered.
18 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ## Guidelines
2 | Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue.
3 |
4 | ### Types of changes
5 | What types of changes does your code introduce?
6 |
7 | - [ ] Bugfix (non-breaking change which fixes an issue)
8 | - [ ] New feature (non-breaking change which adds functionality)
9 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
10 |
11 | ### Preparing a pull request for review
12 | Ensure your change is properly formatted by running:
13 |
14 | ```gradle
15 | $ ./gradlew spotlessApply
16 | ```
17 |
18 | Please correct any failures before requesting a review.
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the ART/Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | out/
15 |
16 | # Gradle files
17 | /.idea
18 | .gradle/
19 | build/
20 |
21 | # Local configuration file (sdk path, etc)
22 | local.properties
23 |
24 | # Proguard folder generated by Eclipse
25 | proguard/
26 |
27 | # Log Files
28 | *.log
29 |
30 | # Android Studio Navigation editor temp files
31 | .navigation/
32 |
33 | # Android Studio captures folder
34 | captures/
35 |
36 | # Intellij
37 | *.iml
38 | .idea/workspace.xml
39 | .idea/tasks.xml
40 | .idea/gradle.xml
41 | .idea/dictionaries
42 | .idea/libraries
43 |
44 | # Mac
45 | *.DS_Store
46 |
47 | # Keystore files
48 | *.jks
49 |
50 | # External native build folder generated in Android Studio 2.2 and later
51 | .externalNativeBuild
52 |
53 | # Google Services (e.g. APIs or Firebase)
54 | google-services.json
55 |
56 | # Freeline
57 | freeline.py
58 | freeline/
59 | freeline_project_description.json
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 |
3 | android:
4 | components:
5 | - tools
6 | - platform-tools
7 | - build-tools-29.0.0
8 | - android-29
9 | - extra-android-support
10 | - extra-android-m2repository
11 | - extra-google-m2repository
12 |
13 | jdk:
14 | - openjdk8
15 |
16 | branches:
17 | except:
18 | - gh-pages
19 |
20 | licenses:
21 | - '.+'
22 |
23 | notifications:
24 | email: false
25 |
26 | cache:
27 | directories:
28 | - $HOME/.gradle
29 |
30 | script:
31 | - chmod +x ./gradlew
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 skydoves
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ElasticViews
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | ✨ An easy way to implement an elastic touch effect for Android.
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | ## Including in your project
21 | [](https://search.maven.org/search?q=g:%22com.github.skydoves%22%20AND%20a:%22elasticviews%22)
22 | [](https://jitpack.io/#skydoves/ElasticViews)
23 |
24 | #### Gradle
25 | Add codes below to your **root** `build.gradle` file (not your module build.gradle file).
26 | ```gradle
27 | allprojects {
28 | repositories {
29 | mavenCentral()
30 | }
31 | }
32 | ```
33 | And add a dependency code to your **module**'s `build.gradle` file.
34 | ```gradle
35 | dependencies {
36 | implementation "com.github.skydoves:elasticviews:2.1.0"
37 | }
38 | ```
39 | ## SNAPSHOT
40 | [](https://oss.sonatype.org/content/repositories/snapshots/com/github/skydoves/elasticviews/)
41 | Snapshots of the current development version of ElasticViews are available, which track [the latest versions](https://oss.sonatype.org/content/repositories/snapshots/com/github/skydoves/elasticviews/).
42 | ```Gradle
43 | repositories {
44 | maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
45 | }
46 | ```
47 |
48 | ## Usage
49 | `ElasticViews` lets we use like using normal views and gives all of the Views or GroupViews touch effect very simply.
50 |
51 | #### Add XML Namespace
52 | First add below XML Namespace inside your XML layout file.
53 |
54 | ```gradle
55 | xmlns:app="http://schemas.android.com/apk/res-auto"
56 | ```
57 |
58 | #### OnClick Method
59 | All of ElasticViews should be set `OnClickListener` or `onClick` method. If not, nothing happens.
60 | ```java
61 | ElasticButton elasticButton = (ElasticButton)findViewById(R.id.elasticbutton);
62 | elasticButton.setOnClickListener(new View.OnClickListener() {
63 | @Override
64 | public void onClick(View v) {
65 | // do something
66 | }
67 | });
68 | ```
69 |
70 | ### ElasticButton
71 | ```gradle
72 |
81 | ```
82 |
83 | ### ElasticCheckButton
84 | ```gradle
85 |
96 | ```
97 |
98 | ### ElasticImageView
99 | ```gradle
100 |
108 | ```
109 |
110 | ### ElasticFloatingActionButton
111 | ```gradle
112 |
120 | ```
121 |
122 | ### ElasticCardView
123 | ```gradle
124 |
132 |
133 | ...
134 |
135 |
136 | ```
137 |
138 | ### ElasticLayout
139 | ElasticLayout gives elastic animation to all child views.
140 |
141 | ```gradle
142 |
148 |
149 |
156 |
157 |
166 |
167 | ```
168 |
169 | ### ElasticAnimation
170 | ElasticAnimation implements elastic animations for android views and view groups.
171 | ```java
172 | new ElasticAnimation(clickedView).setScaleX(0.9f).setScaleY(0.9f).setDuration(400)
173 | .setOnFinishListener(onFinishListener).doAction();
174 | ```
175 |
176 |
177 |
178 | #### ViewPropertyAnimatorListener
179 | we can set `ViewPropertyAnimatorListener` using `setListener` method and detect animation's status.
180 | ```java
181 | .setListener(new ViewPropertyAnimatorListener() {
182 | @Override
183 | public void onAnimationStart(View view) {
184 | // do something
185 | }
186 |
187 | Override
188 | public void onAnimationEnd(View view) {
189 | finishListener.onFinished();
190 | }
191 |
192 | Override
193 | public void onAnimationCancel(View view) {
194 | // do something
195 | }
196 | });
197 | ```
198 |
199 | #### Kotlin Extension
200 | ElasticAnimation supports kotlin extension `elasticAnimation`.
201 | ```kotlin
202 | val anim = textView.elasticAnimation(0.8f, 0.8f, 400, object: ElasticFinishListener {
203 | override fun onFinished() {
204 | // do anything
205 | }
206 | })
207 | anim.doAction()
208 | ```
209 |
210 | #### Kotlin dsl
211 | ```kotlin
212 | elasticAnimation(this) {
213 | setDuration(duration)
214 | setScaleX(scale)
215 | setScaleY(scale)
216 | setOnFinishListener(object : ElasticFinishListener {
217 | override fun onFinished() {
218 | onClick()
219 | }
220 | })
221 | }.doAction()
222 | ```
223 |
224 | #### Example : Normal Button
225 | we can implement animation on all of the views like below.
226 | ```java
227 | @OnClick(R.id.button)
228 | public void addNewAlarm(View v){
229 | // implements animation uising ElasticAnimation
230 | new ElasticAnimation(v).setScaleX(0.85f).setScaleY(0.85f).setDuration(500)
231 | .setOnFinishListener(new ElasticFinishListener() {
232 | @Override
233 | public void onFinished() {
234 | // Do something after duration time
235 | }
236 | }).doAction();
237 | }
238 | }
239 | ```
240 |
241 | #### Example : ListView Item
242 | So also we can implement animation on listView's items like below.
243 | ```java
244 | private class ListViewItemClickListener implements AdapterView.OnItemClickListener {
245 | @Override
246 | public void onItemClick(AdapterView> adapterView, View clickedView, final int pos, long id) {
247 | new ElasticAnimation(clickedView).setScaleX(0.9f).setScaleY(0.9f).setDuration(400)
248 | .setOnFinishListener(new ElasticFinishListener() {
249 | @Override
250 | public void onFinished() {
251 | // Do something after duration time
252 | Toast.makeText(getBaseContext(), "ListViewItem" + pos, Toast.LENGTH_SHORT).show();
253 | }
254 | }).doAction();
255 | }
256 | };
257 | ```
258 |
259 | ## Find this library useful? :heart:
260 | Support it by joining __[stargazers](https://github.com/skydoves/ElasticViews/stargazers)__ for this repository. :star:
261 | And __[follow](https://github.com/skydoves)__ me for my next creations! 🤩
262 |
263 | # License
264 | ```xml
265 | The MIT License (MIT)
266 |
267 | Copyright (c) 2017 skydoves
268 |
269 | Permission is hereby granted, free of charge, to any person obtaining a copy
270 | of this software and associated documentation files (the "Software"), to deal
271 | in the Software without restriction, including without limitation the rights
272 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
273 | copies of the Software, and to permit persons to whom the Software is
274 | furnished to do so, subject to the following conditions:
275 |
276 | The above copyright notice and this permission notice shall be included in
277 | all copies or substantial portions of the Software.
278 |
279 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
280 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
281 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
282 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
283 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
284 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
285 | THE SOFTWARE.
286 | ```
287 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 | apply from: '../dependencies.gradle'
4 |
5 | android {
6 | compileSdkVersion versions.compileSdk
7 | defaultConfig {
8 | minSdkVersion versions.minSdk
9 | targetSdkVersion versions.compileSdk
10 | versionCode versions.versionCode
11 | versionName versions.versionName
12 | }
13 | compileOptions {
14 | sourceCompatibility JavaVersion.VERSION_1_8
15 | targetCompatibility JavaVersion.VERSION_1_8
16 | }
17 | buildFeatures {
18 | viewBinding true
19 | }
20 | }
21 |
22 | dependencies {
23 | implementation "com.google.android.material:material:$versions.googleMaterial"
24 | implementation project(":elasticviews")
25 | }
26 |
27 | apply from: '../spotless.gradle'
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/skydoves/elasticviewsdemo/ExampleActivity0.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.skydoves.elasticviewsdemo
25 |
26 | import android.graphics.Color
27 | import android.os.Bundle
28 | import android.view.View
29 | import android.widget.Toast
30 | import androidx.appcompat.app.AppCompatActivity
31 | import com.google.android.material.snackbar.Snackbar
32 | import com.skydoves.elasticviews.ElasticCheckButton
33 | import com.skydoves.elasticviewsdemo.databinding.ActivityExample0Binding
34 |
35 | class ExampleActivity0 : AppCompatActivity() {
36 |
37 | override fun onCreate(savedInstanceState: Bundle?) {
38 | super.onCreate(savedInstanceState)
39 |
40 | val binding = ActivityExample0Binding.inflate(layoutInflater)
41 | setContentView(binding.root)
42 | }
43 |
44 | fun checkButtons(v: View) {
45 | val elasticCheckButton = v as ElasticCheckButton
46 | Snackbar.make(
47 | v,
48 | "[Change checked state] " +
49 | elasticCheckButton.text.toString() +
50 | " : " +
51 | elasticCheckButton.isChecked,
52 | 200
53 | )
54 | .setActionTextColor(Color.WHITE)
55 | .show()
56 | }
57 |
58 | fun layout(v: View) {
59 | Snackbar.make(v, "Pop-up likes 'TimePickerDialog'", 200).setActionTextColor(Color.WHITE).show()
60 | }
61 |
62 | fun imageViews(v: View) {
63 | when (v.id) {
64 | R.id.example0_ibtn_q_timeset01 ->
65 | Snackbar.make(
66 | v,
67 | "Alarm goes off between start-time and end-time", 200
68 | )
69 | .setActionTextColor(Color.WHITE)
70 | .show()
71 | R.id.example0_ibtn_q_timeset02 ->
72 | Snackbar.make(v, "This is time interval description", 200)
73 | .setActionTextColor(Color.WHITE)
74 | .show()
75 | }
76 | }
77 |
78 | fun addNewAlarm(v: View) {
79 | Toast.makeText(baseContext, "a new Alarm added!", Toast.LENGTH_SHORT).show()
80 | finish()
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/app/src/main/java/com/skydoves/elasticviewsdemo/ExampleActivity1.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.skydoves.elasticviewsdemo
25 |
26 | import android.annotation.SuppressLint
27 | import android.content.Context
28 | import android.os.Bundle
29 | import android.view.LayoutInflater
30 | import android.view.View
31 | import android.view.ViewGroup
32 | import android.widget.AdapterView
33 | import android.widget.BaseAdapter
34 | import android.widget.ListView
35 | import android.widget.TextView
36 | import android.widget.Toast
37 | import androidx.appcompat.app.AppCompatActivity
38 | import com.skydoves.elasticviews.ElasticAnimation
39 | import com.skydoves.elasticviewsdemo.databinding.ActivityExample1Binding
40 | import java.util.ArrayList
41 |
42 | class ExampleActivity1 : AppCompatActivity() {
43 |
44 | private val data = ArrayList()
45 | private var adapter: ListViewAdapter? = null
46 | private var listView: ListView? = null
47 |
48 | override fun onCreate(savedInstanceState: Bundle?) {
49 | super.onCreate(savedInstanceState)
50 |
51 | val binding = ActivityExample1Binding.inflate(layoutInflater)
52 | setContentView(binding.root)
53 |
54 | adapter = ListViewAdapter(this, R.layout.item, data)
55 | listView = findViewById(R.id.example1_listView)
56 | listView!!.adapter = adapter
57 | listView!!.onItemClickListener = ListViewItemClickListener()
58 | }
59 |
60 | fun floatingButtons(v: View) {
61 | val listviewitem = ListViewItem(data.size.toString() + "")
62 | data.add(listviewitem)
63 | adapter!!.notifyDataSetChanged()
64 | listView!!.setSelection(data.size - 1)
65 | }
66 |
67 | // ListView Item Touch Event
68 | private inner class ListViewItemClickListener : AdapterView.OnItemClickListener {
69 | override fun onItemClick(adapterView: AdapterView<*>, clickedView: View, pos: Int, id: Long) {
70 | ElasticAnimation(clickedView)
71 | .setScaleX(0.9f)
72 | .setScaleY(0.9f)
73 | .setDuration(400)
74 | .setOnFinishListener {
75 | // Do something after duration time
76 | Toast.makeText(baseContext, "ListViewItem$pos", Toast.LENGTH_SHORT).show()
77 | }
78 | .doAction()
79 | }
80 | }
81 |
82 | private inner class ListViewItem(val content: String)
83 |
84 | private inner class ListViewAdapter(
85 | context: Context,
86 | private val layout: Int,
87 | private val data: ArrayList
88 | ) : BaseAdapter() {
89 |
90 | private val inflater: LayoutInflater =
91 | context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
92 |
93 | override fun getCount(): Int {
94 | return data.size
95 | }
96 |
97 | override fun getItem(position: Int): String {
98 | return data[position].content
99 | }
100 |
101 | override fun getItemId(position: Int): Long {
102 | return position.toLong()
103 | }
104 |
105 | @SuppressLint("SetTextI18n")
106 | override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
107 | var view = convertView
108 |
109 | if (view == null) view = inflater.inflate(layout, parent, false)
110 | val listviewitem = data[position]
111 |
112 | val tv_title = view!!.findViewById(R.id.item_tv_title)
113 | tv_title.text = "ListViewItem" + listviewitem.content
114 |
115 | val tv_content = view.findViewById(R.id.item_tv_content)
116 | tv_content.text = "This is ListViewItem" + listviewitem.content + "'s content"
117 |
118 | return view
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/app/src/main/java/com/skydoves/elasticviewsdemo/ExampleActivity2.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.skydoves.elasticviewsdemo
25 |
26 | import android.graphics.Color
27 | import android.os.Bundle
28 | import android.view.View
29 | import androidx.appcompat.app.AppCompatActivity
30 | import com.google.android.material.snackbar.Snackbar
31 | import com.skydoves.elasticviews.ElasticAnimation
32 | import com.skydoves.elasticviewsdemo.databinding.ActivityExample2Binding
33 |
34 | class ExampleActivity2 : AppCompatActivity() {
35 |
36 | override fun onCreate(savedInstanceState: Bundle?) {
37 | super.onCreate(savedInstanceState)
38 |
39 | val binding = ActivityExample2Binding.inflate(layoutInflater)
40 | setContentView(binding.root)
41 | }
42 |
43 | fun views(v: View) {
44 | when (v.id) {
45 | R.id.example2_view3 ->
46 | ElasticAnimation(v)
47 | .setScaleX(0.85f)
48 | .setScaleY(0.85f)
49 | .setDuration(500)
50 | .setOnFinishListener {
51 | // Do something after duration time
52 | }
53 | .doAction()
54 | R.id.example2_imv -> Snackbar.make(v, "This is ElasticImageView", 200).setActionTextColor(
55 | Color.WHITE
56 | ).show()
57 | R.id.example2_textView0 -> ElasticAnimation(v).setScaleX(0.75f).setScaleY(0.75f).setDuration(
58 | 500
59 | ).doAction()
60 | R.id.example2_fab ->
61 | Snackbar.make(v, "This is ElasticFloatActionButton", 200)
62 | .setActionTextColor(Color.WHITE)
63 | .show()
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/app/src/main/java/com/skydoves/elasticviewsdemo/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.skydoves.elasticviewsdemo
25 |
26 | import android.content.Intent
27 | import android.os.Bundle
28 | import android.view.View
29 | import androidx.appcompat.app.AppCompatActivity
30 | import com.skydoves.elasticviewsdemo.databinding.ActivityMainBinding
31 |
32 | class MainActivity : AppCompatActivity() {
33 |
34 | override fun onCreate(savedInstanceState: Bundle?) {
35 | super.onCreate(savedInstanceState)
36 |
37 | val binding = ActivityMainBinding.inflate(layoutInflater)
38 | setContentView(binding.root)
39 | }
40 |
41 | fun buttons(v: View) {
42 | when (v.id) {
43 | R.id.elasticbtn0 -> startActivity(Intent(baseContext, ExampleActivity0::class.java))
44 | R.id.elasticbtn1 -> startActivity(Intent(baseContext, ExampleActivity1::class.java))
45 | R.id.elasticbtn2 -> startActivity(Intent(baseContext, ExampleActivity2::class.java))
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skydoves/ElasticViews/752955421fcd12addd59a4e3dd817b2336cebba5/app/src/main/res/drawable/ic_add.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_question.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skydoves/ElasticViews/752955421fcd12addd59a4e3dd817b2336cebba5/app/src/main/res/drawable/ic_question.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_example0.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
17 |
18 |
19 |
26 |
27 |
40 |
41 |
47 |
48 |
53 |
54 |
66 |
67 |
79 |
80 |
92 |
93 |
105 |
106 |
118 |
119 |
131 |
132 |
144 |
145 |
146 |
147 |
148 |
149 |
157 |
158 |
161 |
162 |
174 |
175 |
186 |
187 |
188 |
189 |
198 |
199 |
202 |
203 |
215 |
216 |
229 |
230 |
231 |
232 |
242 |
243 |
246 |
247 |
259 |
260 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
288 |
289 |
301 |
302 |
313 |
314 |
324 |
325 |
328 |
329 |
341 |
342 |
355 |
356 |
357 |
358 |
359 |
360 |
365 |
366 |
381 |
382 |
383 |
384 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_example1.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_example2.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
14 |
15 |
26 |
27 |
34 |
35 |
36 |
37 |
49 |
50 |
63 |
64 |
74 |
75 |
78 |
79 |
90 |
91 |
103 |
104 |
105 |
106 |
113 |
114 |
125 |
126 |
138 |
139 |
140 |
141 |
145 |
146 |
157 |
158 |
168 |
169 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
26 |
27 |
39 |
40 |
49 |
50 |
51 |
52 |
66 |
67 |
82 |
83 |
97 |
98 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
29 |
30 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skydoves/ElasticViews/752955421fcd12addd59a4e3dd817b2336cebba5/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skydoves/ElasticViews/752955421fcd12addd59a4e3dd817b2336cebba5/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skydoves/ElasticViews/752955421fcd12addd59a4e3dd817b2336cebba5/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skydoves/ElasticViews/752955421fcd12addd59a4e3dd817b2336cebba5/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skydoves/ElasticViews/752955421fcd12addd59a4e3dd817b2336cebba5/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skydoves/ElasticViews/752955421fcd12addd59a4e3dd817b2336cebba5/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skydoves/ElasticViews/752955421fcd12addd59a4e3dd817b2336cebba5/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skydoves/ElasticViews/752955421fcd12addd59a4e3dd817b2336cebba5/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skydoves/ElasticViews/752955421fcd12addd59a4e3dd817b2336cebba5/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skydoves/ElasticViews/752955421fcd12addd59a4e3dd817b2336cebba5/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #C51162
4 | #AD1457
5 | #C51162
6 | #2B292B
7 | #424242
8 | #212121
9 | #8effffff
10 | #b2ffffff
11 | #ddffffff
12 | #edf8f8f8
13 | #ffffffff
14 | #57A8D8
15 | #FBC02D
16 | #FFD600
17 | #FBC02D
18 | #FFA000
19 | #FFA726
20 | #FF6D00
21 | #81C784
22 | #388E3C
23 | #81D4fA
24 | #0091EA
25 | #AA00FF
26 | #7200CA
27 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ElasticViews
3 | ExampleActivity0
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | apply from: './dependencies.gradle'
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 | dependencies {
8 | classpath "com.android.tools.build:gradle:$versions.gradleBuildTool"
9 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlin"
10 | classpath "com.diffplug.spotless:spotless-plugin-gradle:$versions.spotlessGradle"
11 | classpath "com.vanniktech:gradle-maven-publish-plugin:$versions.mavenPublish"
12 | classpath "org.jetbrains.dokka:dokka-gradle-plugin:$versions.dokkaGradle"
13 | classpath "org.jetbrains.kotlinx:binary-compatibility-validator:$versions.binaryValidator"
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | google()
20 | mavenCentral()
21 | }
22 | }
23 |
24 | task clean(type: Delete) {
25 | delete rootProject.buildDir
26 | }
27 |
--------------------------------------------------------------------------------
/dependencies.gradle:
--------------------------------------------------------------------------------
1 | ext.versions = [
2 | minSdk : 16,
3 | compileSdk : 30,
4 | versionCode : 24,
5 | versionName : '2.1.0',
6 |
7 | gradleBuildTool: '4.1.3',
8 | spotlessGradle : '5.14.0',
9 | ktlintGradle : '0.41.0',
10 | dokkaGradle : '1.4.32',
11 | binaryValidator : '0.7.1',
12 | mavenPublish : '0.15.1',
13 |
14 | kotlin : '1.4.32',
15 | googleMaterial : '1.3.0-alpha02'
16 | ]
17 |
--------------------------------------------------------------------------------
/elasticviews/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/elasticviews/api/elasticviews.api:
--------------------------------------------------------------------------------
1 | public final class com/skydoves/elasticviews/ElasticAnimation {
2 | public field duration I
3 | public field finishListener Lcom/skydoves/elasticviews/ElasticFinishListener;
4 | public field listener Landroidx/core/view/ViewPropertyAnimatorListener;
5 | public field scaleX F
6 | public field scaleY F
7 | public fun (Landroid/view/View;)V
8 | public final fun doAction ()V
9 | public final fun isAnimating ()Z
10 | public final fun setDuration (I)Lcom/skydoves/elasticviews/ElasticAnimation;
11 | public final fun setListener (Landroidx/core/view/ViewPropertyAnimatorListener;)Lcom/skydoves/elasticviews/ElasticAnimation;
12 | public final fun setOnFinishListener (Lcom/skydoves/elasticviews/ElasticFinishListener;)Lcom/skydoves/elasticviews/ElasticAnimation;
13 | public final synthetic fun setOnFinishListener (Lkotlin/jvm/functions/Function0;)Lcom/skydoves/elasticviews/ElasticAnimation;
14 | public final fun setScaleX (F)Lcom/skydoves/elasticviews/ElasticAnimation;
15 | public final fun setScaleY (F)Lcom/skydoves/elasticviews/ElasticAnimation;
16 | }
17 |
18 | public final class com/skydoves/elasticviews/ElasticButton : androidx/appcompat/widget/AppCompatButton, com/skydoves/elasticviews/ElasticInterface {
19 | public fun (Landroid/content/Context;)V
20 | public fun (Landroid/content/Context;Landroid/util/AttributeSet;)V
21 | public fun (Landroid/content/Context;Landroid/util/AttributeSet;I)V
22 | public synthetic fun (Landroid/content/Context;Landroid/util/AttributeSet;IILkotlin/jvm/internal/DefaultConstructorMarker;)V
23 | public final fun getCornerRadius ()F
24 | public final fun getDuration ()I
25 | public final fun getScale ()F
26 | public final fun setCornerRadius (F)V
27 | public final fun setDuration (I)V
28 | public fun setOnClickListener (Landroid/view/View$OnClickListener;)V
29 | public fun setOnClickListener (Lkotlin/jvm/functions/Function1;)V
30 | public fun setOnFinishListener (Lcom/skydoves/elasticviews/ElasticFinishListener;)V
31 | public fun setOnFinishListener (Lkotlin/jvm/functions/Function0;)V
32 | public final fun setScale (F)V
33 | }
34 |
35 | public final class com/skydoves/elasticviews/ElasticButton$Builder {
36 | public fun (Landroid/content/Context;)V
37 | public final fun build ()Lcom/skydoves/elasticviews/ElasticButton;
38 | public final fun setCornerRadius (F)Lcom/skydoves/elasticviews/ElasticButton$Builder;
39 | public final fun setDuration (I)Lcom/skydoves/elasticviews/ElasticButton$Builder;
40 | public final fun setOnClickListener (Landroid/view/View$OnClickListener;)Lcom/skydoves/elasticviews/ElasticButton$Builder;
41 | public final synthetic fun setOnClickListener (Lkotlin/jvm/functions/Function1;)Lcom/skydoves/elasticviews/ElasticButton$Builder;
42 | public final fun setOnFinishListener (Lcom/skydoves/elasticviews/ElasticFinishListener;)Lcom/skydoves/elasticviews/ElasticButton$Builder;
43 | public final synthetic fun setOnFinishListener (Lkotlin/jvm/functions/Function0;)Lcom/skydoves/elasticviews/ElasticButton$Builder;
44 | public final fun setScale (F)Lcom/skydoves/elasticviews/ElasticButton$Builder;
45 | }
46 |
47 | public final class com/skydoves/elasticviews/ElasticButton$sam$i$android_view_View_OnClickListener$0 : android/view/View$OnClickListener {
48 | public fun (Lkotlin/jvm/functions/Function1;)V
49 | public final synthetic fun onClick (Landroid/view/View;)V
50 | }
51 |
52 | public final class com/skydoves/elasticviews/ElasticButton$sam$i$com_skydoves_elasticviews_ElasticFinishListener$0 : com/skydoves/elasticviews/ElasticFinishListener, kotlin/jvm/internal/FunctionAdapter {
53 | public fun (Lkotlin/jvm/functions/Function0;)V
54 | public fun equals (Ljava/lang/Object;)Z
55 | public fun getFunctionDelegate ()Lkotlin/Function;
56 | public fun hashCode ()I
57 | public final synthetic fun onFinished ()V
58 | }
59 |
60 | public final class com/skydoves/elasticviews/ElasticCardView : androidx/cardview/widget/CardView, com/skydoves/elasticviews/ElasticInterface {
61 | public fun (Landroid/content/Context;)V
62 | public fun (Landroid/content/Context;Landroid/util/AttributeSet;)V
63 | public fun (Landroid/content/Context;Landroid/util/AttributeSet;I)V
64 | public synthetic fun (Landroid/content/Context;Landroid/util/AttributeSet;IILkotlin/jvm/internal/DefaultConstructorMarker;)V
65 | public final fun getDuration ()I
66 | public final fun getScale ()F
67 | public final fun setDuration (I)V
68 | public fun setOnClickListener (Landroid/view/View$OnClickListener;)V
69 | public fun setOnClickListener (Lkotlin/jvm/functions/Function1;)V
70 | public fun setOnFinishListener (Lcom/skydoves/elasticviews/ElasticFinishListener;)V
71 | public fun setOnFinishListener (Lkotlin/jvm/functions/Function0;)V
72 | public final fun setScale (F)V
73 | }
74 |
75 | public final class com/skydoves/elasticviews/ElasticCardView$Builder {
76 | public fun (Landroid/content/Context;)V
77 | public final fun build ()Lcom/skydoves/elasticviews/ElasticCardView;
78 | public final fun setDuration (I)Lcom/skydoves/elasticviews/ElasticCardView$Builder;
79 | public final fun setOnClickListener (Landroid/view/View$OnClickListener;)Lcom/skydoves/elasticviews/ElasticCardView$Builder;
80 | public final synthetic fun setOnClickListener (Lkotlin/jvm/functions/Function1;)Lcom/skydoves/elasticviews/ElasticCardView$Builder;
81 | public final fun setOnFinishListener (Lcom/skydoves/elasticviews/ElasticFinishListener;)Lcom/skydoves/elasticviews/ElasticCardView$Builder;
82 | public final synthetic fun setOnFinishListener (Lkotlin/jvm/functions/Function0;)Lcom/skydoves/elasticviews/ElasticCardView$Builder;
83 | public final fun setScale (F)Lcom/skydoves/elasticviews/ElasticCardView$Builder;
84 | }
85 |
86 | public final class com/skydoves/elasticviews/ElasticCardView$sam$i$android_view_View_OnClickListener$0 : android/view/View$OnClickListener {
87 | public fun (Lkotlin/jvm/functions/Function1;)V
88 | public final synthetic fun onClick (Landroid/view/View;)V
89 | }
90 |
91 | public final class com/skydoves/elasticviews/ElasticCardView$sam$i$com_skydoves_elasticviews_ElasticFinishListener$0 : com/skydoves/elasticviews/ElasticFinishListener, kotlin/jvm/internal/FunctionAdapter {
92 | public fun (Lkotlin/jvm/functions/Function0;)V
93 | public fun equals (Ljava/lang/Object;)Z
94 | public fun getFunctionDelegate ()Lkotlin/Function;
95 | public fun hashCode ()I
96 | public final synthetic fun onFinished ()V
97 | }
98 |
99 | public final class com/skydoves/elasticviews/ElasticCheckButton : androidx/appcompat/widget/AppCompatButton, com/skydoves/elasticviews/ElasticInterface {
100 | public fun (Landroid/content/Context;)V
101 | public fun (Landroid/content/Context;Landroid/util/AttributeSet;)V
102 | public fun (Landroid/content/Context;Landroid/util/AttributeSet;I)V
103 | public synthetic fun (Landroid/content/Context;Landroid/util/AttributeSet;IILkotlin/jvm/internal/DefaultConstructorMarker;)V
104 | public final fun getCheckedAlpha ()F
105 | public final fun getCornerRadius ()F
106 | public final fun getDuration ()I
107 | public final fun getScale ()F
108 | public final fun isChecked ()Z
109 | public final fun setChecked (Z)V
110 | public final fun setCheckedAlpha (F)V
111 | public final fun setCornerRadius (F)V
112 | public final fun setDuration (I)V
113 | public fun setOnClickListener (Landroid/view/View$OnClickListener;)V
114 | public fun setOnClickListener (Lkotlin/jvm/functions/Function1;)V
115 | public fun setOnFinishListener (Lcom/skydoves/elasticviews/ElasticFinishListener;)V
116 | public fun setOnFinishListener (Lkotlin/jvm/functions/Function0;)V
117 | public final fun setScale (F)V
118 | }
119 |
120 | public final class com/skydoves/elasticviews/ElasticCheckButton$Builder {
121 | public fun (Landroid/content/Context;)V
122 | public final fun build ()Lcom/skydoves/elasticviews/ElasticCheckButton;
123 | public final fun setCornerRadius (F)Lcom/skydoves/elasticviews/ElasticCheckButton$Builder;
124 | public final fun setDuration (I)Lcom/skydoves/elasticviews/ElasticCheckButton$Builder;
125 | public final fun setOnClickListener (Landroid/view/View$OnClickListener;)Lcom/skydoves/elasticviews/ElasticCheckButton$Builder;
126 | public final synthetic fun setOnClickListener (Lkotlin/jvm/functions/Function1;)Lcom/skydoves/elasticviews/ElasticCheckButton$Builder;
127 | public final fun setOnFinishListener (Lcom/skydoves/elasticviews/ElasticFinishListener;)Lcom/skydoves/elasticviews/ElasticCheckButton$Builder;
128 | public final synthetic fun setOnFinishListener (Lkotlin/jvm/functions/Function0;)Lcom/skydoves/elasticviews/ElasticCheckButton$Builder;
129 | public final fun setScale (F)Lcom/skydoves/elasticviews/ElasticCheckButton$Builder;
130 | }
131 |
132 | public final class com/skydoves/elasticviews/ElasticCheckButton$sam$i$android_view_View_OnClickListener$0 : android/view/View$OnClickListener {
133 | public fun (Lkotlin/jvm/functions/Function1;)V
134 | public final synthetic fun onClick (Landroid/view/View;)V
135 | }
136 |
137 | public final class com/skydoves/elasticviews/ElasticCheckButton$sam$i$com_skydoves_elasticviews_ElasticFinishListener$0 : com/skydoves/elasticviews/ElasticFinishListener, kotlin/jvm/internal/FunctionAdapter {
138 | public fun (Lkotlin/jvm/functions/Function0;)V
139 | public fun equals (Ljava/lang/Object;)Z
140 | public fun getFunctionDelegate ()Lkotlin/Function;
141 | public fun hashCode ()I
142 | public final synthetic fun onFinished ()V
143 | }
144 |
145 | public final class com/skydoves/elasticviews/ElasticExtensions {
146 | public static final fun elasticAnimation (Landroid/view/View;)Lcom/skydoves/elasticviews/ElasticAnimation;
147 | public static final fun elasticAnimation (Landroid/view/View;F)Lcom/skydoves/elasticviews/ElasticAnimation;
148 | public static final fun elasticAnimation (Landroid/view/View;FF)Lcom/skydoves/elasticviews/ElasticAnimation;
149 | public static final fun elasticAnimation (Landroid/view/View;FFI)Lcom/skydoves/elasticviews/ElasticAnimation;
150 | public static final synthetic fun elasticAnimation (Landroid/view/View;FFILcom/skydoves/elasticviews/ElasticFinishListener;)Lcom/skydoves/elasticviews/ElasticAnimation;
151 | public static final synthetic fun elasticAnimation (Landroid/view/View;FFILkotlin/jvm/functions/Function0;)Lcom/skydoves/elasticviews/ElasticAnimation;
152 | public static final fun elasticAnimation (Landroid/view/View;FFLkotlin/jvm/functions/Function0;)Lcom/skydoves/elasticviews/ElasticAnimation;
153 | public static final fun elasticAnimation (Landroid/view/View;FLkotlin/jvm/functions/Function0;)Lcom/skydoves/elasticviews/ElasticAnimation;
154 | public static final fun elasticAnimation (Landroid/view/View;Lkotlin/jvm/functions/Function0;)Lcom/skydoves/elasticviews/ElasticAnimation;
155 | public static final synthetic fun elasticAnimation (Landroid/view/View;Lkotlin/jvm/functions/Function1;)Lcom/skydoves/elasticviews/ElasticAnimation;
156 | public static synthetic fun elasticAnimation$default (Landroid/view/View;FFILcom/skydoves/elasticviews/ElasticFinishListener;ILjava/lang/Object;)Lcom/skydoves/elasticviews/ElasticAnimation;
157 | public static synthetic fun elasticAnimation$default (Landroid/view/View;FFILkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lcom/skydoves/elasticviews/ElasticAnimation;
158 | }
159 |
160 | public abstract interface class com/skydoves/elasticviews/ElasticFinishListener {
161 | public abstract fun onFinished ()V
162 | }
163 |
164 | public final class com/skydoves/elasticviews/ElasticFloatingActionButton : com/google/android/material/floatingactionbutton/FloatingActionButton, com/skydoves/elasticviews/ElasticInterface {
165 | public fun (Landroid/content/Context;)V
166 | public fun (Landroid/content/Context;Landroid/util/AttributeSet;)V
167 | public fun (Landroid/content/Context;Landroid/util/AttributeSet;I)V
168 | public synthetic fun (Landroid/content/Context;Landroid/util/AttributeSet;IILkotlin/jvm/internal/DefaultConstructorMarker;)V
169 | public final fun getDuration ()I
170 | public final fun getScale ()F
171 | public final fun setDuration (I)V
172 | public fun setOnClickListener (Landroid/view/View$OnClickListener;)V
173 | public fun setOnClickListener (Lkotlin/jvm/functions/Function1;)V
174 | public fun setOnFinishListener (Lcom/skydoves/elasticviews/ElasticFinishListener;)V
175 | public fun setOnFinishListener (Lkotlin/jvm/functions/Function0;)V
176 | public final fun setScale (F)V
177 | }
178 |
179 | public final class com/skydoves/elasticviews/ElasticFloatingActionButton$Builder {
180 | public fun (Landroid/content/Context;)V
181 | public final fun build ()Lcom/skydoves/elasticviews/ElasticFloatingActionButton;
182 | public final fun setDuration (I)Lcom/skydoves/elasticviews/ElasticFloatingActionButton$Builder;
183 | public final fun setOnClickListener (Landroid/view/View$OnClickListener;)Lcom/skydoves/elasticviews/ElasticFloatingActionButton$Builder;
184 | public final synthetic fun setOnClickListener (Lkotlin/jvm/functions/Function1;)Lcom/skydoves/elasticviews/ElasticFloatingActionButton$Builder;
185 | public final fun setOnFinishListener (Lcom/skydoves/elasticviews/ElasticFinishListener;)Lcom/skydoves/elasticviews/ElasticFloatingActionButton$Builder;
186 | public final synthetic fun setOnFinishListener (Lkotlin/jvm/functions/Function0;)Lcom/skydoves/elasticviews/ElasticFloatingActionButton$Builder;
187 | public final fun setScale (F)Lcom/skydoves/elasticviews/ElasticFloatingActionButton$Builder;
188 | }
189 |
190 | public final class com/skydoves/elasticviews/ElasticFloatingActionButton$sam$i$android_view_View_OnClickListener$0 : android/view/View$OnClickListener {
191 | public fun (Lkotlin/jvm/functions/Function1;)V
192 | public final synthetic fun onClick (Landroid/view/View;)V
193 | }
194 |
195 | public final class com/skydoves/elasticviews/ElasticFloatingActionButton$sam$i$com_skydoves_elasticviews_ElasticFinishListener$0 : com/skydoves/elasticviews/ElasticFinishListener, kotlin/jvm/internal/FunctionAdapter {
196 | public fun (Lkotlin/jvm/functions/Function0;)V
197 | public fun equals (Ljava/lang/Object;)Z
198 | public fun getFunctionDelegate ()Lkotlin/Function;
199 | public fun hashCode ()I
200 | public final synthetic fun onFinished ()V
201 | }
202 |
203 | public final class com/skydoves/elasticviews/ElasticImageView : androidx/appcompat/widget/AppCompatImageView, com/skydoves/elasticviews/ElasticInterface {
204 | public fun (Landroid/content/Context;)V
205 | public fun (Landroid/content/Context;Landroid/util/AttributeSet;)V
206 | public fun (Landroid/content/Context;Landroid/util/AttributeSet;I)V
207 | public synthetic fun (Landroid/content/Context;Landroid/util/AttributeSet;IILkotlin/jvm/internal/DefaultConstructorMarker;)V
208 | public final fun getDuration ()I
209 | public final fun getScale ()F
210 | public final fun setDuration (I)V
211 | public fun setOnClickListener (Landroid/view/View$OnClickListener;)V
212 | public fun setOnClickListener (Lkotlin/jvm/functions/Function1;)V
213 | public fun setOnFinishListener (Lcom/skydoves/elasticviews/ElasticFinishListener;)V
214 | public fun setOnFinishListener (Lkotlin/jvm/functions/Function0;)V
215 | public final fun setScale (F)V
216 | }
217 |
218 | public final class com/skydoves/elasticviews/ElasticImageView$Builder {
219 | public fun (Landroid/content/Context;)V
220 | public final fun build ()Lcom/skydoves/elasticviews/ElasticImageView;
221 | public final fun setDuration (I)Lcom/skydoves/elasticviews/ElasticImageView$Builder;
222 | public final fun setOnClickListener (Landroid/view/View$OnClickListener;)Lcom/skydoves/elasticviews/ElasticImageView$Builder;
223 | public final synthetic fun setOnClickListener (Lkotlin/jvm/functions/Function1;)Lcom/skydoves/elasticviews/ElasticImageView$Builder;
224 | public final fun setOnFinishListener (Lcom/skydoves/elasticviews/ElasticFinishListener;)Lcom/skydoves/elasticviews/ElasticImageView$Builder;
225 | public final synthetic fun setOnFinishListener (Lkotlin/jvm/functions/Function0;)Lcom/skydoves/elasticviews/ElasticImageView$Builder;
226 | public final fun setScale (F)Lcom/skydoves/elasticviews/ElasticImageView$Builder;
227 | }
228 |
229 | public final class com/skydoves/elasticviews/ElasticImageView$sam$i$android_view_View_OnClickListener$0 : android/view/View$OnClickListener {
230 | public fun (Lkotlin/jvm/functions/Function1;)V
231 | public final synthetic fun onClick (Landroid/view/View;)V
232 | }
233 |
234 | public final class com/skydoves/elasticviews/ElasticImageView$sam$i$com_skydoves_elasticviews_ElasticFinishListener$0 : com/skydoves/elasticviews/ElasticFinishListener, kotlin/jvm/internal/FunctionAdapter {
235 | public fun (Lkotlin/jvm/functions/Function0;)V
236 | public fun equals (Ljava/lang/Object;)Z
237 | public fun getFunctionDelegate ()Lkotlin/Function;
238 | public fun hashCode ()I
239 | public final synthetic fun onFinished ()V
240 | }
241 |
242 | public final class com/skydoves/elasticviews/ElasticLayout : android/widget/FrameLayout, com/skydoves/elasticviews/ElasticInterface {
243 | public fun (Landroid/content/Context;)V
244 | public fun (Landroid/content/Context;Landroid/util/AttributeSet;)V
245 | public fun (Landroid/content/Context;Landroid/util/AttributeSet;I)V
246 | public synthetic fun (Landroid/content/Context;Landroid/util/AttributeSet;IILkotlin/jvm/internal/DefaultConstructorMarker;)V
247 | public final fun getCornerRadius ()F
248 | public final fun getDuration ()I
249 | public final fun getScale ()F
250 | public final fun setCornerRadius (F)V
251 | public final fun setDuration (I)V
252 | public fun setOnClickListener (Landroid/view/View$OnClickListener;)V
253 | public fun setOnClickListener (Lkotlin/jvm/functions/Function1;)V
254 | public fun setOnFinishListener (Lcom/skydoves/elasticviews/ElasticFinishListener;)V
255 | public fun setOnFinishListener (Lkotlin/jvm/functions/Function0;)V
256 | public final fun setScale (F)V
257 | }
258 |
259 | public final class com/skydoves/elasticviews/ElasticLayout$Builder {
260 | public fun (Landroid/content/Context;)V
261 | public final fun build ()Lcom/skydoves/elasticviews/ElasticLayout;
262 | public final fun setCornerRadius (F)Lcom/skydoves/elasticviews/ElasticLayout$Builder;
263 | public final fun setDuration (I)Lcom/skydoves/elasticviews/ElasticLayout$Builder;
264 | public final fun setOnClickListener (Landroid/view/View$OnClickListener;)Lcom/skydoves/elasticviews/ElasticLayout$Builder;
265 | public final synthetic fun setOnClickListener (Lkotlin/jvm/functions/Function1;)Lcom/skydoves/elasticviews/ElasticLayout$Builder;
266 | public final fun setOnFinishListener (Lcom/skydoves/elasticviews/ElasticFinishListener;)Lcom/skydoves/elasticviews/ElasticLayout$Builder;
267 | public final synthetic fun setOnFinishListener (Lkotlin/jvm/functions/Function0;)Lcom/skydoves/elasticviews/ElasticLayout$Builder;
268 | public final fun setScale (F)Lcom/skydoves/elasticviews/ElasticLayout$Builder;
269 | }
270 |
271 | public final class com/skydoves/elasticviews/ElasticLayout$sam$i$android_view_View_OnClickListener$0 : android/view/View$OnClickListener {
272 | public fun (Lkotlin/jvm/functions/Function1;)V
273 | public final synthetic fun onClick (Landroid/view/View;)V
274 | }
275 |
276 | public final class com/skydoves/elasticviews/ElasticLayout$sam$i$com_skydoves_elasticviews_ElasticFinishListener$0 : com/skydoves/elasticviews/ElasticFinishListener, kotlin/jvm/internal/FunctionAdapter {
277 | public fun (Lkotlin/jvm/functions/Function0;)V
278 | public fun equals (Ljava/lang/Object;)Z
279 | public fun getFunctionDelegate ()Lkotlin/Function;
280 | public fun hashCode ()I
281 | public final synthetic fun onFinished ()V
282 | }
283 |
284 | public final class com/skydoves/elasticviews/ElasticView : android/view/View, com/skydoves/elasticviews/ElasticInterface {
285 | public fun (Landroid/content/Context;)V
286 | public fun (Landroid/content/Context;Landroid/util/AttributeSet;)V
287 | public fun (Landroid/content/Context;Landroid/util/AttributeSet;I)V
288 | public synthetic fun (Landroid/content/Context;Landroid/util/AttributeSet;IILkotlin/jvm/internal/DefaultConstructorMarker;)V
289 | public final fun getCornerRadius ()F
290 | public final fun getDuration ()I
291 | public final fun getScale ()F
292 | public final fun setCornerRadius (F)V
293 | public final fun setDuration (I)V
294 | public fun setOnClickListener (Landroid/view/View$OnClickListener;)V
295 | public fun setOnClickListener (Lkotlin/jvm/functions/Function1;)V
296 | public fun setOnFinishListener (Lcom/skydoves/elasticviews/ElasticFinishListener;)V
297 | public fun setOnFinishListener (Lkotlin/jvm/functions/Function0;)V
298 | public final fun setScale (F)V
299 | }
300 |
301 | public final class com/skydoves/elasticviews/ElasticView$Builder {
302 | public fun (Landroid/content/Context;)V
303 | public final fun build ()Lcom/skydoves/elasticviews/ElasticView;
304 | public final fun setCornerRadius (F)Lcom/skydoves/elasticviews/ElasticView$Builder;
305 | public final fun setDuration (I)Lcom/skydoves/elasticviews/ElasticView$Builder;
306 | public final fun setOnClickListener (Landroid/view/View$OnClickListener;)Lcom/skydoves/elasticviews/ElasticView$Builder;
307 | public final synthetic fun setOnClickListener (Lkotlin/jvm/functions/Function1;)Lcom/skydoves/elasticviews/ElasticView$Builder;
308 | public final fun setOnFinishListener (Lcom/skydoves/elasticviews/ElasticFinishListener;)Lcom/skydoves/elasticviews/ElasticView$Builder;
309 | public final synthetic fun setOnFinishListener (Lkotlin/jvm/functions/Function0;)Lcom/skydoves/elasticviews/ElasticView$Builder;
310 | public final fun setScale (F)Lcom/skydoves/elasticviews/ElasticView$Builder;
311 | }
312 |
313 | public final class com/skydoves/elasticviews/ElasticView$sam$i$android_view_View_OnClickListener$0 : android/view/View$OnClickListener {
314 | public fun (Lkotlin/jvm/functions/Function1;)V
315 | public final synthetic fun onClick (Landroid/view/View;)V
316 | }
317 |
318 | public final class com/skydoves/elasticviews/ElasticView$sam$i$com_skydoves_elasticviews_ElasticFinishListener$0 : com/skydoves/elasticviews/ElasticFinishListener, kotlin/jvm/internal/FunctionAdapter {
319 | public fun (Lkotlin/jvm/functions/Function0;)V
320 | public fun equals (Ljava/lang/Object;)Z
321 | public fun getFunctionDelegate ()Lkotlin/Function;
322 | public fun hashCode ()I
323 | public final synthetic fun onFinished ()V
324 | }
325 |
326 |
--------------------------------------------------------------------------------
/elasticviews/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'org.jetbrains.dokka'
4 | apply plugin: 'binary-compatibility-validator'
5 | apply from: '../dependencies.gradle'
6 |
7 | android {
8 | compileSdkVersion versions.compileSdk
9 | defaultConfig {
10 | minSdkVersion versions.minSdk
11 | targetSdkVersion versions.compileSdk
12 | versionCode versions.versionCode
13 | versionName versions.versionName
14 | }
15 | buildFeatures {
16 | buildConfig false
17 | }
18 | }
19 |
20 | kotlin {
21 | explicitApiWarning()
22 | }
23 |
24 | apiValidation {
25 | ignoredPackages += [
26 | "com/skydoves/elasticviews/databinding",
27 | ]
28 | nonPublicMarkers += [
29 | "kotlin.PublishedApi",
30 | ]
31 | }
32 |
33 | dependencies {
34 | implementation "com.google.android.material:material:$versions.googleMaterial"
35 | }
36 |
37 | apply plugin: "com.vanniktech.maven.publish"
38 | apply from: '../spotless.gradle'
--------------------------------------------------------------------------------
/elasticviews/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/elasticviews/src/main/java/com/skydoves/elasticviews/Definitions.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.skydoves.elasticviews
25 |
26 | @PublishedApi
27 | internal object Definitions {
28 | /** The default target elastic scale size of the animation. */
29 | const val DEFAULT_SCALE: Float = 0.9f
30 |
31 | /** The default target elastic scale-x size of the animation. */
32 | const val DEFAULT_SCALE_X: Float = 0.85f
33 |
34 | /** The default target elastic scale-y size of the animation. */
35 | const val DEFAULT_SCALE_Y: Float = 0.85f
36 |
37 | /** The default duration of the animation. */
38 | const val DEFAULT_DURATION: Int = 400
39 |
40 | /** The default anchor of the elastic animation. */
41 | const val DEFAULT_ANIMATION_ANCHOR = 0.5f
42 | }
43 |
--------------------------------------------------------------------------------
/elasticviews/src/main/java/com/skydoves/elasticviews/ElasticAnimation.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | @file:Suppress("unused")
25 |
26 | package com.skydoves.elasticviews
27 |
28 | import android.view.View
29 | import android.view.ViewGroup
30 | import android.view.animation.CycleInterpolator
31 | import androidx.core.view.ViewCompat
32 | import androidx.core.view.ViewPropertyAnimatorListener
33 | import com.skydoves.elasticviews.Definitions.DEFAULT_ANIMATION_ANCHOR
34 | import com.skydoves.elasticviews.Definitions.DEFAULT_DURATION
35 | import com.skydoves.elasticviews.Definitions.DEFAULT_SCALE_X
36 | import com.skydoves.elasticviews.Definitions.DEFAULT_SCALE_Y
37 |
38 | /** ElasticAnimation implements elastic animations for android views or view groups. */
39 | class ElasticAnimation(private val view: View) {
40 |
41 | @JvmField
42 | @set:JvmSynthetic
43 | var scaleX = DEFAULT_SCALE_X
44 |
45 | @JvmField
46 | @set:JvmSynthetic
47 | var scaleY = DEFAULT_SCALE_Y
48 |
49 | @JvmField
50 | @set:JvmSynthetic
51 | var duration = DEFAULT_DURATION
52 |
53 | @JvmField
54 | @set:JvmSynthetic
55 | var listener: ViewPropertyAnimatorListener? = null
56 |
57 | @JvmField
58 | @set:JvmSynthetic
59 | var finishListener: ElasticFinishListener? = null
60 |
61 | var isAnimating: Boolean = false
62 | private set
63 |
64 | /** Sets a target elastic scale-x size of the animation. */
65 | fun setScaleX(scaleX: Float): ElasticAnimation = apply { this.scaleX = scaleX }
66 |
67 | /** Sets a target elastic scale-y size of the animation. */
68 | fun setScaleY(scaleY: Float): ElasticAnimation = apply { this.scaleY = scaleY }
69 |
70 | /** Sets a duration of the animation. */
71 | fun setDuration(duration: Int): ElasticAnimation = apply { this.duration = duration }
72 |
73 | /** Sets an animator listener of the animation. */
74 | fun setListener(listener: ViewPropertyAnimatorListener): ElasticAnimation = apply {
75 | this.listener = listener
76 | }
77 |
78 | /** An animator listener of the animation. */
79 | fun setOnFinishListener(finishListener: ElasticFinishListener?): ElasticAnimation = apply {
80 | this.finishListener = finishListener
81 | }
82 |
83 | /** An [ElasticFinishListener] listener of the animation. */
84 | @JvmSynthetic
85 | inline fun setOnFinishListener(crossinline block: () -> Unit): ElasticAnimation = apply {
86 | this.finishListener = ElasticFinishListener { block() }
87 | }
88 |
89 | /** starts elastic animation. */
90 | fun doAction() {
91 | if (!isAnimating && view.scaleX == 1f) {
92 | val animatorCompat = ViewCompat.animate(view)
93 | .setDuration(duration.toLong())
94 | .scaleX(scaleX)
95 | .scaleY(scaleY)
96 | .setInterpolator(CycleInterpolator(DEFAULT_ANIMATION_ANCHOR)).apply {
97 | listener?.let { setListener(it) } ?: setListener(object : ViewPropertyAnimatorListener {
98 | override fun onAnimationCancel(view: View?) = Unit
99 | override fun onAnimationStart(view: View?) {
100 | isAnimating = true
101 | }
102 |
103 | override fun onAnimationEnd(view: View?) {
104 | finishListener?.onFinished()
105 | isAnimating = false
106 | }
107 | })
108 | }
109 | if (view is ViewGroup) {
110 | (0 until view.childCount).map { view.getChildAt(it) }.forEach { child ->
111 | ViewCompat.animate(child)
112 | .setDuration(duration.toLong())
113 | .scaleX(scaleX)
114 | .scaleY(scaleY)
115 | .setInterpolator(CycleInterpolator(DEFAULT_ANIMATION_ANCHOR))
116 | .withLayer()
117 | .start()
118 | }
119 | }
120 | animatorCompat.withLayer().start()
121 | }
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/elasticviews/src/main/java/com/skydoves/elasticviews/ElasticButton.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.skydoves.elasticviews
25 |
26 | import android.content.Context
27 | import android.content.res.TypedArray
28 | import android.graphics.drawable.ColorDrawable
29 | import android.graphics.drawable.GradientDrawable
30 | import android.util.AttributeSet
31 | import android.view.View
32 | import android.view.View.OnClickListener
33 | import androidx.annotation.Px
34 | import androidx.appcompat.widget.AppCompatButton
35 | import com.skydoves.elasticviews.Definitions.DEFAULT_DURATION
36 | import com.skydoves.elasticviews.Definitions.DEFAULT_SCALE
37 |
38 | @Suppress("unused")
39 | class ElasticButton @JvmOverloads constructor(
40 | context: Context,
41 | attrs: AttributeSet? = null,
42 | defStyle: Int = androidx.appcompat.R.attr.buttonStyle
43 | ) : AppCompatButton(context, attrs, defStyle), ElasticInterface {
44 |
45 | /** The target elastic scale size of the animation. */
46 | var scale = DEFAULT_SCALE
47 |
48 | /** The default duration of the animation. */
49 | var duration = DEFAULT_DURATION
50 |
51 | @Px
52 | var cornerRadius = 0f
53 |
54 | private var onClickListener: OnClickListener? = null
55 | private var onFinishListener: ElasticFinishListener? = null
56 |
57 | init {
58 | onCreate()
59 | when {
60 | attrs != null && defStyle != androidx.appcompat.R.attr.buttonStyle ->
61 | getAttrs(attrs, defStyle)
62 | attrs != null -> getAttrs(attrs)
63 | }
64 | }
65 |
66 | private fun onCreate() {
67 | this.isAllCaps = false
68 | super.setOnClickListener {
69 | elasticAnimation(this) {
70 | setDuration(this@ElasticButton.duration)
71 | setScaleX(this@ElasticButton.scale)
72 | setScaleY(this@ElasticButton.scale)
73 | setOnFinishListener { invokeListeners() }
74 | }.doAction()
75 | }
76 | }
77 |
78 | private fun getAttrs(attrs: AttributeSet) {
79 | val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ElasticButton)
80 | try {
81 | setTypeArray(typedArray)
82 | } finally {
83 | typedArray.recycle()
84 | }
85 | }
86 |
87 | private fun getAttrs(attrs: AttributeSet, defStyle: Int) {
88 | val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ElasticButton, defStyle, 0)
89 | try {
90 | setTypeArray(typedArray)
91 | } finally {
92 | typedArray.recycle()
93 | }
94 | }
95 |
96 | private fun setTypeArray(typedArray: TypedArray) {
97 | this.scale = typedArray.getFloat(R.styleable.ElasticButton_button_scale, this.scale)
98 | this.duration = typedArray.getInt(R.styleable.ElasticButton_button_duration, this.duration)
99 | this.cornerRadius =
100 | typedArray.getDimension(R.styleable.ElasticButton_button_cornerRadius, this.cornerRadius)
101 | }
102 |
103 | override fun onFinishInflate() {
104 | super.onFinishInflate()
105 | initializeBackground()
106 | }
107 |
108 | private fun initializeBackground() {
109 | if (background is ColorDrawable) {
110 | background = GradientDrawable().apply {
111 | cornerRadius = this@ElasticButton.cornerRadius
112 | setColor((background as ColorDrawable).color)
113 | }.mutate()
114 | }
115 | }
116 |
117 | override fun setOnClickListener(listener: OnClickListener?) {
118 | this.onClickListener = listener
119 | }
120 |
121 | override fun setOnFinishListener(listener: ElasticFinishListener?) {
122 | this.onFinishListener = listener
123 | }
124 |
125 | override fun setOnClickListener(block: (View) -> Unit) =
126 | setOnClickListener(OnClickListener(block))
127 |
128 | override fun setOnFinishListener(block: () -> Unit) =
129 | setOnFinishListener(ElasticFinishListener(block))
130 |
131 | private fun invokeListeners() {
132 | this.onClickListener?.onClick(this)
133 | this.onFinishListener?.onFinished()
134 | }
135 |
136 | /** Builder class for creating [ElasticButton]. */
137 | class Builder(context: Context) {
138 | private val elasticButton = ElasticButton(context)
139 |
140 | fun setScale(value: Float) = apply { this.elasticButton.scale = value }
141 | fun setDuration(value: Int) = apply { this.elasticButton.duration = value }
142 | fun setCornerRadius(@Px value: Float) = apply { this.elasticButton.cornerRadius = value }
143 |
144 | @JvmSynthetic
145 | fun setOnClickListener(block: (View) -> Unit) = apply {
146 | setOnClickListener(OnClickListener(block))
147 | }
148 |
149 | fun setOnClickListener(value: OnClickListener) = apply {
150 | this.elasticButton.setOnClickListener(value)
151 | }
152 |
153 | @JvmSynthetic
154 | fun setOnFinishListener(block: () -> Unit) = apply {
155 | setOnFinishListener(ElasticFinishListener(block))
156 | }
157 |
158 | fun setOnFinishListener(value: ElasticFinishListener) = apply {
159 | this.elasticButton.setOnFinishListener(value)
160 | }
161 |
162 | fun build() = this.elasticButton
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/elasticviews/src/main/java/com/skydoves/elasticviews/ElasticCardView.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.skydoves.elasticviews
25 |
26 | import android.content.Context
27 | import android.content.res.TypedArray
28 | import android.util.AttributeSet
29 | import android.view.View
30 | import android.view.View.OnClickListener
31 | import androidx.cardview.widget.CardView
32 |
33 | @Suppress("unused")
34 | class ElasticCardView @JvmOverloads constructor(
35 | context: Context,
36 | attrs: AttributeSet? = null,
37 | defStyle: Int = androidx.cardview.R.attr.cardViewStyle
38 | ) : CardView(context, attrs, defStyle), ElasticInterface {
39 |
40 | /** The target elastic scale size of the animation. */
41 | var scale = Definitions.DEFAULT_SCALE
42 |
43 | /** The default duration of the animation. */
44 | var duration = Definitions.DEFAULT_DURATION
45 |
46 | private var onUserClickListener: OnClickListener? = null
47 | private var onFinishListener: ElasticFinishListener? = null
48 |
49 | init {
50 | onCreate()
51 | when {
52 | attrs != null && defStyle != androidx.cardview.R.attr.cardViewStyle ->
53 | getAttrs(attrs, defStyle)
54 | attrs != null -> getAttrs(attrs)
55 | }
56 | }
57 |
58 | private fun onCreate() {
59 | super.setOnClickListener {
60 | elasticAnimation(this) {
61 | setDuration(this@ElasticCardView.duration)
62 | setScaleX(this@ElasticCardView.scale)
63 | setScaleY(this@ElasticCardView.scale)
64 | setOnFinishListener { invokeListeners() }
65 | }.doAction()
66 | }
67 | }
68 |
69 | private fun getAttrs(attrs: AttributeSet) {
70 | val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ElasticCardView)
71 | try {
72 | setTypeArray(typedArray)
73 | } finally {
74 | typedArray.recycle()
75 | }
76 | }
77 |
78 | private fun getAttrs(attrs: AttributeSet, defStyle: Int) {
79 | val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ElasticCardView, defStyle, 0)
80 | try {
81 | setTypeArray(typedArray)
82 | } finally {
83 | typedArray.recycle()
84 | }
85 | }
86 |
87 | private fun setTypeArray(typedArray: TypedArray) {
88 | this.scale = typedArray.getFloat(R.styleable.ElasticCardView_cardView_scale, this.scale)
89 | this.duration = typedArray.getInt(R.styleable.ElasticCardView_cardView_duration, this.duration)
90 | }
91 |
92 | override fun setOnClickListener(listener: OnClickListener?) {
93 | this.onUserClickListener = listener
94 | }
95 |
96 | override fun setOnFinishListener(listener: ElasticFinishListener?) {
97 | this.onFinishListener = listener
98 | }
99 |
100 | override fun setOnClickListener(block: (View) -> Unit) =
101 | setOnClickListener(OnClickListener(block))
102 |
103 | override fun setOnFinishListener(block: () -> Unit) =
104 | setOnFinishListener(ElasticFinishListener(block))
105 |
106 | private fun invokeListeners() {
107 | this.onUserClickListener?.onClick(this)
108 | this.onFinishListener?.onFinished()
109 | }
110 |
111 | /** Builder class for creating [ElasticCardView]. */
112 | class Builder(context: Context) {
113 | private val elasticCardView = ElasticCardView(context)
114 |
115 | fun setScale(value: Float) = apply { this.elasticCardView.scale = value }
116 | fun setDuration(value: Int) = apply { this.elasticCardView.duration = value }
117 |
118 | @JvmSynthetic
119 | fun setOnClickListener(block: (View) -> Unit) = apply {
120 | setOnClickListener(OnClickListener(block))
121 | }
122 |
123 | fun setOnClickListener(value: OnClickListener) = apply {
124 | this.elasticCardView.setOnClickListener(value)
125 | }
126 |
127 | @JvmSynthetic
128 | fun setOnFinishListener(block: () -> Unit) = apply {
129 | setOnFinishListener(ElasticFinishListener(block))
130 | }
131 |
132 | fun setOnFinishListener(value: ElasticFinishListener) = apply {
133 | this.elasticCardView.setOnFinishListener(value)
134 | }
135 |
136 | fun build() = this.elasticCardView
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/elasticviews/src/main/java/com/skydoves/elasticviews/ElasticCheckButton.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.skydoves.elasticviews
25 |
26 | import android.content.Context
27 | import android.content.res.TypedArray
28 | import android.graphics.drawable.ColorDrawable
29 | import android.graphics.drawable.GradientDrawable
30 | import android.util.AttributeSet
31 | import android.view.View
32 | import android.view.View.OnClickListener
33 | import androidx.annotation.FloatRange
34 | import androidx.annotation.Px
35 | import androidx.appcompat.widget.AppCompatButton
36 |
37 | @Suppress("unused")
38 | class ElasticCheckButton @JvmOverloads constructor(
39 | context: Context,
40 | attrs: AttributeSet? = null,
41 | defStyle: Int = androidx.appcompat.R.attr.buttonStyle
42 | ) : AppCompatButton(context, attrs, defStyle), ElasticInterface {
43 |
44 | /** The target elastic scale size of the animation. */
45 | var scale = Definitions.DEFAULT_SCALE
46 |
47 | /** The default duration of the animation. */
48 | var duration = Definitions.DEFAULT_DURATION
49 |
50 | @FloatRange(from = 0.0, to = 1.0)
51 | var checkedAlpha = 0.5f
52 | set(value) {
53 | field = value
54 | updateElasticCheckButton()
55 | }
56 |
57 | @Px
58 | var cornerRadius = 0f
59 |
60 | var isChecked = false
61 | set(value) {
62 | field = value
63 | updateElasticCheckButton()
64 | }
65 |
66 | private var onClickListener: OnClickListener? = null
67 | private var onFinishListener: ElasticFinishListener? = null
68 |
69 | init {
70 | onCreate()
71 | when {
72 | attrs != null && defStyle != androidx.appcompat.R.attr.buttonStyle ->
73 | getAttrs(attrs, defStyle)
74 | attrs != null -> getAttrs(attrs)
75 | }
76 | }
77 |
78 | private fun onCreate() {
79 | this.isAllCaps = false
80 | super.setOnClickListener {
81 | this.isChecked = !this.isChecked
82 | elasticAnimation(this) {
83 | setDuration(this@ElasticCheckButton.duration)
84 | setScaleX(this@ElasticCheckButton.scale)
85 | setScaleY(this@ElasticCheckButton.scale)
86 | setOnFinishListener { invokeListeners() }
87 | }.doAction()
88 | }
89 | }
90 |
91 | private fun getAttrs(attrs: AttributeSet) {
92 | val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ElasticCheckButton)
93 | try {
94 | setTypeArray(typedArray)
95 | } finally {
96 | typedArray.recycle()
97 | }
98 | }
99 |
100 | private fun getAttrs(attrs: AttributeSet, defStyle: Int) {
101 | val typedArray =
102 | context.obtainStyledAttributes(attrs, R.styleable.ElasticCheckButton, defStyle, 0)
103 | try {
104 | setTypeArray(typedArray)
105 | } finally {
106 | typedArray.recycle()
107 | }
108 | }
109 |
110 | private fun setTypeArray(typedArray: TypedArray) {
111 | this.scale = typedArray.getFloat(R.styleable.ElasticCheckButton_checkButton_scale, this.scale)
112 | this.duration =
113 | typedArray.getInt(R.styleable.ElasticCheckButton_checkButton_duration, this.duration)
114 | this.cornerRadius =
115 | typedArray.getDimension(
116 | R.styleable.ElasticCheckButton_checkButton_cornerRadius,
117 | this.cornerRadius
118 | )
119 | this.checkedAlpha =
120 | typedArray.getFloat(R.styleable.ElasticCheckButton_checkButton_alpha, this.checkedAlpha)
121 | this.isChecked =
122 | typedArray.getBoolean(R.styleable.ElasticCheckButton_checkButton_isChecked, this.isChecked)
123 | }
124 |
125 | override fun onFinishInflate() {
126 | super.onFinishInflate()
127 | initializeBackground()
128 | updateElasticCheckButton()
129 | }
130 |
131 | private fun initializeBackground() {
132 | if (background is ColorDrawable) {
133 | background = GradientDrawable().apply {
134 | cornerRadius = this@ElasticCheckButton.cornerRadius
135 | setColor((background as ColorDrawable).color)
136 | }.mutate()
137 | }
138 | }
139 |
140 | private fun updateElasticCheckButton() {
141 | if (this.isChecked) {
142 | this.alpha = this.checkedAlpha
143 | }
144 | }
145 |
146 | override fun setOnClickListener(listener: OnClickListener?) {
147 | this.onClickListener = listener
148 | }
149 |
150 | override fun setOnFinishListener(listener: ElasticFinishListener?) {
151 | this.onFinishListener = listener
152 | }
153 |
154 | override fun setOnClickListener(block: (View) -> Unit) =
155 | setOnClickListener(OnClickListener(block))
156 |
157 | override fun setOnFinishListener(block: () -> Unit) =
158 | setOnFinishListener(ElasticFinishListener(block))
159 |
160 | private fun invokeListeners() {
161 | this.alpha = when (this.isChecked) {
162 | true -> this.checkedAlpha
163 | false -> 1.0f
164 | }
165 | this.onClickListener?.onClick(this)
166 | this.onFinishListener?.onFinished()
167 | }
168 |
169 | /** Builder class for creating [ElasticCheckButton]. */
170 | class Builder(context: Context) {
171 | private val elasticCheckButton = ElasticCheckButton(context)
172 |
173 | fun setScale(value: Float) = apply { this.elasticCheckButton.scale = value }
174 | fun setDuration(value: Int) = apply { this.elasticCheckButton.duration = value }
175 | fun setCornerRadius(@Px value: Float) = apply { this.elasticCheckButton.cornerRadius = value }
176 |
177 | @JvmSynthetic
178 | fun setOnClickListener(block: (View) -> Unit) = apply {
179 | setOnClickListener(OnClickListener(block))
180 | }
181 |
182 | fun setOnClickListener(value: OnClickListener) = apply {
183 | this.elasticCheckButton.setOnClickListener(value)
184 | }
185 |
186 | @JvmSynthetic
187 | fun setOnFinishListener(block: () -> Unit) = apply {
188 | setOnFinishListener(ElasticFinishListener(block))
189 | }
190 |
191 | fun setOnFinishListener(value: ElasticFinishListener) = apply {
192 | this.elasticCheckButton.setOnFinishListener(value)
193 | }
194 |
195 | fun build() = this.elasticCheckButton
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/elasticviews/src/main/java/com/skydoves/elasticviews/ElasticExtensions.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | @file:Suppress("unused")
25 | @file:JvmName("ElasticExtensions")
26 | @file:JvmMultifileClass
27 |
28 | package com.skydoves.elasticviews
29 |
30 | import android.view.View
31 |
32 | @DslMarker
33 | internal annotation class ElasticDsl
34 |
35 | /**
36 | * An extension for operating elastic animation to the target view with custom attributes.
37 | *
38 | * @param scaleX The target elastic scale-x size of the animation.
39 | * @param scaleY The target elastic scale-y size of the animation.
40 | * @param duration The duration of the animation.
41 | * @param listener The [ElasticFinishListener] for being notified when the animation is finished.
42 | */
43 | @ElasticDsl
44 | @JvmOverloads
45 | @JvmSynthetic
46 | fun View.elasticAnimation(
47 | scaleX: Float = Definitions.DEFAULT_SCALE_X,
48 | scaleY: Float = Definitions.DEFAULT_SCALE_Y,
49 | duration: Int = Definitions.DEFAULT_DURATION,
50 | listener: ElasticFinishListener? = null
51 | ): ElasticAnimation {
52 | return ElasticAnimation(this)
53 | .setScaleX(scaleX)
54 | .setScaleY(scaleY)
55 | .setDuration(duration)
56 | .setOnFinishListener(listener)
57 | }
58 |
59 | /**
60 | * An extension for operating elastic animation to the target view with custom attributes.
61 | *
62 | * @param scaleX The target elastic scale-x size of the animation.
63 | * @param scaleY The target elastic scale-y size of the animation.
64 | * @param duration The duration of the animation.
65 | * @param block The lambda for being notified when the animation is finished.
66 | */
67 | @ElasticDsl
68 | @JvmOverloads
69 | @JvmSynthetic
70 | inline fun View.elasticAnimation(
71 | scaleX: Float = Definitions.DEFAULT_SCALE_X,
72 | scaleY: Float = Definitions.DEFAULT_SCALE_Y,
73 | duration: Int = Definitions.DEFAULT_DURATION,
74 | crossinline block: () -> Unit
75 | ): ElasticAnimation {
76 | return ElasticAnimation(this)
77 | .setScaleX(scaleX)
78 | .setScaleY(scaleY)
79 | .setDuration(duration)
80 | .setOnFinishListener(ElasticFinishListener { block() })
81 | }
82 |
83 | /**
84 | * An extension for creating elastic animation with kotlin dsl style.
85 | *
86 | * @param block The dsl block of the [ElasticAnimation].
87 | *
88 | * @return A new instance of the [ElasticAnimation].
89 | */
90 | @ElasticDsl
91 | @JvmSynthetic
92 | inline fun elasticAnimation(
93 | view: View,
94 | crossinline block: ElasticAnimation.() -> Unit
95 | ): ElasticAnimation = ElasticAnimation(view).apply(block)
96 |
--------------------------------------------------------------------------------
/elasticviews/src/main/java/com/skydoves/elasticviews/ElasticFinishListener.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.skydoves.elasticviews
25 |
26 | /** ElasticFinishListener is for listening elastic animation terminated status. */
27 | fun interface ElasticFinishListener {
28 |
29 | /** invoked when the elastic animation is terminated. */
30 | fun onFinished()
31 | }
32 |
--------------------------------------------------------------------------------
/elasticviews/src/main/java/com/skydoves/elasticviews/ElasticFloatingActionButton.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.skydoves.elasticviews
25 |
26 | import android.content.Context
27 | import android.content.res.TypedArray
28 | import android.util.AttributeSet
29 | import android.view.View
30 | import android.view.View.OnClickListener
31 | import com.google.android.material.floatingactionbutton.FloatingActionButton
32 |
33 | @Suppress("unused")
34 | class ElasticFloatingActionButton @JvmOverloads constructor(
35 | context: Context,
36 | attrs: AttributeSet? = null,
37 | defStyle: Int = com.google.android.material.R.attr.floatingActionButtonStyle
38 | ) : FloatingActionButton(context, attrs, defStyle), ElasticInterface {
39 |
40 | /** The target elastic scale size of the animation. */
41 | var scale = Definitions.DEFAULT_SCALE
42 |
43 | /** The default duration of the animation. */
44 | var duration = Definitions.DEFAULT_DURATION
45 |
46 | private var onClickListener: OnClickListener? = null
47 | private var onFinishListener: ElasticFinishListener? = null
48 |
49 | init {
50 | onCreate()
51 | when {
52 | attrs != null && defStyle != com.google.android.material.R.attr.floatingActionButtonStyle ->
53 | getAttrs(attrs, defStyle)
54 | attrs != null -> getAttrs(attrs)
55 | }
56 | }
57 |
58 | private fun onCreate() {
59 | this.isClickable = true
60 | super.setOnClickListener {
61 | elasticAnimation(this) {
62 | setDuration(this@ElasticFloatingActionButton.duration)
63 | setScaleX(this@ElasticFloatingActionButton.scale)
64 | setScaleY(this@ElasticFloatingActionButton.scale)
65 | setOnFinishListener { invokeListeners() }
66 | }.doAction()
67 | }
68 | }
69 |
70 | private fun getAttrs(attrs: AttributeSet) {
71 | val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ElasticFloatingActionButton)
72 | setTypeArray(typedArray)
73 | }
74 |
75 | private fun getAttrs(attrs: AttributeSet, defStyle: Int) {
76 | val typedArray =
77 | context.obtainStyledAttributes(attrs, R.styleable.ElasticFloatingActionButton, defStyle, 0)
78 | setTypeArray(typedArray)
79 | }
80 |
81 | private fun setTypeArray(typedArray: TypedArray) {
82 | this.scale = typedArray.getFloat(R.styleable.ElasticFloatingActionButton_fabutton_scale, scale)
83 | this.duration =
84 | typedArray.getInt(R.styleable.ElasticFloatingActionButton_fabutton_duration, duration)
85 | }
86 |
87 | override fun setOnClickListener(listener: OnClickListener?) {
88 | this.onClickListener = listener
89 | }
90 |
91 | override fun setOnFinishListener(listener: ElasticFinishListener?) {
92 | this.onFinishListener = listener
93 | }
94 |
95 | override fun setOnClickListener(block: (View) -> Unit) =
96 | setOnClickListener(OnClickListener(block))
97 |
98 | override fun setOnFinishListener(block: () -> Unit) =
99 | setOnFinishListener(ElasticFinishListener(block))
100 |
101 | private fun invokeListeners() {
102 | this.onClickListener?.onClick(this)
103 | this.onFinishListener?.onFinished()
104 | }
105 |
106 | /** Builder class for creating [ElasticFloatingActionButton]. */
107 | class Builder(context: Context) {
108 | private val elasticFloatingButton = ElasticFloatingActionButton(context)
109 |
110 | fun setScale(value: Float) = apply { this.elasticFloatingButton.scale = value }
111 | fun setDuration(value: Int) = apply { this.elasticFloatingButton.duration = value }
112 |
113 | @JvmSynthetic
114 | fun setOnClickListener(block: (View) -> Unit) = apply {
115 | setOnClickListener(OnClickListener(block))
116 | }
117 |
118 | fun setOnClickListener(value: OnClickListener) = apply {
119 | this.elasticFloatingButton.setOnClickListener(value)
120 | }
121 |
122 | @JvmSynthetic
123 | fun setOnFinishListener(block: () -> Unit) = apply {
124 | setOnFinishListener(ElasticFinishListener(block))
125 | }
126 |
127 | fun setOnFinishListener(value: ElasticFinishListener) = apply {
128 | this.elasticFloatingButton.setOnFinishListener(value)
129 | }
130 |
131 | fun build() = this.elasticFloatingButton
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/elasticviews/src/main/java/com/skydoves/elasticviews/ElasticImageView.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.skydoves.elasticviews
25 |
26 | import android.content.Context
27 | import android.content.res.TypedArray
28 | import android.util.AttributeSet
29 | import android.view.View
30 | import android.view.View.OnClickListener
31 | import androidx.appcompat.widget.AppCompatImageView
32 |
33 | @Suppress("unused")
34 | class ElasticImageView @JvmOverloads constructor(
35 | context: Context,
36 | attrs: AttributeSet? = null,
37 | defStyle: Int = 0
38 | ) : AppCompatImageView(context, attrs, defStyle), ElasticInterface {
39 |
40 | /** The target elastic scale size of the animation. */
41 | var scale = Definitions.DEFAULT_SCALE
42 |
43 | /** The default duration of the animation. */
44 | var duration = Definitions.DEFAULT_DURATION
45 |
46 | private var onClickListener: OnClickListener? = null
47 | private var onFinishListener: ElasticFinishListener? = null
48 |
49 | init {
50 | onCreate()
51 | when {
52 | attrs != null && defStyle != 0 -> getAttrs(attrs, defStyle)
53 | attrs != null -> getAttrs(attrs)
54 | }
55 | }
56 |
57 | private fun onCreate() {
58 | this.isClickable = true
59 | super.setOnClickListener {
60 | elasticAnimation(this) {
61 | setDuration(this@ElasticImageView.duration)
62 | setScaleX(this@ElasticImageView.scale)
63 | setScaleY(this@ElasticImageView.scale)
64 | setOnFinishListener { invokeListeners() }
65 | }.doAction()
66 | }
67 | }
68 |
69 | private fun getAttrs(attrs: AttributeSet) {
70 | val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ElasticImageView)
71 | try {
72 | setTypeArray(typedArray)
73 | } finally {
74 | typedArray.recycle()
75 | }
76 | }
77 |
78 | private fun getAttrs(attrs: AttributeSet, defStyle: Int) {
79 | val typedArray =
80 | context.obtainStyledAttributes(attrs, R.styleable.ElasticImageView, defStyle, 0)
81 | try {
82 | setTypeArray(typedArray)
83 | } finally {
84 | typedArray.recycle()
85 | }
86 | }
87 |
88 | private fun setTypeArray(typedArray: TypedArray) {
89 | this.scale = typedArray.getFloat(R.styleable.ElasticImageView_imageView_scale, scale)
90 | this.duration = typedArray.getInt(R.styleable.ElasticImageView_imageView_duration, duration)
91 | }
92 |
93 | override fun setOnClickListener(listener: OnClickListener?) {
94 | this.onClickListener = listener
95 | }
96 |
97 | override fun setOnFinishListener(listener: ElasticFinishListener?) {
98 | this.onFinishListener = listener
99 | }
100 |
101 | override fun setOnClickListener(block: (View) -> Unit) =
102 | setOnClickListener(OnClickListener(block))
103 |
104 | override fun setOnFinishListener(block: () -> Unit) =
105 | setOnFinishListener(ElasticFinishListener(block))
106 |
107 | private fun invokeListeners() {
108 | this.onClickListener?.onClick(this)
109 | this.onFinishListener?.onFinished()
110 | }
111 |
112 | /** Builder class for creating [ElasticImageView]. */
113 | class Builder(context: Context) {
114 | private val elasticImageView = ElasticImageView(context)
115 |
116 | fun setScale(value: Float) = apply { this.elasticImageView.scale = value }
117 | fun setDuration(value: Int) = apply { this.elasticImageView.duration = value }
118 |
119 | @JvmSynthetic
120 | fun setOnClickListener(block: (View) -> Unit) = apply {
121 | setOnClickListener(OnClickListener(block))
122 | }
123 |
124 | fun setOnClickListener(value: OnClickListener) = apply {
125 | this.elasticImageView.setOnClickListener(value)
126 | }
127 |
128 | @JvmSynthetic
129 | fun setOnFinishListener(block: () -> Unit) = apply {
130 | setOnFinishListener(ElasticFinishListener(block))
131 | }
132 |
133 | fun setOnFinishListener(value: ElasticFinishListener) = apply {
134 | this.elasticImageView.setOnFinishListener(value)
135 | }
136 |
137 | fun build() = this.elasticImageView
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/elasticviews/src/main/java/com/skydoves/elasticviews/ElasticInterface.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.skydoves.elasticviews
25 |
26 | import android.view.View
27 |
28 | /**
29 | * ElasticView is an interface for abstracting elastic view's listener.
30 | */
31 | internal interface ElasticInterface {
32 |
33 | fun setOnClickListener(block: (View) -> Unit)
34 |
35 | fun setOnFinishListener(listener: ElasticFinishListener?)
36 |
37 | fun setOnFinishListener(block: () -> Unit)
38 | }
39 |
--------------------------------------------------------------------------------
/elasticviews/src/main/java/com/skydoves/elasticviews/ElasticLayout.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.skydoves.elasticviews
25 |
26 | import android.content.Context
27 | import android.content.res.TypedArray
28 | import android.graphics.drawable.ColorDrawable
29 | import android.graphics.drawable.GradientDrawable
30 | import android.util.AttributeSet
31 | import android.view.View
32 | import android.view.View.OnClickListener
33 | import android.widget.FrameLayout
34 | import androidx.annotation.Px
35 |
36 | @Suppress("unused")
37 | class ElasticLayout @JvmOverloads constructor(
38 | context: Context,
39 | attrs: AttributeSet? = null,
40 | defStyle: Int = 0
41 | ) : FrameLayout(context, attrs, defStyle), ElasticInterface {
42 |
43 | /** The target elastic scale size of the animation. */
44 | var scale = Definitions.DEFAULT_SCALE
45 |
46 | /** The default duration of the animation. */
47 | var duration = Definitions.DEFAULT_DURATION
48 |
49 | @Px
50 | var cornerRadius = 0f
51 |
52 | private var onClickListener: OnClickListener? = null
53 | private var onFinishListener: ElasticFinishListener? = null
54 |
55 | init {
56 | onCreate()
57 | when {
58 | attrs != null && defStyle != 0 -> getAttrs(attrs, defStyle)
59 | attrs != null -> getAttrs(attrs)
60 | }
61 | }
62 |
63 | private fun onCreate() {
64 | this.isClickable = true
65 | this.isFocusable = true
66 | super.setOnClickListener {
67 | elasticAnimation(this) {
68 | setDuration(this@ElasticLayout.duration)
69 | setScaleX(this@ElasticLayout.scale)
70 | setScaleY(this@ElasticLayout.scale)
71 | setOnFinishListener { invokeListeners() }
72 | }.doAction()
73 | }
74 | }
75 |
76 | private fun getAttrs(attrs: AttributeSet) {
77 | val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ElasticLayout)
78 | try {
79 | setTypeArray(typedArray)
80 | } finally {
81 | typedArray.recycle()
82 | }
83 | }
84 |
85 | private fun getAttrs(attrs: AttributeSet, defStyle: Int) {
86 | val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ElasticLayout, defStyle, 0)
87 | try {
88 | setTypeArray(typedArray)
89 | } finally {
90 | typedArray.recycle()
91 | }
92 | }
93 |
94 | private fun setTypeArray(typedArray: TypedArray) {
95 | this.scale = typedArray.getFloat(R.styleable.ElasticLayout_layout_scale, this.scale)
96 | this.duration = typedArray.getInt(R.styleable.ElasticLayout_layout_duration, this.duration)
97 | this.cornerRadius =
98 | typedArray.getDimension(R.styleable.ElasticLayout_layout_cornerRadius, this.cornerRadius)
99 | }
100 |
101 | override fun onFinishInflate() {
102 | super.onFinishInflate()
103 | initializeBackground()
104 | }
105 |
106 | private fun initializeBackground() {
107 | if (background is ColorDrawable) {
108 | background = GradientDrawable().apply {
109 | cornerRadius = this@ElasticLayout.cornerRadius
110 | setColor((background as ColorDrawable).color)
111 | }.mutate()
112 | }
113 | }
114 |
115 | override fun setOnClickListener(listener: OnClickListener?) {
116 | this.onClickListener = listener
117 | }
118 |
119 | override fun setOnFinishListener(listener: ElasticFinishListener?) {
120 | this.onFinishListener = listener
121 | }
122 |
123 | override fun setOnClickListener(block: (View) -> Unit) =
124 | setOnClickListener(OnClickListener(block))
125 |
126 | override fun setOnFinishListener(block: () -> Unit) =
127 | setOnFinishListener(ElasticFinishListener(block))
128 |
129 | private fun invokeListeners() {
130 | this.onClickListener?.onClick(this)
131 | this.onFinishListener?.onFinished()
132 | }
133 |
134 | /** Builder class for creating [ElasticLayout]. */
135 | class Builder(context: Context) {
136 | private val elasticLayout = ElasticLayout(context)
137 |
138 | fun setScale(value: Float) = apply { this.elasticLayout.scale = value }
139 | fun setDuration(value: Int) = apply { this.elasticLayout.duration = value }
140 | fun setCornerRadius(@Px value: Float) = apply { this.elasticLayout.cornerRadius = value }
141 |
142 | @JvmSynthetic
143 | fun setOnClickListener(block: (View) -> Unit) = apply {
144 | setOnClickListener(OnClickListener(block))
145 | }
146 |
147 | fun setOnClickListener(value: OnClickListener) = apply {
148 | this.elasticLayout.setOnClickListener(value)
149 | }
150 |
151 | @JvmSynthetic
152 | fun setOnFinishListener(block: () -> Unit) = apply {
153 | setOnFinishListener(ElasticFinishListener(block))
154 | }
155 |
156 | fun setOnFinishListener(value: ElasticFinishListener) = apply {
157 | this.elasticLayout.setOnFinishListener(value)
158 | }
159 |
160 | fun build() = this.elasticLayout
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/elasticviews/src/main/java/com/skydoves/elasticviews/ElasticView.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.skydoves.elasticviews
25 |
26 | import android.content.Context
27 | import android.content.res.TypedArray
28 | import android.graphics.drawable.ColorDrawable
29 | import android.graphics.drawable.GradientDrawable
30 | import android.util.AttributeSet
31 | import android.view.View
32 | import android.view.View.OnClickListener
33 | import androidx.annotation.Px
34 |
35 | @Suppress("unused")
36 | class ElasticView @JvmOverloads constructor(
37 | context: Context,
38 | attrs: AttributeSet? = null,
39 | defStyle: Int = 0
40 | ) : View(context, attrs, defStyle), ElasticInterface {
41 |
42 | /** The target elastic scale size of the animation. */
43 | var scale = Definitions.DEFAULT_SCALE
44 |
45 | /** The default duration of the animation. */
46 | var duration = Definitions.DEFAULT_DURATION
47 |
48 | @Px
49 | var cornerRadius = 0f
50 |
51 | private var onUserClickListener: OnClickListener? = null
52 | private var onFinishListener: ElasticFinishListener? = null
53 |
54 | init {
55 | onCreate()
56 | when {
57 | attrs != null && defStyle != 0 -> getAttrs(attrs, defStyle)
58 | attrs != null -> getAttrs(attrs)
59 | }
60 | }
61 |
62 | private fun onCreate() {
63 | super.setOnClickListener {
64 | elasticAnimation(this) {
65 | setDuration(this@ElasticView.duration)
66 | setScaleX(this@ElasticView.scale)
67 | setScaleY(this@ElasticView.scale)
68 | setOnFinishListener { invokeListeners() }
69 | }.doAction()
70 | }
71 | }
72 |
73 | private fun getAttrs(attrs: AttributeSet) {
74 | val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ElasticView)
75 | try {
76 | setTypeArray(typedArray)
77 | } finally {
78 | typedArray.recycle()
79 | }
80 | }
81 |
82 | private fun getAttrs(attrs: AttributeSet, defStyle: Int) {
83 | val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ElasticView, defStyle, 0)
84 | try {
85 | setTypeArray(typedArray)
86 | } finally {
87 | typedArray.recycle()
88 | }
89 | }
90 |
91 | private fun setTypeArray(typedArray: TypedArray) {
92 | this.scale = typedArray.getFloat(R.styleable.ElasticView_view_scale, this.scale)
93 | this.duration = typedArray.getInt(R.styleable.ElasticView_view_duration, this.duration)
94 | this.cornerRadius =
95 | typedArray.getDimension(R.styleable.ElasticView_view_cornerRadius, this.cornerRadius)
96 | }
97 |
98 | override fun onFinishInflate() {
99 | super.onFinishInflate()
100 | initializeBackground()
101 | }
102 |
103 | private fun initializeBackground() {
104 | if (background is ColorDrawable) {
105 | background = GradientDrawable().apply {
106 | cornerRadius = this@ElasticView.cornerRadius
107 | setColor((background as ColorDrawable).color)
108 | }.mutate()
109 | }
110 | }
111 |
112 | override fun setOnClickListener(listener: OnClickListener?) {
113 | this.onUserClickListener = listener
114 | }
115 |
116 | override fun setOnFinishListener(listener: ElasticFinishListener?) {
117 | this.onFinishListener = listener
118 | }
119 |
120 | override fun setOnClickListener(block: (View) -> Unit) =
121 | setOnClickListener(OnClickListener(block))
122 |
123 | override fun setOnFinishListener(block: () -> Unit) =
124 | setOnFinishListener(ElasticFinishListener(block))
125 |
126 | private fun invokeListeners() {
127 | this.onUserClickListener?.onClick(this)
128 | this.onFinishListener?.onFinished()
129 | }
130 |
131 | /** Builder class for creating [ElasticView]. */
132 | class Builder(context: Context) {
133 | private val elasticView = ElasticView(context)
134 |
135 | fun setScale(value: Float) = apply { this.elasticView.scale = value }
136 | fun setDuration(value: Int) = apply { this.elasticView.duration = value }
137 | fun setCornerRadius(@Px value: Float) = apply { this.elasticView.cornerRadius = value }
138 |
139 | @JvmSynthetic
140 | fun setOnClickListener(block: (View) -> Unit) = apply {
141 | setOnClickListener(OnClickListener(block))
142 | }
143 |
144 | fun setOnClickListener(value: OnClickListener) = apply {
145 | this.elasticView.setOnClickListener(value)
146 | }
147 |
148 | @JvmSynthetic
149 | fun setOnFinishListener(block: () -> Unit) = apply {
150 | setOnFinishListener(ElasticFinishListener(block))
151 | }
152 |
153 | fun setOnFinishListener(value: ElasticFinishListener) = apply {
154 | this.elasticView.setOnFinishListener(value)
155 | }
156 |
157 | fun build() = this.elasticView
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/elasticviews/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2019 skydoves (Jaewoong Eum)
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 |
17 | # Jvm environments
18 | org.gradle.jvmargs=-Xmx4g
19 |
20 | # AndroidX
21 | android.useAndroidX=true
22 |
23 | # Required to publish to Nexus
24 | systemProp.org.gradle.internal.publish.checksums.insecure=true
25 |
26 | # Increase timeout when pushing to Sonatype
27 | systemProp.org.gradle.internal.http.connectionTimeout=120000
28 | systemProp.org.gradle.internal.http.socketTimeout=120000
29 |
30 | # Maven
31 | GROUP=com.github.skydoves
32 | POM_PACKAGING=aar
33 |
34 | VERSION_NAME=2.1.1-SNAPSHOT
35 |
36 | POM_ARTIFACT_ID=elasticviews
37 | POM_NAME=elasticviews
38 | POM_DESCRIPTION=An easy way to implement an elastic touch effect for Android.
39 |
40 | POM_URL=https://github.com/skydoves/elasticviews/
41 | POM_SCM_URL=https://github.com/skydoves/elasticviews/
42 | POM_SCM_CONNECTION=scm:git:git://github.com/skydoves/elasticviews.git
43 | POM_SCM_DEV_CONNECTION=scm:git:git://github.com/skydoves/elasticviews.git
44 |
45 | POM_LICENCE_NAME=The Apache Software License, Version 2.0
46 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
47 | POM_LICENCE_DIST=repo
48 |
49 | POM_DEVELOPER_ID=skydoves
50 | POM_DEVELOPER_NAME=Jaewoong Eum
51 | POM_DEVELOPER_URL=https://github.com/skydoves/
52 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skydoves/ElasticViews/752955421fcd12addd59a4e3dd817b2336cebba5/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Oct 24 22:39:59 KST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
7 |
--------------------------------------------------------------------------------
/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 ':app', ':elasticviews'
2 |
--------------------------------------------------------------------------------
/spotless.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.diffplug.spotless"
2 | apply from: '../dependencies.gradle'
3 | spotless {
4 | kotlin {
5 | target "**/*.kt"
6 | ktlint("$versions.ktlintGradle").userData(['indent_size': '2', 'continuation_indent_size': '2'])
7 | licenseHeaderFile '../spotless.license.kt'
8 | trimTrailingWhitespace()
9 | endWithNewline()
10 | }
11 | }
--------------------------------------------------------------------------------
/spotless.license.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2017 skydoves
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
--------------------------------------------------------------------------------