用開源項目circular progress button實現有進度條的Button


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM