├── .github ├── dependabot.yml └── workflows │ ├── Build.yml │ └── Lint.yml ├── .gitignore ├── .idea ├── .gitignore ├── compiler.xml ├── discord.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml ├── jarRepositories.xml ├── misc.xml └── vcs.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── dev │ │ └── sagar │ │ └── progressbutton │ │ ├── ComposeActivity.kt │ │ └── MainActivity.kt │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.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 │ ├── dimens.xml │ ├── strings.xml │ └── themes.xml ├── build.gradle ├── gif └── demo.gif ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jitpack.yml ├── progress-button-compose ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── dev │ └── sagar │ └── progress_button_compose │ ├── ButtonState.kt │ ├── DefaultValues.kt │ ├── ProgressButtonColors.kt │ ├── ProgressButtonCompose.kt │ └── ProgressButtonElevation.kt ├── progress-button ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── dev │ │ └── sagar │ │ └── progress_button │ │ ├── ButtonStates.kt │ │ ├── DefaultParams.kt │ │ ├── ProgressButton.kt │ │ └── ViewEx.kt │ └── res │ ├── anim │ ├── fade_in.xml │ ├── scale_down.xml │ └── scale_up.xml │ ├── layout │ └── progress_button_view.xml │ └── values │ ├── attrs.xml │ └── colors.xml └── settings.gradle /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Updates for Github Actions used in the repo 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | # Updates for Gradle dependencies used in the app 9 | - package-ecosystem: gradle 10 | directory: "/" 11 | schedule: 12 | interval: "daily" 13 | reviewers: 14 | - "hellosagar" 15 | -------------------------------------------------------------------------------- /.github/workflows/Build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | build_apk: 6 | name: Generate APK 7 | runs-on: ubuntu-18.04 8 | 9 | steps: 10 | - uses: actions/checkout@v2 11 | - uses: actions/setup-node@v2 12 | - name: Setup Node.js environment 13 | uses: actions/setup-node@v2.1.5 14 | with: 15 | node-version: '12' 16 | - name: Set up JDK 12 17 | uses: actions/setup-java@v1 18 | with: 19 | java-version: 12 20 | 21 | # Cache gradle 22 | - name: Cache Gradle and wrapper 23 | uses: actions/cache@v2 24 | with: 25 | path: | 26 | ~/.gradle/caches 27 | ~/.gradle/wrapper 28 | key: cache-${{ runner.os }}-${{ matrix.jdk }}-gradle-${{ hashFiles('**/*.gradle*') }} 29 | restore-keys: | 30 | ${{ runner.os }}-gradle- 31 | - name: Grant Permission to Execute 32 | run: chmod +x gradlew 33 | 34 | - name: Build debug APK 35 | run: bash ./gradlew assembleDebug --stacktrace 36 | - name: Upload APK 37 | uses: actions/upload-artifact@v2.2.4 38 | with: 39 | name: app 40 | path: app/build/outputs/apk/debug/app-debug.apk 41 | -------------------------------------------------------------------------------- /.github/workflows/Lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | lint: 7 | name: Lint Check 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - name: Checkout Code 12 | uses: actions/checkout@v2 13 | 14 | - name: Lint Code Base 15 | uses: docker://github/super-linter:v2.2.0 16 | env: 17 | VALIDATE_ALL_CODEBASE: true 18 | VALIDATE_MD: false 19 | VALIDATE_XML: true 20 | VALIDATE_KOTLIN: true 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/discord.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 18 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Sagar Khurana 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 |

Progress Button █▒▒▒▒▒▒▒

2 | 3 |

4 | 5 | ProgressButton licence 6 | 7 | 8 | progress-button-version 9 | 10 | 11 | ProgressButton forks 12 | 13 | 14 | ProgressButton stars 15 | 16 | 17 | ProgressButton issues 18 | 19 | 20 | ProgressButton pull-requests 21 | 22 |

23 | 24 |

25 | Report Bug 26 | · 27 | Request Feature 28 |

29 | 30 | ### Need easy way to refelect all the button states? 31 | Progress Button is an android library for handling different types states like active, finished, enabled, disabled, and reset with a single line of code. 32 | 33 | ## 🚀 Demo 34 | 35 |

36 | 37 |

38 | 39 | ## 🧐 Features 40 | 41 | - One line of code to change state 42 | - Easy configurable 43 | - Customizable 44 | - Set vibration on click 45 | - Disable views in active state 46 | 47 | ## 🛠️ Installation Steps 48 | 49 | ```gradle 50 | repositories { 51 | maven { url 'https://jitpack.io' } 52 | } 53 | 54 | dependencies { 55 | implementation 'com.github.hellosagar:ProgressButton:latest_version' 56 | } 57 | ``` 58 | 59 | ## 💻 Usage 60 | 61 | In XMl you need to define the button with your parameters to achieve the desired the design 62 | 63 | #### Notes - 64 | * To use vibration on click please add the following permission in android manifest 65 | ```xml 66 | 67 | ``` 68 | 69 | Here is the sample code 70 | 71 | ```xml 72 | 86 | ``` 87 | 88 | ## Color Parameters 89 | 90 | | Explanation | Parameter Name | Type | Default Value | 91 | | ---------------------------- | ----------------------- | ---------- | -------------- | 92 | | Set Default Color | **default_color** | color | #0052FE | 93 | | Set Disabled Color | **disabled_color** | color | #537CD3 | 94 | | Set Pressed Color | **pressed_color** | color | #0845D1 | 95 | | Set Finished Color | **finished_color** | color | #27AE60 | 96 | | Set Ripple Color | **ripple_color** | color | @android:color/transparent | 97 | | Set Text Color | **btn_text_color** | color | #FFFFFF | 98 | | Set Stroke Color | **stroke_color** | color | @android:color/transparent | 99 | 100 | ## Text Parameters 101 | 102 | | Explanation | Parameter Name | Type | Default Value | 103 | | ---------------------------- | ------------------ | ---------- | ---------------- | 104 | | Set Default Text | **default_color** | text | Button | 105 | | Set Finished Text | **finish_text** | text | Finish | 106 | | Set Text Size | **btn_text_size** | dimension | 14sp | 107 | 108 | 109 | ## Vibration Parameters 110 | 111 | | Explanation | Parameter Name | Type | Default Value | 112 | | ---------------------------- | ------------------ | ---------- | ---------------- | 113 | | Is Vibration enabled | **is_vibrate** | boolean | false | 114 | | Set Vibration time in (ms) | **finish_text** | integer | 30 | 115 | 116 | 117 | ## Misc Button Parameters 118 | 119 | | Explanation | Parameter Name | Type | Default Value | 120 | | ---------------------------- | ------------------ | ---------- | ---------------- | 121 | | Set Stroke Width | **stroke_width** | dimension | 0dp | 122 | | Set Corner Radius | **corner_radius** | dimension | 10dp | 123 | | Set Button Elevation | **btn_elevation** | dimension | 0dp | 124 | 125 | 126 | Here is the code sample to understand on how to change the button state 127 | 128 | ```kotlin 129 | class MainActivity : AppCompatActivity() { 130 | private lateinit var binding: ActivityMainBinding 131 | 132 | override fun onCreate(savedInstanceState: Bundle?) { 133 | super.onCreate(savedInstanceState) 134 | binding = ActivityMainBinding.inflate(layoutInflater) 135 | setContentView(binding.root) 136 | 137 | initViews() 138 | initClickListeners() 139 | } 140 | 141 | private fun initViews() = binding.apply { 142 | // Passing list of view that we want them to be disabled during the active state 143 | progressButton.setDisableViews(listOf( 144 | editTextTextPersonName, 145 | editTextTextPersonName2, 146 | )) 147 | 148 | } 149 | 150 | private fun initClickListeners() = binding.apply { 151 | 152 | progressButton.setOnClickListener { 153 | Toast.makeText(this@MainActivity, "On click!", Toast.LENGTH_SHORT).show() 154 | } 155 | 156 | btnLoading.setOnClickListener { 157 | // Loading state 158 | progressButton.loading() 159 | } 160 | 161 | btnFinish.setOnClickListener { 162 | // Finish state 163 | progressButton.finished() 164 | } 165 | 166 | btnEnable.setOnClickListener { 167 | // Enable state 168 | progressButton.enable() 169 | } 170 | 171 | btnDisable.setOnClickListener { 172 | // Enable state 173 | progressButton.disable() 174 | } 175 | 176 | btnReset.setOnClickListener { 177 | // Reset state 178 | progressButton.reset() 179 | } 180 | 181 | } 182 | 183 | } 184 | ``` 185 | 186 | You can also directly integrate livedata to your button. This will automatically change the state of 187 | button according to the livedata. 188 | 189 | ```kotlin 190 | 191 | //This is an enum that contains all button states, use this for livedata 192 | enum class ButtonStates { 193 | LOADING, ENABLED, DISABLED, FINISHED 194 | } 195 | 196 | //liveData variable 197 | val buttonState = MutableLiveData() 198 | 199 | //In Fragment or Activity 200 | binding.progressButton.attachToLiveData(buttonState) 201 | 202 | ``` 203 | 204 | Just post the button state to the livedata like 205 | `livedata.postValue(ButtonStates.LOADING)` and button will change to loading state automatically 206 | 207 | ## Jetpack Compose 208 | 209 | If you are using Jetpack Compose, all you have to do it to call the ProgressButton composable 210 | 211 | ### Composable function 212 | 213 | ```kotlin 214 | @Composable 215 | fun ProgressButton( 216 | buttonState: ButtonState, 217 | text: String, 218 | completedText: String, 219 | modifier: Modifier = Modifier, 220 | shape: Shape = RoundedCornerShape(4.dp), 221 | progressBarStrokeWidth: Dp = 3.dp, 222 | progressButtonColors: ProgressButtonColors = ProgressButtonColors(), 223 | progressButtonElevation: ProgressButtonElevation = ProgressButtonElevation(), 224 | textStyle: TextStyle = defaultTextStyle, 225 | onClick: () -> Unit 226 | ) 227 | ``` 228 | 229 | ### Parameters 230 | 231 | | Explanation | Paramter name | Type | Default value | 232 | |------|------|------|------| 233 | | Current state of button | buttonState | ButtonState | none | 234 | | Text shown in button | text | String | none | 235 | | Text shown in completed State | text | String | none | 236 | | Modifier for button | modifier | Modifier | Modifier | 237 | | Shape of button | shape | Shape | RoundedCornerShape with 4dp radius | 238 | | Stroke width of the progress bar inside button | progressBarStrokeWidth | Dp | 3.dp | 239 | | Colors used in button | progressButtonColors | ProgressButtonColors | ProgressButtonColors() | 240 | | Elevation used in button states | progressButtonElevation | ProgressButtonElevation | ProgressButtonElevation() | 241 | | Text Style of text inside button | textStyle | TextStyle | TextStyle(color = Color.White, fontSize = 16.sp, fontWeight = FontWeight.Bold) | 242 | | Lambda function to be called on button press | onClick | () -> Unit | none | 243 | 244 | ### Helper Classes 245 | 246 | ```kotlin 247 | //This class holds data of the colors used in button 248 | data class ProgressButtonColors( 249 | val backgroundColor: Color = DEFAULT_COLOR, //#0052FE 250 | val disabledColor: Color = DISABLED_COLOR, //#537CD3 251 | val finishedColor: Color = FINISHED_COLOR, //#27AE60 252 | val contentColor: Color = CONTENT_COLOR //#FFFFFF 253 | ) 254 | 255 | //This class holds data for the elevation used in button 256 | data class ProgressButtonElevation( 257 | val defaultElevation: Dp = DEFAULT_ELEVATION, //8dp 258 | val elevationOnPress: Dp = DEFAULT_ELEVATION_ON_PRESS //12dp 259 | ) 260 | ``` 261 | 262 | ### Sample code 263 | 264 | ```kotlin 265 | fun MainScreenContent() { 266 | //mutable State to holf button state 267 | var buttonState by remember { 268 | mutableStateOf(ButtonState.DISABLED) 269 | } 270 | ProgressButton( 271 | buttonState = buttonState, 272 | text = "Button", 273 | completedText = "Finished", 274 | shape = RoundedCornerShape(12.dp), 275 | modifier = Modifier.fillMaxWidth() 276 | ) { 277 | } 278 | 279 | } 280 | ``` 281 | 282 | 🌟 You are all set! 283 | 284 | ## 🍰 Contribute 285 | 286 | Feel free to fork this project, to optimise the code or to add new features. 287 | 288 | ## 📝 TODO 289 | 290 | * Lottie support 291 | 292 | ## 🛡️ License 293 | 294 | This project is licensed under the MIT License - see the [`LICENSE`](LICENSE) file for details. 295 | 296 | ## 🙌 Support 297 | 298 | This project needs a 🌟 from you 299 | 300 |

301 | Developed with ❤️ in India 🇮🇳 302 |

303 | 304 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | } 5 | 6 | android { 7 | compileSdkVersion 30 8 | buildToolsVersion "30.0.3" 9 | 10 | defaultConfig { 11 | applicationId "dev.sagar.progressbutton" 12 | minSdkVersion 26 13 | targetSdkVersion 30 14 | versionCode 1 15 | versionName "1.0" 16 | 17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 18 | 19 | vectorDrawables { 20 | useSupportLibrary true 21 | } 22 | } 23 | 24 | buildTypes { 25 | release { 26 | minifyEnabled false 27 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 28 | } 29 | } 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | kotlinOptions { 35 | jvmTarget = '1.8' 36 | useIR = true 37 | } 38 | buildFeatures { 39 | viewBinding true 40 | compose true 41 | } 42 | composeOptions { 43 | kotlinCompilerExtensionVersion compose_version 44 | } 45 | 46 | } 47 | 48 | dependencies { 49 | 50 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 51 | implementation 'androidx.core:core-ktx:1.5.0' 52 | implementation 'androidx.appcompat:appcompat:1.3.0' 53 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4' 54 | implementation project(path: ':progress-button') 55 | implementation project(path: ':progress-button-compose') 56 | testImplementation 'junit:junit:4.+' 57 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 58 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 59 | 60 | // Material Design 61 | implementation 'com.google.android.material:material:1.4.0' 62 | 63 | // Lifecycle 64 | implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" 65 | implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1" 66 | implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.3.1" 67 | 68 | 69 | 70 | implementation "androidx.compose.ui:ui:$compose_version" 71 | implementation "androidx.compose.material:material:$compose_version" 72 | implementation "androidx.compose.ui:ui-tooling:$compose_version" 73 | implementation 'androidx.activity:activity-compose:1.3.0-beta02' 74 | 75 | } -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/dev/sagar/progressbutton/ComposeActivity.kt: -------------------------------------------------------------------------------- 1 | package dev.sagar.progressbutton 2 | 3 | import android.os.Bundle 4 | import androidx.activity.ComponentActivity 5 | import androidx.activity.compose.setContent 6 | import androidx.compose.foundation.ExperimentalFoundationApi 7 | import androidx.compose.foundation.layout.* // ktlint-disable no-wildcard-imports 8 | import androidx.compose.foundation.shape.RoundedCornerShape 9 | import androidx.compose.material.Button 10 | import androidx.compose.material.Surface 11 | import androidx.compose.material.Text 12 | import androidx.compose.runtime.* // ktlint-disable no-wildcard-imports 13 | import androidx.compose.ui.Alignment 14 | import androidx.compose.ui.Modifier 15 | import androidx.compose.ui.graphics.Color 16 | import androidx.compose.ui.res.stringResource 17 | import androidx.compose.ui.tooling.preview.Preview 18 | import androidx.compose.ui.unit.dp 19 | import dev.sagar.progress_button_compose.ButtonState 20 | import dev.sagar.progress_button_compose.ProgressButton 21 | import dev.sagar.progress_button_compose.ProgressButtonColors 22 | 23 | class ComposeActivity : ComponentActivity() { 24 | @ExperimentalFoundationApi 25 | override fun onCreate(savedInstanceState: Bundle?) { 26 | super.onCreate(savedInstanceState) 27 | setContent { 28 | Surface(color = Color.White) { 29 | MainScreenContent() 30 | } 31 | } 32 | } 33 | } 34 | 35 | @ExperimentalFoundationApi 36 | @Composable 37 | @Preview 38 | fun MainScreenContent() { 39 | 40 | var buttonState by remember { 41 | mutableStateOf(ButtonState.DISABLED) 42 | } 43 | 44 | Column( 45 | modifier = Modifier 46 | .fillMaxSize() 47 | .padding(32.dp), 48 | verticalArrangement = Arrangement.Center, 49 | horizontalAlignment = Alignment.CenterHorizontally 50 | ) { 51 | ProgressButton( 52 | buttonState = buttonState, 53 | text = stringResource(R.string.button), 54 | completedText = stringResource(R.string.finished), 55 | shape = RoundedCornerShape(12.dp), 56 | modifier = Modifier 57 | .fillMaxWidth(), 58 | progressButtonColors = ProgressButtonColors() 59 | ) { } 60 | 61 | Spacer(modifier = Modifier.height(100.dp)) 62 | 63 | ControlButton(text = stringResource(R.string.enable)) { 64 | buttonState = ButtonState.ENABLED 65 | } 66 | Spacer(modifier = Modifier.height(16.dp)) 67 | ControlButton(text = stringResource(R.string.disable)) { 68 | buttonState = ButtonState.DISABLED 69 | } 70 | Spacer(modifier = Modifier.height(16.dp)) 71 | ControlButton(text = stringResource(R.string.loading)) { 72 | buttonState = ButtonState.LOADING 73 | } 74 | Spacer(modifier = Modifier.height(16.dp)) 75 | ControlButton(text = stringResource(R.string.finished)) { 76 | buttonState = ButtonState.FINISHED 77 | } 78 | } 79 | } 80 | 81 | @Composable 82 | fun ControlButton(text: String, onClick: () -> Unit) { 83 | Button(onClick = onClick, contentPadding = PaddingValues(horizontal = 16.dp)) { 84 | Text(text = text, color = Color.White) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/dev/sagar/progressbutton/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package dev.sagar.progressbutton 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import android.widget.Toast 6 | import androidx.appcompat.app.AppCompatActivity 7 | import androidx.lifecycle.LiveData 8 | import androidx.lifecycle.liveData 9 | import dev.sagar.progress_button.ButtonStates 10 | import dev.sagar.progressbutton.databinding.ActivityMainBinding 11 | import kotlinx.coroutines.Dispatchers 12 | import kotlinx.coroutines.delay 13 | 14 | class MainActivity : AppCompatActivity() { 15 | private lateinit var binding: ActivityMainBinding 16 | 17 | private val sampleLiveData: LiveData = liveData(Dispatchers.IO) { 18 | emit(ButtonStates.DISABLED) 19 | delay(DELAY_TIME) 20 | emit(ButtonStates.ENABLED) 21 | delay(DELAY_TIME) 22 | emit(ButtonStates.LOADING) 23 | delay(DELAY_TIME) 24 | emit(ButtonStates.FINISHED) 25 | delay(DELAY_TIME) 26 | emit(ButtonStates.ENABLED) 27 | } 28 | 29 | override fun onCreate(savedInstanceState: Bundle?) { 30 | super.onCreate(savedInstanceState) 31 | binding = ActivityMainBinding.inflate(layoutInflater) 32 | setContentView(binding.root) 33 | 34 | initViews() 35 | initClickListeners() 36 | } 37 | 38 | private fun initViews() = binding.apply { 39 | // Passing list of view that we want them to be disabled during the active state 40 | progressButton.setDisableViews( 41 | listOf( 42 | editTextTextPersonName, 43 | editTextTextPersonName2, 44 | ) 45 | ) 46 | } 47 | 48 | private fun initClickListeners() = binding.apply { 49 | 50 | progressButton.setOnClickListener { 51 | Toast.makeText(this@MainActivity, "On click!", Toast.LENGTH_SHORT).show() 52 | } 53 | 54 | btnLoading.setOnClickListener { 55 | // Loading state 56 | progressButton.loading() 57 | } 58 | 59 | btnFinish.setOnClickListener { 60 | // Finish state 61 | progressButton.finished() 62 | } 63 | 64 | btnEnable.setOnClickListener { 65 | // Enable state 66 | progressButton.enable() 67 | } 68 | 69 | btnDisable.setOnClickListener { 70 | // Enable state 71 | progressButton.disable() 72 | } 73 | 74 | btnReset.setOnClickListener { 75 | // Reset state 76 | progressButton.reset() 77 | } 78 | 79 | switchToCompose.setOnClickListener { 80 | Intent(this@MainActivity, ComposeActivity::class.java).also { 81 | startActivity(it) 82 | } 83 | } 84 | 85 | progressButton.attachToLiveData(sampleLiveData, this@MainActivity) 86 | } 87 | 88 | companion object { 89 | const val DELAY_TIME = 5000L 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 19 | 20 |