circular progress button可以讓button實現進度條,效果和動畫都做的很贊,只是有點小bug。需要注意的是按鈕上的文字不能太大,否則會出現錯位。
項目的地址:https://github.com/dmytrodanylyk/circular-progress-button
下面我們來看看怎么使用它。
一、添加依賴並在xml中放入控件
從項目地址中下載好lib后導入自己的工程,在xml中放入這樣一個button
<com.dd.CircularProgressButton android:id="@+id/circularButton06" android:layout_width="196dp" android:layout_height="64dp" android:layout_marginTop="15dp" android:textColor="@color/cpb_white" android:textSize="18sp" app:cpb_cornerRadius="48dp" app:cpb_selectorComplete="@drawable/complete_state_selector" app:cpb_selectorError="@drawable/error_state_selector" app:cpb_selectorIdle="@drawable/idle_state_selector" app:cpb_textComplete="Complete" app:cpb_textError="Error" app:cpb_textIdle="Upload" />
二、在xml文件中設置各種屬性
用這些屬性需要自定義命名空間。xmlns:app="http://schemas.android.com/apk/res-auto"
textColor:全局字體顏色設置
textSize:全局字體大小設置
cpb_cornerRadius:按鈕的邊緣弧度數
cpb_textIdle:默認的text文字
cpb_textComplete:完成時顯示的text
cpb_textError:出錯時顯示的text
cpb_iconComplete:完成時顯示的圖標,這個和cpb_textComplete不能共用
cpb_iconError:出錯時顯示的圖標,這個和cpb_textError不能共用
cpb_paddingProgress:圓形進度條和按鈕的邊界的差值,設定后按鈕會在走進度時縮小到小進度條,走完后再由小進度條擴大到原始按鈕
cpb_selectorComplete:自定義完成時按鈕背景的顏色,包括獲取焦點、按下、普通各種狀態
cpb_selectorError:自定義出錯時按鈕背景的顏色,包括獲取焦點、按下、普通各種狀態
cpb_selectorIdle:自定義初始時按鈕的背景色,包括獲取焦點、按下、普通各種狀態
對於cpb_selectorComplete、cpb_selectorError、cpb_selectorIdle需要在drawable中寫上selector文件。這樣就可以設置各種背景色了。
complete_state_selector.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:color="#ff794e9b"/> <item android:state_focused="true" android:color="#ff794e9b"/> <item android:state_enabled="false" android:color="@color/cpb_grey"/> <item android:state_enabled="true" android:color="#ffaa66cc"/> </selector>
error_state_selector.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:color="#ffcd0a51"/> <item android:state_focused="true" android:color="#ffcd0a51"/> <item android:state_enabled="false" android:color="@color/cpb_grey"/> <item android:state_enabled="true" android:color="#fe0a5a"/> </selector>
idle_state_selector.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:color="#fff17a0a"/> <item android:state_focused="true" android:color="#fff17a0a"/> <item android:state_enabled="false" android:color="@color/cpb_grey"/> <item android:state_enabled="true" android:color="#fffeaa0c"/> </selector>
三、在java代碼中使用
由於是有進度條的button,我們先來對進度條的設計進行了解。
按鈕按下后會觸發一個圓形的進度條,這個進度條上面的進度我們是可以自行控制的,如果進度為100,那么說明加載完畢,直接會顯示按鈕成功的時的狀態,如果進度是-1,那么就說明加載失敗,按鈕會顯示出錯的狀態,如果進度是0,那么就是按鈕默認的狀態。
按鈕默認的狀態,進度=0
按鈕加載成功的狀態,進度=100.這里面顯示圖片(對勾)還是顯示文字都可以自定義。
加載是吧,按鈕顯示錯誤的狀態,進度=-1,使用×還是用文字或別的圖片由自己定義。
CircularProgressButton是這個按鈕的對象,我們找到這個控件后就可以進行設置了,設置方式也很簡單。
舉例:
1.顯示不精准進度的按鈕
CircularProgressButton circularButton01 = (CircularProgressButton) findViewById(R.id.circularButton01); circularButton01.setIndeterminateProgressMode(true); // 進入不精准進度模式 circularButton01.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { CircularProgressButton btn = (CircularProgressButton) v; int progress = btn.getProgress(); System.out.println("progress = " + progress); if (progress == 0) { // 初始時progress = 0 btn.setProgress(50); // 點擊后開始不精准進度,不精准進度的進度值一直為50 } else if (progress == 100) { // 如果當前進度為100,即完成狀態,那么重新回到未完成的狀態 btn.setProgress(0); } else if (progress == 50) { // 如果當前進度為50,那么點擊后就顯示完成的狀態 btn.setProgress(100); // -1表示出錯,顯示出錯的圖片和背景,100表示完成,顯示完成的圖片和背景 } } });
2.顯示精准進度的按鈕
按鈕點擊后調用simulateSuccessProgress方法,如果在進度加載時點擊了按鈕,那么按鈕重新回到初始狀態。
final CircularProgressButton circularButton03 = (CircularProgressButton) findViewById(R.id.circularButton03); circularButton03.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (circularButton03.getProgress() == 0) { simulateSuccessProgress(circularButton03); // 如果是初始狀態就開始進入進度條動畫 } else { circularButton03.setProgress(0); // 如果不是初始狀態,那么就回到初始狀態 } } });
/** * 設置成功的進度 * @param button */ private void simulateSuccessProgress(final CircularProgressButton button) { // 這里巧妙運用了valueAnimator這個類來計算動畫的值,這個類本身就起計算作用,不處理任何動畫,這里在計算好后自行進行了進度的設定 ValueAnimator widthAnimation = ValueAnimator.ofInt(1, 100); // 設定范圍為1到100 widthAnimation.setDuration(1500); // 設定動畫的持續時間 widthAnimation.setInterpolator(new AccelerateDecelerateInterpolator()); // 設定動畫的插值器 widthAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { // 在動畫進行時進行處理 @Override public void onAnimationUpdate(ValueAnimator animation) { Integer value = (Integer) animation.getAnimatedValue(); button.setProgress(value); // 設置進度為當前動畫的進度 } }); widthAnimation.start(); // 開始動畫的計算工作 }
三、主要代碼
1. xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" tools:context="${relativePackage}.${activityClass}" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:text="CircularProgressButton" /> <!-- textColor:全局字體顏色設置 textSize:全局字體大小設置 cpb_cornerRadius:按鈕的邊緣弧度數 cpb_textIdle:默認的text文字 cpb_textComplete:完成時顯示的text cpb_textError:出錯時顯示的text cpb_iconComplete:完成時顯示的圖標,這個和cpb_textComplete不能共用 cpb_iconError:出錯時顯示的圖標,這個和cpb_textError不能共用 cpb_paddingProgress:圓形進度條和按鈕的邊界的差值,設定后按鈕會在走進度時縮小到小進度條,走完后再由小進度條擴大到原始按鈕 cpb_selectorComplete:自定義完成時按鈕背景的顏色,包括獲取焦點、按下、普通各種狀態 cpb_selectorError:自定義出錯時按鈕背景的顏色,包括獲取焦點、按下、普通各種狀態 cpb_selectorIdle:自定義初始時按鈕的背景色,包括獲取焦點、按下、普通各種狀態\n --> <com.dd.CircularProgressButton android:id="@+id/circularButton06" android:layout_width="196dp" android:layout_height="64dp" android:layout_alignLeft="@+id/circularButton05" android:layout_below="@+id/circularButton05" android:layout_marginTop="15dp" android:textColor="@color/cpb_white" android:textSize="18sp" app:cpb_cornerRadius="48dp" app:cpb_selectorComplete="@drawable/complete_state_selector" app:cpb_selectorError="@drawable/error_state_selector" app:cpb_selectorIdle="@drawable/idle_state_selector" app:cpb_textComplete="Complete" app:cpb_textError="Error" app:cpb_textIdle="Upload" /> <com.dd.CircularProgressButton android:id="@+id/circularButton05" android:layout_width="196dp" android:layout_height="64dp" android:layout_below="@+id/circularButton04" android:layout_centerHorizontal="true" android:layout_marginTop="34dp" android:textColor="@color/cpb_white" android:textSize="18sp" app:cpb_cornerRadius="48dp" app:cpb_selectorComplete="@drawable/complete_state_selector" app:cpb_selectorError="@drawable/error_state_selector" app:cpb_selectorIdle="@drawable/idle_state_selector" app:cpb_textComplete="Complete" app:cpb_textError="Error" app:cpb_textIdle="Upload" /> <com.dd.CircularProgressButton android:id="@+id/circularButton04" android:layout_width="100dp" android:layout_height="40dp" android:layout_below="@+id/circularButton03" android:layout_centerHorizontal="true" android:layout_marginTop="15dp" android:textColor="#00ffff" android:textSize="18sp" app:cpb_cornerRadius="10dp" app:cpb_textComplete="Complete" app:cpb_textError="Error" app:cpb_textIdle="upload" /> <com.dd.CircularProgressButton android:id="@+id/circularButton03" android:layout_width="100dp" android:layout_height="40dp" android:layout_alignLeft="@+id/circularButton04" android:layout_below="@+id/circularButton02" android:layout_marginTop="28dp" android:textColor="#ffff00" android:textSize="18sp" app:cpb_cornerRadius="30dp" app:cpb_iconComplete="@drawable/ic_action_accept" app:cpb_iconError="@drawable/ic_action_cancel" app:cpb_textIdle="upload" /> <com.dd.CircularProgressButton android:id="@+id/circularButton02" android:layout_width="120dp" android:layout_height="50dp" android:layout_alignLeft="@+id/circularButton01" android:layout_below="@+id/circularButton01" android:layout_marginTop="14dp" android:textColor="#00ffff" android:textSize="18sp" app:cpb_cornerRadius="10dp" app:cpb_textComplete="Complete" app:cpb_textError="Error" app:cpb_textIdle="upload" /> <com.dd.CircularProgressButton android:id="@+id/circularButton01" android:layout_width="120dp" android:layout_height="50dp" android:layout_below="@+id/textView1" android:layout_centerHorizontal="true" android:layout_marginTop="20dp" android:textColor="#ffff00" android:textSize="18sp" app:cpb_cornerRadius="30dp" app:cpb_iconComplete="@drawable/ic_action_accept" app:cpb_iconError="@drawable/ic_action_cancel" app:cpb_paddingProgress="15dp" app:cpb_textIdle="upload" /> </RelativeLayout>
2. java
package com.kale.buttontest; import com.dd.CircularProgressButton; import android.animation.ValueAnimator; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.animation.AccelerateDecelerateInterpolator; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); CircularProgressButton circularButton01 = (CircularProgressButton) findViewById(R.id.circularButton01); circularButton01.setIndeterminateProgressMode(true); // 進入不精准進度模式 circularButton01.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { CircularProgressButton btn = (CircularProgressButton) v; int progress = btn.getProgress(); System.out.println("progress = " + progress); if (progress == 0) { // 初始時progress = 0 btn.setProgress(50); // 點擊后開始不精准進度,不精准進度的進度值一直為50 } else if (progress == 100) { // 如果當前進度為100,即完成狀態,那么重新回到未完成的狀態 btn.setProgress(0); } else if (progress == 50) { // 如果當前進度為50,那么點擊后就顯示完成的狀態 btn.setProgress(100); // -1表示出錯,顯示出錯的圖片和背景,100表示完成,顯示完成的圖片和背景 } } }); CircularProgressButton circularButton02 = (CircularProgressButton) findViewById(R.id.circularButton02); circularButton02.setIndeterminateProgressMode(true); circularButton02.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { CircularProgressButton btn = (CircularProgressButton) v; int progress = btn.getProgress(); System.out.println("progress = " + progress); if (progress == 0) { // 初始時progress = 0 btn.setProgress(50); // 點擊后開始不精准旋轉,進度為50 } else if (progress == -1) { // 如果當前進度為-1,即出錯狀態,那么重新回到初始狀態 btn.setProgress(0); } else if (progress == 50) { // 如果當前進度為50,那么點擊后就顯示出錯的狀態 btn.setProgress(-1); // -1表示出錯,顯示出錯的圖片和背景 } } }); final CircularProgressButton circularButton03 = (CircularProgressButton) findViewById(R.id.circularButton03); circularButton03.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (circularButton03.getProgress() == 0) { simulateSuccessProgress(circularButton03); // 如果是初始狀態就開始進入進度條動畫 } else { circularButton03.setProgress(0); // 如果不是初始狀態,那么就回到初始狀態 } } }); final CircularProgressButton circularButton04 = (CircularProgressButton) findViewById(R.id.circularButton04); circularButton04.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (circularButton04.getProgress() == 0) { // 如果是初始狀態就開始進入進度條動畫 simulateErrorProgress(circularButton04); } else { circularButton04.setProgress(0); // 如果不是初始狀態,那么就回到初始狀態 } } }); final CircularProgressButton circularButton05 = (CircularProgressButton) findViewById(R.id.circularButton05); circularButton05.setIndeterminateProgressMode(true); circularButton05.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (circularButton05.getProgress() == 0) { circularButton05.setProgress(50); } else if (circularButton05.getProgress() == 100) { circularButton05.setProgress(0); } else { circularButton05.setProgress(100); } } }); final CircularProgressButton circularButton06 = (CircularProgressButton) findViewById(R.id.circularButton06); circularButton06.setIndeterminateProgressMode(true); circularButton06.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (circularButton06.getProgress() == 0) { circularButton06.setProgress(50); } else if (circularButton06.getProgress() == -1) { circularButton06.setProgress(0); } else { circularButton06.setProgress(-1); } } }); } /** * 設置成功的進度 * @param button */ private void simulateSuccessProgress(final CircularProgressButton button) { // 這里巧妙運用了valueAnimator這個類來計算動畫的值,這個類本身就起計算作用,不處理任何動畫,這里在計算好后自行進行了進度的設定 ValueAnimator widthAnimation = ValueAnimator.ofInt(1, 100); // 設定范圍為1到100 widthAnimation.setDuration(1500); // 設定動畫的持續時間 widthAnimation.setInterpolator(new AccelerateDecelerateInterpolator()); // 設定動畫的插值器 widthAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { // 在動畫進行時進行處理 @Override public void onAnimationUpdate(ValueAnimator animation) { Integer value = (Integer) animation.getAnimatedValue(); button.setProgress(value); // 設置進度為當前動畫的進度 } }); widthAnimation.start(); // 開始動畫的計算工作 } /** * 設置出錯時的進度條 * @param button */ private void simulateErrorProgress(final CircularProgressButton button) { ValueAnimator widthAnimation = ValueAnimator.ofInt(1, 99); widthAnimation.setDuration(1500); widthAnimation.setInterpolator(new AccelerateDecelerateInterpolator()); widthAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Integer value = (Integer) animation.getAnimatedValue(); button.setProgress(value); // 將當前動畫的進度設置為按鈕的進度 if (value == 99) { // 如果按鈕的進度到了99,那么直接設置為出錯狀態 button.setProgress(-1); } } }); widthAnimation.start(); // 開始動畫的計算 } }
源碼下載:http://download.csdn.net/detail/shark0017/8354435