• 用开源项目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:自定义初始时按钮的背景色,包括获取焦点、按下、普通各种状态
    
         -->
    
        <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

  • 相关阅读:
    转--Android中自定义字体的实现方法
    android中Intent传值与Bundle传值的区别详解
    通过Application传递数据代码
    LayoutInflater的使用
    转--Android资源总结(环境搭建/ 反编译工具)
    转--android Toast大全(五种情形)建立属于你自己的Toast
    转--9中对话框
    转--全局异常处理
    安卓记住密码
    转--Android学习笔记-实用代码合集
  • 原文地址:https://www.cnblogs.com/tianzhijiexian/p/4219536.html
Copyright © 2020-2023  润新知