├── .gitignore ├── README-zh.md ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── unstoppable │ │ └── submitbutton │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── unstoppable │ │ │ └── submitbutton │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ └── activity_main.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 │ └── com │ └── unstoppable │ └── submitbutton │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screens ├── submitbutton_failed.gif ├── submitbutton_progress.gif └── submitbutton_succeed.gif ├── settings.gradle └── submitbuttonview ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src ├── androidTest └── java │ └── com │ └── unstoppable │ └── submitbuttonview │ └── ExampleInstrumentedTest.java ├── main ├── AndroidManifest.xml ├── java │ └── com │ │ └── unstoppable │ │ └── submitbuttonview │ │ └── SubmitButton.java └── res │ └── values │ └── attrs.xml └── test └── java └── com └── unstoppable └── submitbuttonview └── ExampleUnitTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /README-zh.md: -------------------------------------------------------------------------------- 1 | ## SubmitButton 2 | 3 | [![Travis](https://img.shields.io/badge/download-1.1.3-brightgreen.svg)](https://bintray.com/unstoppable/maven/submitbutton/1.1.3) 4 | 5 | 6 | README: [English](https://github.com/Someonewow/SubmitButton/blob/master/README.md) | [中文](https://github.com/Someonewow/SubmitButton/blob/master/README-zh.md) 7 | 8 | 9 | 10 | >带有进度动画的Android自定义提交按钮. 11 | 12 | ## 示例 13 | 14 | ![submit succeed](https://raw.githubusercontent.com/Someonewow/SubmitButton/master/screens/submitbutton_succeed.gif) 15 | 16 | ![submit failed](https://raw.githubusercontent.com/Someonewow/SubmitButton/master/screens/submitbutton_failed.gif) 17 | 18 | ![submit progress](https://raw.githubusercontent.com/Someonewow/SubmitButton/master/screens/submitbutton_progress.gif) 19 | 20 | ## 如何使用 21 | 22 | ##### 1.在要使用的Module的build.gradle文件中添加依赖; 23 | 24 | dependencies { 25 | ''' 26 | compile 'com.unstoppable:submitbutton:1.1.3' 27 | } 28 | 29 | ##### 2.布局文件中添加SubmitButton; 30 | 31 | 35 | 36 | ##### 3.自定义属性 37 | 38 | | 属性名 | 类型 | 描述 |默认值 | 39 | |:--------------|:----- |:------------------|:---- | 40 | |buttonColor |color |按钮主题色 | #19CC95 | 41 | |buttonText |String |按钮文本 |null | 42 | |buttonTextSize |dimension |按钮文本大小 |15sp | 43 | |succeedColor |color |submit成功按钮主题色 | #19CC95 | 44 | |failedColor |color |submit失败按钮主题色 | #FC8E34 | 45 | |progressStyle |enum |设置进度样式(可选:loading 或 progress)|loading| 46 | 47 | ##### 4.接口方法 48 | 49 | /** 50 | * 传入submit结果以呈现不同结果反馈效果 51 | * 52 | * @param boolean isSucceed 53 | */ 54 | mSubmitView.doResult(isSucceed); 55 | 56 | /** 57 | * 重置SubmitButton 58 | */ 59 | mSubmitView.reset(); 60 | 61 | /** 62 | * 设置进度(该方法仅在progressStyle设置为progress时有效) 63 | * 64 | * @param progress 进度值 (0-100) 65 | */ 66 | mSubmitView.setProgress(); 67 | 68 | /** 69 | * 设置动画结束回调接口 70 | * 71 | * @param listener 72 | */ 73 | mSubmitView.setOnResultEndListener(OnResultEndListener listener) 74 | 75 | ## 更新日志 76 | 77 | #### 当前版本:1.1.3 78 | 79 | - **完成一些改进** 80 | 81 | #### 版本:1.1.2 82 | 83 | - **修复由于硬件加速导致的在某些机型上无法绘制动画的问题** 84 | 85 | 86 | #### 版本:1.1.1 87 | 88 | - **增加结果动画结束回调接口** 89 | 90 | - **修复问题** 91 | 92 | #### 版本:1.1.0 93 | 94 | - **新增进度样式设置方法** 95 | 96 | #### 版本:1.0.1 97 | 98 | - **修复问题** 99 | 100 | #### 版本:1.0.0 101 | 102 | - **初始构建** 103 | 104 | ## License 105 | 106 | Copyright 2017 Unstoppable 107 | 108 | Licensed under the Apache License, Version 2.0 (the "License"); 109 | you may not use this file except in compliance with the License. 110 | You may obtain a copy of the License at 111 | 112 | http://www.apache.org/licenses/LICENSE-2.0 113 | 114 | Unless required by applicable law or agreed to in writing, software 115 | distributed under the License is distributed on an "AS IS" BASIS, 116 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 117 | See the License for the specific language governing permissions and 118 | limitations under the License. 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## SubmitButton 2 | 3 | [![Travis](https://img.shields.io/badge/download-1.1.3-brightgreen.svg)](https://bintray.com/unstoppable/maven/submitbutton/1.1.3) 4 | 5 | 6 | README: [English](https://github.com/Someonewow/SubmitButton/blob/master/README.md) | [中文](https://github.com/Someonewow/SubmitButton/blob/master/README-zh.md) 7 | 8 | 9 | >It's a submit button with a fun animation for Android. 10 | 11 | ## Demo 12 | 13 | ![submit succeed](https://raw.githubusercontent.com/Someonewow/SubmitButton/master/screens/submitbutton_succeed.gif) 14 | 15 | ![submit failed](https://raw.githubusercontent.com/Someonewow/SubmitButton/master/screens/submitbutton_failed.gif) 16 | 17 | ![submit progress](https://raw.githubusercontent.com/Someonewow/SubmitButton/master/screens/submitbutton_progress.gif) 18 | 19 | ## Getting Started 20 | 21 | ##### 1.Specify SubmitButton as a dependency in your build.gradle file; 22 | 23 | dependencies { 24 | ''' 25 | compile 'com.unstoppable:submitbutton:1.1.3' 26 | } 27 | 28 | ##### 2.Add SubmitButton to the layout file; 29 | 30 | 34 | 35 | ##### 3.Attribute 36 | 37 | | name | format | description |default | 38 | |:--------------|:----- |:------------------------------------------------------|:--------| 39 | |buttonColor |color |set the button theme color |#19CC95 | 40 | |buttonText |String |set the button text |null | 41 | |buttonTextSize |dimension |set the button text size |15sp | 42 | |succeedColor |color |set the button color after the submission is successful|#19CC95 | 43 | |failedColor |color |set the button color after the submission fails |#FC8E34 | 44 | |progressStyle |enum |set the button progress style (Optional:loading or progress) |loading| 45 | 46 | ##### 4.Method 47 | 48 | /** 49 | * Pass the results to show different feedback results 50 | * 51 | * @param boolean isSucceed 52 | */ 53 | mSubmitView.doResult(boolean isSucceed); 54 | 55 | /** 56 | * Reset SubmitButton 57 | */ 58 | mSubmitView.reset(); 59 | 60 | /** 61 | * set progress(This method is valid only if progressStyle is set to progress) 62 | * 63 | * @param progress (0-100) 64 | */ 65 | mSubmitView.setProgress(); 66 | 67 | /** 68 | * set the animation end callback interface 69 | * 70 | * @param listener 71 | */ 72 | mSubmitView.setOnResultEndListener(OnResultEndListener listener) 73 | 74 | ## Changelog 75 | 76 | #### Current Version:1.1.3 77 | 78 | - **Made some improvements.** 79 | 80 | #### Version:1.1.2 81 | 82 | - **Fix bugs that can not be displayed on some phones because of HardwareAccelerated.** 83 | 84 | #### Version:1.1.1 85 | 86 | - **Add animation end callback interface.** 87 | 88 | - **Bug fixes.** 89 | 90 | #### Version:1.1.0 91 | 92 | - **Add progress style setting mothod.** 93 | 94 | #### Version:1.0.1 95 | 96 | - **Bug fixes.** 97 | 98 | #### Version:1.0.0 99 | 100 | - **Initial Build.** 101 | 102 | ## License 103 | 104 | Copyright 2017 Unstoppable 105 | 106 | Licensed under the Apache License, Version 2.0 (the "License"); 107 | you may not use this file except in compliance with the License. 108 | You may obtain a copy of the License at 109 | 110 | http://www.apache.org/licenses/LICENSE-2.0 111 | 112 | Unless required by applicable law or agreed to in writing, software 113 | distributed under the License is distributed on an "AS IS" BASIS, 114 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 115 | See the License for the specific language governing permissions and 116 | limitations under the License. 117 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.2" 6 | defaultConfig { 7 | applicationId "com.unstoppable.submitbutton" 8 | minSdkVersion 15 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | compile project(':submitbuttonview') 28 | compile 'com.android.support:appcompat-v7:25.3.1' 29 | compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha4' 30 | testCompile 'junit:junit:4.12' 31 | } 32 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\androidsdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/unstoppable/submitbutton/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.unstoppable.submitbutton; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.unstoppable.submitbutton", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/unstoppable/submitbutton/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.unstoppable.submitbutton; 2 | 3 | import android.os.AsyncTask; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | import android.view.accessibility.AccessibilityManager; 8 | import android.widget.Button; 9 | import android.widget.CompoundButton; 10 | import android.widget.LinearLayout; 11 | import android.widget.Switch; 12 | import android.widget.Toast; 13 | 14 | import com.unstoppable.submitbuttonview.SubmitButton; 15 | 16 | public class MainActivity extends AppCompatActivity implements View.OnClickListener { 17 | 18 | private SubmitButton sBtnLoading, sBtnProgress; 19 | private Button btnSucceed, btnFailed, btnReset; 20 | private Switch mSwitch; 21 | private MyTask task; 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_main); 27 | 28 | sBtnLoading = (SubmitButton) findViewById(R.id.sbtn_loading); 29 | sBtnProgress = (SubmitButton) findViewById(R.id.sbtn_progress); 30 | mSwitch = (Switch) findViewById(R.id.switch1); 31 | 32 | btnFailed = (Button) findViewById(R.id.btn_failed); 33 | btnSucceed = (Button) findViewById(R.id.btn_succeed); 34 | btnReset = (Button) findViewById(R.id.btn_reset); 35 | 36 | sBtnLoading.setOnClickListener(this); 37 | sBtnProgress.setOnClickListener(this); 38 | btnSucceed.setOnClickListener(this); 39 | btnFailed.setOnClickListener(this); 40 | btnReset.setOnClickListener(this); 41 | 42 | 43 | sBtnLoading.setOnResultEndListener(new SubmitButton.OnResultEndListener() { 44 | @Override 45 | public void onResultEnd() { 46 | Toast.makeText(MainActivity.this, "ResultEnd", Toast.LENGTH_SHORT).show(); 47 | } 48 | }); 49 | 50 | mSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 51 | @Override 52 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 53 | if (isChecked) { 54 | sBtnLoading.setVisibility(View.GONE); 55 | sBtnProgress.setVisibility(View.VISIBLE); 56 | sBtnLoading.reset(); 57 | } else { 58 | sBtnLoading.setVisibility(View.VISIBLE); 59 | sBtnProgress.setVisibility(View.GONE); 60 | if (task != null && !task.isCancelled()) { 61 | task.cancel(true); 62 | sBtnProgress.reset(); 63 | } 64 | } 65 | } 66 | }); 67 | } 68 | 69 | @Override 70 | public void onClick(View v) { 71 | switch (v.getId()) { 72 | case R.id.sbtn_loading: 73 | Toast.makeText(this, "SubmitButton be clicked", Toast.LENGTH_SHORT).show(); 74 | break; 75 | case R.id.sbtn_progress: 76 | if (task == null || task.isCancelled()) { 77 | task = new MyTask(); 78 | task.execute(); 79 | } 80 | break; 81 | case R.id.btn_succeed: 82 | if (mSwitch.isChecked()) { 83 | sBtnProgress.doResult(true); 84 | } else { 85 | sBtnLoading.doResult(true); 86 | } 87 | break; 88 | case R.id.btn_failed: 89 | if (mSwitch.isChecked()) { 90 | sBtnProgress.doResult(false); 91 | } else { 92 | sBtnLoading.doResult(false); 93 | } 94 | break; 95 | case R.id.btn_reset: 96 | if (mSwitch.isChecked()) { 97 | if (task != null && !task.isCancelled()) { 98 | task.cancel(true); 99 | sBtnProgress.reset(); 100 | } 101 | } else { 102 | sBtnLoading.reset(); 103 | } 104 | break; 105 | } 106 | } 107 | 108 | private class MyTask extends AsyncTask { 109 | 110 | @Override 111 | protected Boolean doInBackground(Void... params) { 112 | int i = 0; 113 | while (i <= 100) { 114 | if (isCancelled()) { 115 | return null; 116 | } 117 | try { 118 | Thread.sleep(30); 119 | } catch (InterruptedException e) { 120 | e.printStackTrace(); 121 | } 122 | i++; 123 | publishProgress(i); 124 | } 125 | return true; 126 | } 127 | 128 | @Override 129 | protected void onPostExecute(Boolean aBoolean) { 130 | if (aBoolean == null) { 131 | sBtnProgress.reset(); 132 | } 133 | sBtnProgress.doResult(aBoolean); 134 | } 135 | 136 | @Override 137 | protected void onProgressUpdate(Integer... values) { 138 | sBtnProgress.setProgress(values[0]); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 26 | 27 |