├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── app
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── id
│ │ └── ss564
│ │ └── sample
│ │ └── swipebuttonexample
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── id
│ │ │ └── ss564
│ │ │ └── sample
│ │ │ └── swipebuttonexample
│ │ │ └── MainActivity.kt
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── ic_arrow_forward.xml
│ │ ├── ic_check_circle.xml
│ │ ├── ic_chevron_right.xml
│ │ ├── ic_favorite.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_lock_open.xml
│ │ ├── ic_lock_outline.xml
│ │ ├── oval_morp_shadow.png
│ │ ├── sliding_background.xml
│ │ ├── sliding_button_background.xml
│ │ ├── sliding_button_oval_background.xml
│ │ ├── sliding_button_oval_background_2.xml
│ │ ├── sliding_button_oval_background_3.xml
│ │ ├── sliding_icon_example_2.xml
│ │ ├── sliding_icon_example_3.xml
│ │ ├── sliding_icon_tint.xml
│ │ ├── sliding_icon_tint_example_2.xml
│ │ ├── sliding_rect_background.xml
│ │ ├── sliding_rect_background_2.xml
│ │ ├── sliding_rect_background_3.xml
│ │ ├── sliding_shape_background.xml
│ │ └── sliding_track_tint_example_3.xml
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.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
│ └── test
│ └── java
│ └── id
│ └── ss564
│ └── sample
│ └── swipebuttonexample
│ └── ExampleUnitTest.kt
├── build.gradle
├── gradle.properties
├── previews
├── preview_sample_a_1.jpg
├── preview_sample_a_2.jpg
├── preview_sample_a_3.jpg
├── preview_sample_a_4.jpg
├── preview_sample_b_1.JPG
├── preview_sample_b_2.JPG
├── preview_sample_b_3.JPG
└── preview_sample_b_4.JPG
├── settings.gradle
└── slidingbutton
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
├── androidTest
└── java
│ └── id
│ └── ss564
│ └── lib
│ └── slidingbutton
│ └── ExampleInstrumentedTest.kt
├── main
├── AndroidManifest.xml
├── java
│ └── id
│ │ └── ss564
│ │ └── lib
│ │ └── slidingbutton
│ │ └── SlidingButton.kt
└── res
│ ├── drawable-v21
│ ├── default_sliding_indicator_background.xml
│ ├── default_slidingbutton_background.xml
│ └── ic_default_slide_icon_new.xml
│ ├── drawable
│ ├── default_sliding_indicator_background.xml
│ ├── default_slidingbutton_background.xml
│ ├── default_slidingcontainer_background.xml
│ └── ic_default_slide_icon.png
│ ├── layout
│ └── layout_button.xml
│ └── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── public.xml
│ ├── strings.xml
│ └── styles.xml
└── test
└── java
└── id
└── ss564
└── lib
└── slidingbutton
└── ExampleUnitTest.kt
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 |
4 |
5 | ## Version 2.0.0 _(15 Apr 2020)_
6 |
7 | Behavior change on state listener, rename to `OnStateChangeListener`. So you can listen *state change* using method `setOnStateChangeListener()` with value `SlidingButton.OnStateChangeListener`.
8 |
9 | Change state rename to `slidingButton.changeState(active,animated)`
10 |
11 |
12 |
13 | Additional listener when button sliding. You can now listen it using method `setOnSlidingListener()` with value `SlidingButton.OnSlidingListener`. For example :
14 |
15 | - Java
16 |
17 | ```java
18 | slidingButton.setOnSlidingListener(new SlidingButton.OnSlidingListener{
19 |
20 | @Override
21 | public void onChange(float progress){
22 | // do what you wanna do
23 | }
24 | });
25 | ```
26 |
27 |
28 |
29 | - Kotlin
30 |
31 | ```kotlin
32 | slidingButton.setOnSlidingListener { progress ->
33 | // do what you wanna do
34 | }
35 | ```
36 |
37 |
38 |
39 | Additional features like **text alpha** when sliding the button, **track indicator** and **corner radius** (especially for API 21). You can set using attributes like the following :
40 |
41 | - `app:sliding_enabledTextAlpha`
42 |
43 | Use to alpha text when sliding, value of this attribute **Boolean**. Default value true
44 |
45 | - `app:sliding_showTrack`
46 |
47 | Use to show track indicator when sliding, value of this attribute **Boolean**. Default value false
48 |
49 | - `app:sliding_trackBackground`
50 |
51 | Use to set track indicator background.
52 |
53 | - `app:sliding_trackBackgroundTint`
54 |
55 | Use to set tint track indicator background.
56 |
57 | - `app:sliding_trackExtendTo`
58 |
59 | Use to set track extended to `container` or `button`
60 |
61 | - `app:sliding_corner_radius` only on API level 21 (Lollipop)
62 |
63 |
64 |
65 | -------
66 |
67 | ## Version 1.0.2 _(09 Apr 2020)_
68 |
69 | Add method to change status programmatically. So you can change status use method `changeStatus(active,animated)` as you needed
70 |
71 |
72 |
73 | -------
74 |
75 | ## Version 1.0.1 _(03 Apr 2020)_
76 | Linked to `jcenter()`, Now not need to add maven url to repositories `build.gradle` project level.
77 | If you still using `v1.0.0`, should add maven url to repositories `build.gradle` project level
78 | ```groovy
79 | repositories {
80 | ...
81 | maven { url 'https://dl.bintray.com/ss564/SlidingButton' }
82 | ...
83 | }
84 | ```
85 |
86 |
87 |
88 | -------
89 |
90 | ## Version 1.0.0 _(03 Apr 2020)_
91 |
92 | Slide button library for android, we hope this library is useful and easy to customize as you needed.
93 |
94 |
95 |
96 | -------
97 |
98 | ## Version 1.0.0-rc _(03 Apr 2020)_
99 |
100 | First launch as pre-release version
101 |
102 | > **Note** : Don't use this version, coz we have an missed configuration, so this version can't be used
103 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at kedai564@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Source Set 564 Contributors
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 all
13 | 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 THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SlidingButton
2 |
3 | 
4 | 
5 |
6 | Slide button library for android, we hope this library is useful and easy to customize as you needed. For additional information you can see [**change log**](https://github.com/Source-Set-564/SlidingButton/blob/master/CHANGELOG.md)
7 |
8 | ### Sample Preview
9 |
10 |
11 |
12 | #### Sample A
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | #### Sample B
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | --------
31 |
32 | # Gradle
33 |
34 | Add **dependencies** to your `build.gradle` file at `:app` or modules level
35 |
36 | ```groovy
37 | implementation 'id.ss564.lib.slidingbutton:slidingbutton:'
38 | ```
39 |
40 | and don't forget add `jcenter()` to your repository
41 | ```groovy
42 | repositories {
43 | //...
44 | jcenter()
45 | //...
46 | }
47 | ```
48 |
49 | Then **sync** your gradle.
50 |
51 | ----------
52 |
53 | # How To Use
54 |
55 | > **Notes** : This guide is still in process, I will work on it as soon as possible. So, keep checking later if you see this note.
56 |
57 |
58 |
59 | In your *layout.xml* file, add the view
60 |
61 | ```xml
62 |
66 | ```
67 |
68 | Yeah... just add like code above. It's pretty simple :smile:
69 |
70 | You can use `SlidingButton.OnStateChangeListener` to find out if the button is shifted or not. Just add a little bit code like below on your `java` or `kotlin` file, for example on **MainActivity**
71 |
72 | - Java
73 |
74 | ```java
75 | public class MainActivity extend AppCompatActivty {
76 |
77 | @Override
78 | protected void onCreate(Bundle savedInstanceState){
79 | super.onCreate(savedInstanceState);
80 | setContentView(R.layout.activity_main);
81 |
82 | SlidingButton mSlidingButton = findViewById(R.id.slidingButton);
83 | mSlidingButton.setOnStateChangeListener(new SlidingButton.OnStateChangeListener(){
84 |
85 | @Override
86 | public void onChange(boolean active){
87 | //do what you wanna to do
88 | }
89 | })
90 | }
91 | }
92 | ```
93 |
94 |
95 | - Kotlin
96 |
97 | ```kotlin
98 | class MainActivity : AppCompatActivity() {
99 |
100 | override fun onCreate(savedInstanceState : Bundle?){
101 | super.onCreate(savedInstanceState)
102 | setContentView(R.layout.activity_main)
103 |
104 | //access view using synthetic, do your own style to access the view :)
105 | slidingButton.setOnStateChangeListener { active ->
106 | //or using `object : SlidingButton.OnStateChangeListener` instead of lambda
107 |
108 | //do what you wanna to do
109 | }
110 | }
111 | }
112 | ```
113 |
114 | It's pretty simple right? :smile:
115 |
116 |
117 |
118 | If you wanna customizing, please attention to the following attributes:
119 |
120 | - `app:sliding_text`
121 |
122 | Use to set text to the view, value of this attribute is *string* that can be **hardcode**, **reference**,or **null**
123 |
124 | - `app:sliding_text_color`
125 |
126 | Use to set text color, value of this attribute can be **hardcode** or **reference**. Absolutely you can reference it to *ColorStateList* :smile:
127 |
128 | - `app:sliding_text_size`
129 |
130 | Use to set text size, value of this attribute is *dimension* that can be **hardcode** or **reference**
131 |
132 | - `app:sliding_text_fontFamily`
133 |
134 | Use to set font family by name, value of this attribute is *string* that can be **hardcode**, or **reference**
135 |
136 | - `app:sliding_text_textStyle`
137 |
138 | Use to set text style, value of this attribute `normal`, `italic`,`bold`, or `bold|italic`
139 |
140 | - `app:sliding_text_background`
141 |
142 | Use to set text background, value of this attribute can be **color**, **drawable**, or **null**. Absolutely you can reference it to *ColorStateList* or *StateListDrawable* :smile:
143 |
144 | - `app:sliding_text_paddingStart`, `app:sliding_text_paddingTop`, `app:sliding_text_paddingEnd`, `app:sliding_text_paddingBottom`
145 |
146 | Use to set text padding, value is *dimension* that can be **hardcode** or **reference**
147 |
148 | - `app:sliding_button_width`, `app:sliding_button_height`
149 |
150 | - `app:sliding_button_icon`
151 |
152 | - `app:sliding_button_icon_tint`
153 |
154 | - `app:sliding_icon_scaleType`
155 |
156 | - `app:sliding_button_background`
157 |
158 | - `app:sliding_button_paddingStart`, `app:sliding_button_paddingTop`, `app:sliding_button_paddingEnd`, `app:sliding_button_paddingBottom`
159 |
160 | - `app:sliding_button_marginStart`, `app:sliding_button_marginTop`, `app:sliding_button_marginEnd`, `app:sliding_button_marginBottom`
161 |
162 | - `app:sliding_enabledTextAlpha`
163 |
164 | Use to alpha text when sliding, value of this attribute **Boolean**. Default value true
165 |
166 | - `app:sliding_showTrack`
167 |
168 | Use to show track indicator when sliding, value of this attribute **Boolean**. Default value false
169 |
170 | - `app:sliding_trackBackground`
171 |
172 | Use to set track indicator background.
173 |
174 | - `app:sliding_trackBackgroundTint`
175 |
176 | Use to set tint track indicator background.
177 |
178 | - `app:sliding_trackExtendTo`
179 |
180 | Use to set track extended to `container` or `button`
181 |
182 | - `app:sliding_corner_radius` only on API level 21 (Lollipop)
183 |
184 |
185 |
186 | --------
187 |
188 | # License
189 | MIT License
190 |
191 | Copyright (c) 2020 Source Set 564 Contributors
192 |
193 | Permission is hereby granted, free of charge, to any person obtaining a copy
194 | of this software and associated documentation files (the "Software"), to deal
195 | in the Software without restriction, including without limitation the rights
196 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
197 | copies of the Software, and to permit persons to whom the Software is
198 | furnished to do so, subject to the following conditions:
199 |
200 | The above copyright notice and this permission notice shall be included in all
201 | copies or substantial portions of the Software.
202 |
203 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
204 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
205 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
206 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
207 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
208 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
209 | SOFTWARE.
210 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 |
5 | android {
6 | compileSdkVersion 29
7 | buildToolsVersion "29.0.3"
8 |
9 | defaultConfig {
10 | applicationId "id.ss564.sample.swipebuttonexample"
11 | minSdkVersion 17
12 | targetSdkVersion 29
13 | versionCode 1
14 | versionName "1.0"
15 |
16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
17 | }
18 |
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 |
26 | }
27 |
28 | dependencies {
29 | implementation fileTree(dir: 'libs', include: ['*.jar'])
30 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
31 | implementation 'androidx.appcompat:appcompat:1.1.0'
32 | implementation 'androidx.core:core-ktx:1.2.0'
33 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
34 | implementation project(':slidingbutton')
35 |
36 | testImplementation 'junit:junit:4.13'
37 | androidTestImplementation 'androidx.test.ext:junit:1.1.1'
38 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
39 | }
40 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/id/ss564/sample/swipebuttonexample/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package id.ss564.sample.swipebuttonexample
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("id.ss564.sample.swipebuttonexample", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/id/ss564/sample/swipebuttonexample/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package id.ss564.sample.swipebuttonexample
2 |
3 | import androidx.appcompat.app.AppCompatActivity
4 | import android.os.Bundle
5 | import android.os.Handler
6 | import kotlinx.android.synthetic.main.activity_main.*
7 |
8 | class MainActivity : AppCompatActivity() {
9 |
10 | override fun onCreate(savedInstanceState: Bundle?) {
11 | super.onCreate(savedInstanceState)
12 | setContentView(R.layout.activity_main)
13 | slidingButton.setOnStateChangeListener {
14 | if(it){
15 | Handler().postDelayed({
16 | slidingButton.changeState(false,true)
17 | },3000L)
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
18 |
22 |
26 |
27 |
28 |
29 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_arrow_forward.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check_circle.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_chevron_right.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_favorite.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
13 |
19 |
25 |
31 |
37 |
43 |
49 |
55 |
61 |
67 |
73 |
79 |
85 |
91 |
97 |
103 |
109 |
115 |
121 |
127 |
133 |
139 |
145 |
151 |
157 |
163 |
169 |
175 |
181 |
187 |
193 |
199 |
205 |
206 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_lock_open.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_lock_outline.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/oval_morp_shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/app/src/main/res/drawable/oval_morp_shadow.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sliding_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 | -
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sliding_button_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sliding_button_oval_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sliding_button_oval_background_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 | -
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sliding_button_oval_background_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 | -
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sliding_icon_example_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sliding_icon_example_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sliding_icon_tint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sliding_icon_tint_example_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sliding_rect_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sliding_rect_background_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 | -
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sliding_rect_background_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sliding_shape_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sliding_track_tint_example_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
23 |
24 |
42 |
43 |
68 |
69 |
85 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #6200EE
4 | #3700B3
5 | #2ec7c5
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SlidingButtonExample
3 | Move it
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/id/ss564/sample/swipebuttonexample/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package id.ss564.sample.swipebuttonexample
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.3.71'
5 | repositories {
6 | google()
7 | jcenter()
8 | mavenCentral()
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:3.6.2'
12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
13 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | plugins {
20 | id "com.jfrog.bintray" version "1.8.4"
21 | }
22 |
23 | allprojects {
24 | repositories {
25 | google()
26 | jcenter()
27 | mavenCentral()
28 | }
29 | }
30 |
31 | task clean(type: Delete) {
32 | delete rootProject.buildDir
33 | }
34 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 | # Kotlin code style for this project: "official" or "obsolete":
21 | kotlin.code.style=official
22 |
--------------------------------------------------------------------------------
/previews/preview_sample_a_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/previews/preview_sample_a_1.jpg
--------------------------------------------------------------------------------
/previews/preview_sample_a_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/previews/preview_sample_a_2.jpg
--------------------------------------------------------------------------------
/previews/preview_sample_a_3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/previews/preview_sample_a_3.jpg
--------------------------------------------------------------------------------
/previews/preview_sample_a_4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/previews/preview_sample_a_4.jpg
--------------------------------------------------------------------------------
/previews/preview_sample_b_1.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/previews/preview_sample_b_1.JPG
--------------------------------------------------------------------------------
/previews/preview_sample_b_2.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/previews/preview_sample_b_2.JPG
--------------------------------------------------------------------------------
/previews/preview_sample_b_3.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/previews/preview_sample_b_3.JPG
--------------------------------------------------------------------------------
/previews/preview_sample_b_4.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/previews/preview_sample_b_4.JPG
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name='SlidingButtonExample'
2 | include ':app'
3 | include ':slidingbutton'
4 |
--------------------------------------------------------------------------------
/slidingbutton/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 |
5 | android {
6 | compileSdkVersion 29
7 | buildToolsVersion "29.0.3"
8 |
9 | defaultConfig {
10 | minSdkVersion 17
11 | targetSdkVersion 29
12 | versionCode 5
13 | versionName "2.0.0"
14 |
15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
16 | consumerProguardFiles 'consumer-rules.pro'
17 | }
18 |
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 |
26 | }
27 |
28 | dependencies {
29 | implementation fileTree(dir: 'libs', include: ['*.jar'])
30 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
31 | implementation 'androidx.appcompat:appcompat:1.1.0'
32 |
33 | testImplementation 'junit:junit:4.13'
34 | androidTestImplementation 'androidx.test.ext:junit:1.1.1'
35 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
36 | }
37 |
38 | apply from: 'publish.gradle'
39 |
--------------------------------------------------------------------------------
/slidingbutton/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/slidingbutton/consumer-rules.pro
--------------------------------------------------------------------------------
/slidingbutton/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/slidingbutton/src/androidTest/java/id/ss564/lib/slidingbutton/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package id.ss564.lib.slidingbutton
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("id.ss564.lib.slidingbutton.test", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/slidingbutton/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/slidingbutton/src/main/java/id/ss564/lib/slidingbutton/SlidingButton.kt:
--------------------------------------------------------------------------------
1 | package id.ss564.lib.slidingbutton
2 |
3 | import android.animation.Animator
4 | import android.animation.ValueAnimator
5 | import android.content.Context
6 | import android.content.res.ColorStateList
7 | import android.graphics.*
8 | import android.graphics.drawable.ColorDrawable
9 | import android.graphics.drawable.Drawable
10 | import android.os.Build
11 | import android.util.AttributeSet
12 | import android.util.TypedValue
13 | import android.view.*
14 | import android.view.animation.*
15 | import android.widget.FrameLayout
16 | import android.widget.ImageView
17 | import android.widget.TextView
18 | import androidx.annotation.*
19 | import androidx.core.content.ContextCompat
20 | import kotlin.math.max
21 |
22 | /**
23 | * Created by Anwar on 29 Mar 2020.
24 | */
25 |
26 | class SlidingButton : FrameLayout {
27 |
28 | private val inflatedView: View
29 | private lateinit var slidingImage: ImageView
30 | private lateinit var slidingText: TextView
31 | private lateinit var slidingIndicator: View
32 |
33 | private var mStateListener: OnStateChangeListener? = null
34 | private var slidingListener: OnSlidingListener? = null
35 |
36 | private var statusActive = false
37 | set(value) {
38 | field = value
39 | if (value && showIndicator) animatedIndicator()
40 | mStateListener?.onChange(value)
41 | }
42 |
43 | private var startOfButton = 0F
44 | private var endOfButton = 0F
45 |
46 | private var showIndicator = true
47 | private var enableTextAlpha = true
48 |
49 | private val stateListIconTint: ColorStateList
50 |
51 | var buttonBackground: Drawable? = null
52 | set(value) {
53 | field = value
54 | if (::slidingImage.isInitialized)
55 | slidingImage.background = value
56 | }
57 |
58 | var buttonIcon: Drawable? = null
59 | set(value) {
60 | field = value
61 | if (::slidingImage.isInitialized)
62 | slidingImage.setImageDrawable(value)
63 | }
64 |
65 | var iconScaleType: ImageView.ScaleType = ImageView.ScaleType.CENTER_INSIDE
66 | set(value) {
67 | when (value) {
68 | ImageView.ScaleType.CENTER_INSIDE,
69 | ImageView.ScaleType.CENTER_CROP,
70 | ImageView.ScaleType.CENTER,
71 | ImageView.ScaleType.FIT_CENTER,
72 | ImageView.ScaleType.FIT_XY -> {
73 | field = value
74 | if (::slidingImage.isInitialized) slidingImage.scaleType = value
75 | }
76 | else -> throw IllegalArgumentException("ScaleType $value aren't allowed, please use CENTER, CENTER_CROP, CENTER_INSIDE,FIT_CENTER, or FIT_XY")
77 | }
78 | }
79 |
80 | var textBackground: Drawable? = null
81 | set(value) {
82 | field = value
83 | if (::slidingText.isInitialized) slidingText.background = value
84 | }
85 |
86 | private var mTextSize: Float = 0F
87 | private set(value) {
88 | field = value
89 | if (::slidingText.isInitialized)
90 | slidingText.setTextSize(TypedValue.COMPLEX_UNIT_PX, value)
91 | }
92 |
93 | val textSize: Float
94 | get() = if (::slidingText.isInitialized) {
95 | slidingText.textSize
96 | } else {
97 | mTextSize
98 | }
99 |
100 | /**
101 | * [textPaddings]
102 | * index of the array mean [0] start,[1] top,[2] end,[3] bottom
103 | */
104 | val textPaddings = intArrayOf(0, 0, 0, 0)
105 |
106 | var textColors: ColorStateList? = null
107 | set(value) {
108 | field = value
109 | if (::slidingText.isInitialized)
110 | slidingText.setTextColor(value)
111 | }
112 |
113 | val currentTextColor =
114 | if (::slidingText.isInitialized) slidingText.currentTextColor else textColors?.defaultColor
115 |
116 | var textTypeface: Typeface? = null
117 | set(value) {
118 | field = value
119 | if (::slidingText.isInitialized && value != null) slidingText.typeface = value
120 | }
121 |
122 | private var mText: String? = null
123 | set(value) {
124 | field = value
125 | if (::slidingText.isInitialized)
126 | slidingText.text = value
127 | }
128 |
129 | var buttonWidth: Int = 0
130 | set(value) {
131 | field = value
132 | if (::slidingImage.isInitialized) slidingImage.layoutParams.width = value
133 | }
134 |
135 | var buttonHeight: Int = 0
136 | set(value) {
137 | field = value
138 | if (::slidingImage.isInitialized) slidingImage.layoutParams.height = value
139 | }
140 |
141 | /**
142 | * [buttonMargins],[buttonPaddings]
143 | * index of the array mean [0] start,[1] top,[2] end,[3] bottom
144 | */
145 | val buttonMargins = intArrayOf(0, 0, 0, 0)
146 | val buttonPaddings = intArrayOf(0, 0, 0, 0)
147 |
148 | private var trackExtendedTo = TrackExtended.BUTTON
149 |
150 | var cornerRadius: Float = 0F
151 | @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
152 | set(value) {
153 | field = value
154 | if (::slidingImage.isInitialized) {
155 | RoundedOutlineProvider(value).also {
156 | this.outlineProvider = it
157 | slidingImage.outlineProvider = it
158 | slidingText.outlineProvider = it
159 | slidingIndicator.outlineProvider = it
160 | }
161 | }
162 | }
163 |
164 | var trackBackground: Drawable? = null
165 | set(value) {
166 | field = value
167 | if (::slidingIndicator.isInitialized) {
168 | slidingIndicator.background = value
169 | }
170 | }
171 |
172 | var trackBackgroundTint: ColorStateList? = null
173 | set(value) {
174 | field = value
175 | if (::slidingIndicator.isInitialized) {
176 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
177 | slidingIndicator.background?.setTintList(value)
178 | } else if (value != null) {
179 | slidingIndicator.background?.colorFilter = PorterDuffColorFilter(
180 | value.getColorForState(slidingIndicator.drawableState, value.defaultColor),
181 | PorterDuff.Mode.SRC_IN
182 | )
183 | }
184 | }
185 | }
186 |
187 | constructor(context: Context) : this(context, null)
188 |
189 | constructor(context: Context, attrs: AttributeSet?) : this(
190 | context,
191 | attrs,
192 | R.attr.slidingButtonStyle
193 | )
194 |
195 | constructor(
196 | _context: Context,
197 | attrs: AttributeSet?,
198 | defStyleInt: Int = R.attr.slidingButtonStyle
199 | ) : super(
200 | _context,
201 | attrs,
202 | defStyleInt
203 | ) {
204 |
205 | val colorPrimary = TypedValue()
206 | context.theme.resolveAttribute(R.attr.colorPrimary, colorPrimary, true)
207 |
208 | val ex by lazy {
209 | TypedValue().apply {
210 | context.theme.resolveAttribute(
211 | R.attr.colorAccent,
212 | this,
213 | true
214 | )
215 | }.data
216 | }
217 | val colorAccent = TypedValue()
218 | context.theme.resolveAttribute(R.attr.colorAccent, colorAccent, true)
219 | val arr = context.obtainStyledAttributes(
220 | attrs,
221 | R.styleable.SlidingButton,
222 | defStyleInt,
223 | R.style.SlidingButton
224 | )
225 |
226 | /**
227 | * TextView attrs configuration
228 | */
229 | val defaultTextSize = context.resources.getDimension(R.dimen.default_text_size)
230 | mTextSize = arr.getDimension(R.styleable.SlidingButton_sliding_text_size, defaultTextSize)
231 |
232 | textColors = arr.getColorStateList(R.styleable.SlidingButton_sliding_text_color)
233 | ?: ColorStateList.valueOf(ex)
234 |
235 | mText = arr.getString(R.styleable.SlidingButton_sliding_text)
236 | textBackground = arr.getDrawable(R.styleable.SlidingButton_sliding_text_background)
237 |
238 | val textStyle = arr.getInteger(R.styleable.SlidingButton_sliding_text_textStyle, 0).let {
239 | if (it < 0) 0 else it
240 | }
241 | val fontFamilyName = arr.getString(R.styleable.SlidingButton_sliding_text_fontFamily)
242 | ?: "sans-serif"
243 | textTypeface = Typeface.create(fontFamilyName, textStyle)
244 | textPaddings[0] = arr.getDimensionPixelSize(
245 | R.styleable.SlidingButton_sliding_text_paddingStart,
246 | 0
247 | )
248 | textPaddings[1] = arr.getDimensionPixelSize(
249 | R.styleable.SlidingButton_sliding_text_paddingTop,
250 | 0
251 | )
252 | textPaddings[2] = arr.getDimensionPixelSize(
253 | R.styleable.SlidingButton_sliding_text_paddingEnd,
254 | 0
255 | )
256 | textPaddings[3] = arr.getDimensionPixelSize(
257 | R.styleable.SlidingButton_sliding_text_paddingBottom,
258 | 0
259 | )
260 |
261 | /**
262 | * ImageView attrs configuration
263 | */
264 | val defaultButtonDrawable =
265 | ContextCompat.getDrawable(context, R.drawable.ic_default_slide_icon)
266 | buttonIcon = arr.getDrawable(R.styleable.SlidingButton_sliding_button_icon)
267 | ?: defaultButtonDrawable
268 |
269 | stateListIconTint = arr.getColorStateList(
270 | R.styleable.SlidingButton_sliding_button_icon_tint
271 | ) ?: ColorStateList.valueOf(colorAccent.data)
272 |
273 | buttonBackground = arr.getDrawable(R.styleable.SlidingButton_sliding_button_background)
274 |
275 | val defaultButtonSize = resources.getDimensionPixelSize(R.dimen.default_image_height)
276 | buttonWidth = arr.getDimensionPixelSize(
277 | R.styleable.SlidingButton_sliding_button_width,
278 | defaultButtonSize
279 | )
280 | buttonHeight = arr.getDimensionPixelSize(
281 | R.styleable.SlidingButton_sliding_button_height,
282 | defaultButtonSize
283 | )
284 |
285 | val scaleName = arr.getInteger(R.styleable.SlidingButton_sliding_icon_scaleType, 7).let {
286 | when (it) {
287 | 1 -> "FIT_XY"
288 | 3 -> "FIT_CENTER"
289 | 5 -> "CENTER"
290 | 6 -> "CENTER_CROP"
291 | else -> "CENTER_INSIDE"
292 | }
293 | }
294 | iconScaleType = ImageView.ScaleType.valueOf(scaleName)
295 |
296 | buttonMargins[0] = arr.getDimensionPixelSize(
297 | R.styleable.SlidingButton_sliding_button_marginStart,
298 | 0
299 | )
300 | buttonMargins[1] = arr.getDimensionPixelSize(
301 | R.styleable.SlidingButton_sliding_button_marginTop,
302 | 0
303 | )
304 | buttonMargins[2] = arr.getDimensionPixelSize(
305 | R.styleable.SlidingButton_sliding_button_marginEnd,
306 | 0
307 | )
308 | buttonMargins[3] = arr.getDimensionPixelSize(
309 | R.styleable.SlidingButton_sliding_button_marginBottom,
310 | 0
311 | )
312 |
313 | buttonPaddings[0] = arr.getDimensionPixelSize(
314 | R.styleable.SlidingButton_sliding_button_paddingStart,
315 | 0
316 | )
317 | buttonPaddings[1] = arr.getDimensionPixelSize(
318 | R.styleable.SlidingButton_sliding_button_paddingTop,
319 | 0
320 | )
321 | buttonPaddings[2] = arr.getDimensionPixelSize(
322 | R.styleable.SlidingButton_sliding_button_paddingEnd,
323 | 0
324 | )
325 | buttonPaddings[3] = arr.getDimensionPixelSize(
326 | R.styleable.SlidingButton_sliding_button_paddingBottom,
327 | 0
328 | )
329 |
330 | enableTextAlpha = arr.getBoolean(R.styleable.SlidingButton_sliding_enabledTextAlpha, true)
331 | showIndicator = arr.getBoolean(R.styleable.SlidingButton_sliding_showTrack, false)
332 |
333 | trackBackground = arr.getDrawable(R.styleable.SlidingButton_sliding_trackBackground)
334 | ?: ContextCompat.getDrawable(context, R.drawable.default_sliding_indicator_background)
335 |
336 | trackBackgroundTint = arr.getColorStateList(
337 | R.styleable.SlidingButton_sliding_trackBackgroundTint
338 | )
339 |
340 | val index = arr.getInteger(R.styleable.SlidingButton_sliding_trackExtendTo, 1)
341 | trackExtendedTo = arrayOf(TrackExtended.CONTAINER, TrackExtended.BUTTON)[index]
342 |
343 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
344 | cornerRadius = arr.getDimension(R.styleable.SlidingButton_sliding_corner_radius, 0F)
345 | buttonIcon?.setTintList(stateListIconTint)
346 | trackBackground?.setTintList(trackBackgroundTint)
347 | } else {
348 | buttonIcon?.colorFilter = PorterDuffColorFilter(
349 | stateListIconTint.defaultColor,
350 | PorterDuff.Mode.SRC_IN
351 | )
352 | if (trackBackgroundTint != null && trackBackground != null) {
353 | trackBackground?.colorFilter = PorterDuffColorFilter(
354 | trackBackgroundTint!!.getColorForState(
355 | trackBackground!!.state,
356 | trackBackgroundTint!!.defaultColor
357 | ),
358 | PorterDuff.Mode.SRC_IN
359 | )
360 | }
361 | }
362 |
363 | arr.recycle()
364 |
365 | inflatedView = LayoutInflater.from(context).inflate(R.layout.layout_button, this, true)
366 | }
367 |
368 | override fun onFinishInflate() {
369 | super.onFinishInflate()
370 | slidingText = inflatedView.findViewById(R.id.slidingText)
371 | slidingIndicator = inflatedView.findViewById(R.id.slidingIndicator)
372 | slidingImage = inflatedView.findViewById(R.id.slidingImage)
373 |
374 | configureTextView()
375 | configureTrackView()
376 | configureImageView()
377 |
378 | //Apply Rounded corner to views
379 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
380 | RoundedOutlineProvider(cornerRadius).also {
381 | this.outlineProvider = it
382 | slidingText.outlineProvider = it
383 | slidingImage.outlineProvider = it
384 | slidingIndicator.outlineProvider = it
385 | }
386 | }
387 |
388 | configureTouch()
389 | }
390 |
391 | private fun configureTrackView() {
392 | if (showIndicator) {
393 | slidingIndicator.background = trackBackground
394 | slidingIndicator.viewTreeObserver.addOnGlobalLayoutListener(object :
395 | ViewTreeObserver.OnGlobalLayoutListener {
396 | override fun onGlobalLayout() {
397 | slidingIndicator.visibility = View.VISIBLE
398 | val lp = slidingIndicator.layoutParams as LayoutParams
399 | when (trackExtendedTo) {
400 | TrackExtended.BUTTON -> {
401 | lp.width = startOfButton.toInt() + buttonWidth - buttonMargins[2]
402 | lp.height = buttonHeight
403 | lp.marginStart = buttonMargins[0]
404 | lp.marginEnd = buttonMargins[2]
405 | }
406 | TrackExtended.CONTAINER -> {
407 | lp.width = 0
408 | lp.height = this@SlidingButton.measuredHeight
409 | lp.marginStart = 0
410 | lp.marginEnd = 0
411 | }
412 | }
413 | slidingIndicator.layoutParams = lp
414 | inflatedView.viewTreeObserver.removeOnGlobalLayoutListener(this)
415 | }
416 | })
417 | } else {
418 | slidingIndicator.visibility = View.GONE
419 | }
420 | }
421 |
422 | private fun configureImageView() {
423 | slidingImage.background = buttonBackground
424 | slidingImage.layoutParams.let { it as LayoutParams }.also {
425 | it.width = buttonWidth
426 | it.height = buttonHeight
427 | it.marginStart = buttonMargins[0]
428 | it.topMargin = buttonMargins[1]
429 | it.marginEnd = buttonMargins[2]
430 | it.bottomMargin = buttonMargins[3]
431 | slidingImage.layoutParams = it
432 | }
433 | slidingImage.setPaddingRelative(
434 | buttonPaddings[0],
435 | buttonPaddings[1],
436 | buttonPaddings[2],
437 | buttonPaddings[3]
438 | )
439 | slidingImage.scaleType = iconScaleType
440 | slidingImage.setImageDrawable(buttonIcon)
441 | }
442 |
443 | private fun configureTextView() {
444 | slidingText.background = textBackground
445 | slidingText.setPaddingRelative(
446 | textPaddings[0],
447 | textPaddings[1],
448 | textPaddings[2],
449 | textPaddings[3]
450 | )
451 | slidingText.text = mText
452 | slidingText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize)
453 | slidingText.setTextColor(textColors)
454 | slidingText.typeface = textTypeface
455 | }
456 |
457 | override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
458 | super.onSizeChanged(w, h, oldw, oldh)
459 | startOfButton = buttonMargins[0].toFloat()
460 | endOfButton =
461 | w.toFloat() - (buttonWidth.toFloat() + buttonMargins[2].toFloat() + paddingEnd.toFloat() + paddingStart.toFloat())
462 | }
463 |
464 | override fun removeAllViews() = throw IllegalStateException("This method isn't allowed ")
465 |
466 | override fun removeView(view: View?) = throw IllegalStateException("This method isn't allowed ")
467 |
468 | override fun removeViewAt(index: Int) =
469 | throw IllegalStateException("This method isn't allowed ")
470 |
471 | private fun configureTouch() {
472 | this.setOnTouchListener { _, event ->
473 | val startTouch = (paddingStart + buttonMargins[0]).toFloat()
474 | val maxStartTouch = startTouch + buttonWidth
475 | val isStartTouch = event.x in startTouch..maxStartTouch
476 |
477 | val maxEndTouch = (this.width - paddingEnd - buttonMargins[2]).toFloat()
478 | val isEndTouch = event.x in endOfButton..maxEndTouch
479 |
480 | when (event.action) {
481 | MotionEvent.ACTION_DOWN -> (isStartTouch && !statusActive) || (isEndTouch && statusActive)
482 | MotionEvent.ACTION_MOVE -> onMove(event, startTouch, endOfButton + buttonWidth)
483 | MotionEvent.ACTION_UP -> onUp()
484 | else -> true
485 | }
486 | }
487 | }
488 |
489 | override fun performClick(): Boolean = super.performClick()
490 |
491 | private fun onUp(): Boolean = when {
492 | slidingImage.x + buttonWidth < this.width * 0.55F && slidingImage.x > startOfButton -> {
493 | animatedToStart()
494 | true
495 | }
496 | slidingImage.x + buttonWidth >= this.width * 0.55F -> {
497 | animatedToEnd()
498 | true
499 | }
500 | slidingImage.x <= startOfButton -> {
501 | translateAnimation()
502 | true
503 | }
504 | else -> false
505 | }
506 |
507 | fun changeState(active: Boolean, animated: Boolean = false) {
508 | if (animated && active) {
509 | statusActive = true
510 | animatedToEnd()
511 | } else if (animated && !active) {
512 | statusActive = false
513 | animatedToStart()
514 | } else if (active) {
515 | slidingImage.x = endOfButton
516 | statusActive = true
517 | } else {
518 | slidingImage.x = startOfButton
519 | statusActive = false
520 | }
521 | }
522 |
523 | private fun animatedToStart() {
524 | if (isActivated) isActivated = false
525 |
526 | val floatAnimator = ValueAnimator.ofFloat(slidingImage.x, startOfButton)
527 | floatAnimator.addUpdateListener {
528 | updateSlidingXPosition(it.animatedValue as Float)
529 | }
530 | floatAnimator.addListener(object : Animator.AnimatorListener {
531 | override fun onAnimationRepeat(animation: Animator?) {}
532 |
533 | override fun onAnimationEnd(animation: Animator?) {
534 | isActivated = false
535 | if (statusActive) statusActive = false
536 | }
537 |
538 | override fun onAnimationCancel(animation: Animator?) {}
539 |
540 | override fun onAnimationStart(animation: Animator?) {}
541 | })
542 | floatAnimator.duration = 115L
543 | floatAnimator.interpolator = AccelerateDecelerateInterpolator()
544 | floatAnimator.start()
545 | }
546 |
547 | private fun animatedToEnd() {
548 | val floatAnimator = ValueAnimator.ofFloat(slidingImage.x, endOfButton)
549 | floatAnimator.addUpdateListener {
550 | updateSlidingXPosition(it.animatedValue as Float)
551 | }
552 | floatAnimator.addListener(object : Animator.AnimatorListener {
553 | override fun onAnimationRepeat(animation: Animator?) {}
554 |
555 | override fun onAnimationEnd(animation: Animator?) {
556 | isActivated = true
557 | if (!statusActive) statusActive = true
558 | }
559 |
560 | override fun onAnimationCancel(animation: Animator?) {}
561 |
562 | override fun onAnimationStart(animation: Animator?) {}
563 | })
564 | floatAnimator.duration = 115L
565 | floatAnimator.interpolator = AccelerateDecelerateInterpolator()
566 | floatAnimator.start()
567 | }
568 |
569 | private fun animatedIndicator() {
570 | val animation = ScaleAnimation(
571 | 0F,
572 | 1F,
573 | 1F,
574 | 1F,
575 | slidingIndicator.width.toFloat(),
576 | slidingIndicator.height * 0.5F
577 | )
578 | animation.duration = 500L
579 | animation.interpolator = DecelerateInterpolator()
580 | slidingIndicator.startAnimation(animation)
581 | }
582 |
583 | private fun onMove(event: MotionEvent, start: Float, end: Float): Boolean {
584 | if (isActivated) isActivated = false
585 |
586 | if (event.x < startOfButton + buttonWidth) {
587 | updateSlidingXPosition(startOfButton)
588 | return true
589 | }
590 |
591 | if (event.x in start..end) {
592 | updateSlidingXPosition(event.x - buttonWidth)
593 | return true
594 | }
595 |
596 | return false
597 | }
598 |
599 | private fun updateSlidingXPosition(x: Float) {
600 | slidingImage.x = x
601 | val realX = x - startOfButton
602 | val percent = realX / (endOfButton - startOfButton)
603 |
604 | if (enableTextAlpha) {
605 | slidingText.alpha = if (percent < 0.2F) 1F - percent else max(0F, 1F - (percent + 0.3F))
606 | }
607 |
608 | if (showIndicator) {
609 | val lp = slidingIndicator.layoutParams as LayoutParams
610 | lp.width = when {
611 | trackExtendedTo == TrackExtended.CONTAINER && percent == 0F -> 0
612 | trackExtendedTo == TrackExtended.CONTAINER && percent < 1F -> x.toInt() + buttonWidth
613 | trackExtendedTo == TrackExtended.CONTAINER && percent >= 1F -> x.toInt() + buttonWidth + buttonMargins[2]
614 | else -> x.toInt() + buttonWidth - buttonMargins[2]
615 | }
616 | slidingIndicator.layoutParams = lp
617 | }
618 | slidingListener?.onSliding(percent)
619 | }
620 |
621 | private fun translateAnimation() {
622 | slidingImage.clearAnimation()
623 | val animation = TranslateAnimation(0F, endOfButton, 0F, 0F)
624 | animation.interpolator = AccelerateDecelerateInterpolator()
625 | animation.duration = 350L
626 | animation.setAnimationListener(object : Animation.AnimationListener {
627 | override fun onAnimationRepeat(animation: Animation?) {}
628 |
629 | override fun onAnimationEnd(animation: Animation?) {
630 | slidingImage.clearAnimation()
631 | val anim = ScaleAnimation(
632 | 0.35F,
633 | 1F,
634 | 0.35F,
635 | 1F,
636 | slidingImage.width.toFloat() / 2F,
637 | slidingImage.height.toFloat() / 2F
638 | )
639 | anim.interpolator = DecelerateInterpolator()
640 | anim.duration = 225L
641 | anim.setAnimationListener(object : Animation.AnimationListener {
642 | override fun onAnimationRepeat(animation: Animation?) {}
643 |
644 | override fun onAnimationEnd(animation: Animation?) {
645 | slidingImage.clearAnimation()
646 | slidingImage.scaleX = 1F
647 | slidingImage.scaleY = 1F
648 | if (showIndicator) slidingIndicator.alpha = 1F
649 | }
650 |
651 | override fun onAnimationStart(animation: Animation?) {}
652 | })
653 | slidingImage.startAnimation(anim)
654 | }
655 |
656 | override fun onAnimationStart(animation: Animation?) {
657 | if (showIndicator) slidingIndicator.alpha = 0F
658 | }
659 | })
660 | slidingImage.startAnimation(animation)
661 | }
662 |
663 | override fun setEnabled(enabled: Boolean) {
664 | super.setEnabled(enabled)
665 | slidingText.isEnabled = enabled
666 | slidingImage.isEnabled = enabled
667 | slidingIndicator.isEnabled = enabled
668 | changeStateDrawablePreLollipop()
669 | }
670 |
671 | fun setText(text: String) {
672 | mText = text
673 | }
674 |
675 | fun setText(@StringRes resId: Int) {
676 | mText = context.resources.getString(resId)
677 | }
678 |
679 | fun setTextSize(@Dimension size: Float) {
680 | mTextSize = size
681 | }
682 |
683 | fun setTextColor(@ColorInt color: Int) {
684 | textColors = ColorStateList.valueOf(color)
685 | }
686 |
687 | fun setTextBackground(@DrawableRes resId: Int) {
688 | textBackground = ContextCompat.getDrawable(context, resId)
689 | }
690 |
691 | fun setTextBackgroundColor(@ColorInt color: Int) {
692 | when (textBackground) {
693 | is ColorDrawable -> (slidingText.background as ColorDrawable).color = color
694 | else -> textBackground = ColorDrawable(color)
695 | }
696 | }
697 |
698 | fun setTextPadding(start: Int, top: Int, end: Int, bottom: Int) {
699 | textPaddings[0] = start
700 | textPaddings[1] = top
701 | textPaddings[2] = end
702 | textPaddings[3] = bottom
703 | slidingText.setPadding(textPaddings[0], textPaddings[1], textPaddings[2], textPaddings[3])
704 | }
705 |
706 | fun setButtonIcon(@DrawableRes resId: Int) {
707 | buttonIcon = ContextCompat.getDrawable(context, resId)
708 | }
709 |
710 | fun setButtonBackground(@DrawableRes resId: Int) {
711 | buttonBackground = ContextCompat.getDrawable(context, resId)
712 | }
713 |
714 | fun setButtonBackgroundColor(@ColorInt color: Int) {
715 | when (buttonBackground) {
716 | is ColorDrawable -> (slidingImage.background as ColorDrawable).color = color
717 | else -> buttonBackground = ColorDrawable(color)
718 | }
719 | }
720 |
721 | fun setButtonPadding(start: Int, top: Int, end: Int, bottom: Int) {
722 | buttonPaddings[0] = start
723 | buttonPaddings[1] = top
724 | buttonPaddings[2] = end
725 | buttonPaddings[3] = bottom
726 | slidingImage.setPadding(
727 | buttonPaddings[0],
728 | buttonPaddings[1],
729 | buttonPaddings[2],
730 | buttonPaddings[3]
731 | )
732 | }
733 |
734 | fun setButtonMargin(start: Int, top: Int, end: Int, bottom: Int) {
735 | buttonMargins[0] = start
736 | buttonMargins[1] = top
737 | buttonMargins[2] = end
738 | buttonMargins[3] = bottom
739 | slidingImage.layoutParams.let { it as LayoutParams }.setMargins(
740 | buttonMargins[0],
741 | buttonMargins[1],
742 | buttonMargins[2],
743 | buttonMargins[3]
744 | )
745 | }
746 |
747 | fun setOnStateChangeListener(listener: OnStateChangeListener?) {
748 | mStateListener = listener
749 | }
750 |
751 | fun setOnStateChangeListener(l: (active: Boolean) -> Unit) {
752 | this.setOnStateChangeListener(object : OnStateChangeListener {
753 | override fun onChange(active: Boolean) {
754 | l.invoke(active)
755 | }
756 | })
757 | }
758 |
759 | fun setOnSlidingListener(listener: OnSlidingListener?) {
760 | slidingListener = listener
761 | }
762 |
763 | fun setOnSlidingListener(l: (progress: Float) -> Unit) {
764 | this.setOnSlidingListener(object : OnSlidingListener {
765 | override fun onSliding(progress: Float) {
766 | l.invoke(progress)
767 | }
768 | })
769 | }
770 |
771 | override fun setActivated(activated: Boolean) {
772 | super.setActivated(activated)
773 | changeStateDrawablePreLollipop()
774 | }
775 |
776 | private fun changeStateDrawablePreLollipop() {
777 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) return
778 |
779 | slidingImage.drawable.colorFilter = PorterDuffColorFilter(
780 | stateListIconTint.getColorForState(
781 | slidingImage.drawableState,
782 | stateListIconTint.defaultColor
783 | ), PorterDuff.Mode.SRC_IN
784 | )
785 |
786 | trackBackgroundTint?.let {
787 | slidingIndicator.background?.colorFilter = PorterDuffColorFilter(
788 | it.getColorForState(slidingIndicator.drawableState, it.defaultColor),
789 | PorterDuff.Mode.SRC_IN
790 | )
791 | }
792 | }
793 |
794 | interface OnStateChangeListener {
795 | fun onChange(active: Boolean)
796 | }
797 |
798 | interface OnSlidingListener {
799 | fun onSliding(progress: Float)
800 | }
801 |
802 | @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
803 | private class RoundedOutlineProvider(val radius: Float) : ViewOutlineProvider() {
804 | override fun getOutline(view: View, outline: Outline) {
805 | val rect = Rect(0, 0, view.width, view.height)
806 | outline.setRoundRect(rect, radius)
807 | view.clipToOutline = true
808 | }
809 | }
810 |
811 | @Keep
812 | enum class TrackExtended constructor(val value: Int) {
813 | CONTAINER(0),
814 | BUTTON(1)
815 | }
816 | }
--------------------------------------------------------------------------------
/slidingbutton/src/main/res/drawable-v21/default_sliding_indicator_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 | -
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/slidingbutton/src/main/res/drawable-v21/default_slidingbutton_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/slidingbutton/src/main/res/drawable-v21/ic_default_slide_icon_new.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
14 |
15 |
--------------------------------------------------------------------------------
/slidingbutton/src/main/res/drawable/default_sliding_indicator_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 | -
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/slidingbutton/src/main/res/drawable/default_slidingbutton_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/slidingbutton/src/main/res/drawable/default_slidingcontainer_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/slidingbutton/src/main/res/drawable/ic_default_slide_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Source-Set-564/SlidingButton/8d5afe783b96b348623f8906fb7d2cf54417d804/slidingbutton/src/main/res/drawable/ic_default_slide_icon.png
--------------------------------------------------------------------------------
/slidingbutton/src/main/res/layout/layout_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
16 |
25 |
26 |
33 |
--------------------------------------------------------------------------------
/slidingbutton/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 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/slidingbutton/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #E8ECEF
4 |
--------------------------------------------------------------------------------
/slidingbutton/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 46dp
4 | 18sp
5 |
--------------------------------------------------------------------------------
/slidingbutton/src/main/res/values/public.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/slidingbutton/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Slide the button
4 |
--------------------------------------------------------------------------------
/slidingbutton/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
18 |
19 |
22 |
23 |
26 |
27 |
31 |
--------------------------------------------------------------------------------
/slidingbutton/src/test/java/id/ss564/lib/slidingbutton/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package id.ss564.lib.slidingbutton
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------