首页 > 代码库 > 【Android的从零单排开发日记】之入门篇(十四)——Button控件+自定义Button控件

【Android的从零单排开发日记】之入门篇(十四)——Button控件+自定义Button控件

    好久不见,又是一个新的学期开始了,为什么我感觉好惆怅啊!这一周也发生了不少事情,节假日放了三天的假(好久没有这么悠闲过了),实习公司那边被组长半强制性的要求去解决一个后台登陆的问题,结果就是把Android这块放在一边了,滚去看PHP的后台框架了(人家只是一个Android实习生,不带这么玩的),学校那边老师布置了一个hibernate的项目,还说我给你们一个月时间,慢慢看,慢慢学习(结果就是在群上发了一大堆的hibernate的视频教程,还真的是慢慢看慢慢学习了,而且视频还是极老的,hibernate还是版本3),遇到这种老师我也是醉了。顺便求点hibernate的教程,简单易上手最好了。〈(_ _)〉

    好了,进入正题吧,今天要做的是button这个控件。按钮在窗口应用程序中是最常见的控件了,也算是程序与用户进行交互的常见手段了。按钮触发的事件处理,我们称为Evenr Handler,而在Android中,按钮事件是由系统的Button.OnClickListener所控制。那么接下来先看看最基本的button控件是怎么实现的。

 

一、基本Button控件

  1. 首先第一步就是往布局文件里拖一个Button控件,当然自己码出来也可以。XML布局如下
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"         >    <Button        android:id="@+id/button1"             <!-- button按钮的id号,程序通过这个id号来查找相应的控件 -->        android:layout_width="wrap_content"   <!-- button按钮的宽度 当前意思是 根据内容自动拉伸,其他的还有match_parent,表示根据父控件来调整大小-->        android:layout_height="wrap_content"  <!-- button按钮的长度-->        android:layout_alignParentTop="true"  <!-- RelativeLayout布局中,将控件的上边缘和父控件的上边缘对齐 -->        android:layout_centerHorizontal="true"<!-- RelativeLayout布局中,水平居中的意思 -->        android:layout_marginTop="150dp"      <!-- RelativeLayout布局中,距离父控件顶端的距离 -->        android:text="Button" />              <!-- button按钮上显示的文字信息 --></RelativeLayout>

    当然,一个控件的布局属性还有很多,这些都是需要我们多用多熟悉才行。

  2. 然后再在程序中调用它
    public class MainActivity extends Activity {        private Button myButton;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //通过id寻找控件,记得寻找控件前一定要先设置好布局文件        myButton = (Button)findViewById(R.id.button1);        myButton.setOnClickListener(new OnClickListener() {                        @Override            public void onClick(View v) {                // TODO Auto-generated method stub                //这里填写单击按钮后要执行的事件            }                    });        myButton.setOnTouchListener(new OnTouchListener(){...});//设置触碰到按钮的监听器        myButton.setOnLongClickListener(new OnLongClickListener(){...});//设置长按按钮的监听器        myButton.setOnHoverListener(new OnHoverListener(){...});//设置界面覆盖按钮时的监听器        //还有其它的的监听器,我们可以根据不同的需求来调用相应的监听器    }}

    或者这样设置监听器

    public class MainActivity extends Activity implements OnClickListener{        private Button myButton;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //寻找控件,记得寻找控件前一定要先设置好布局文件        myButton = (Button)findViewById(R.id.button1);        myButton.setOnClickListener(this);                }    @Override    public void onClick(View v) {        // TODO Auto-generated method stub        //获取点击的View        switch(v.getId()){        //根据View的id来进行相关操作        case R.id.button1:            //按钮点击时处理相关的事件            break;        }    }}

    这样一个基础功能的button控件就完成了。但当然,这不是我们今天要讲的重点,重点是我们如何自定义一个按钮,而不是使用系统给我们的按钮。

二、自定义按钮

我们先来看看效果图吧

 

这是一个自带进度条的按钮,它可以显示异步任务的进度,当完成后结束操作。我们来看看具体是怎么实现的吧。

  1. 拆分这个按钮。仔细观察上面的效果图,我们可以把这个按钮分成3个部分,首先是最简单的外面一圈圆,基本上画出个圆放在那里就行了。接着是中间的三角形,正方形以及完成的勾,这个我们可以使用view里的画图类勾勒出来,再使用简单的动画Animation来切换。最后的一部分是覆盖在圆圈上的不断在表示进度的圆圈,这个我们可以不断调用这个view的ondraw来刷新进度。这就是整个按钮的设计思路。我们来看看实际的代码吧。
  2. 首先是表示进度的圆圈,我们来新建一个CusImage继承view类,实时的传入进度参数。
    package com.example.mybutton;import android.annotation.SuppressLint;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.util.Log;import android.view.View;@SuppressLint("ViewConstructor") public class CusImage extends View {    private ButtonLayout b;    private Paint myPaint;    private float startAngle, sweepAngle;    private RectF rect;    // 默认控件大小    private int pix = 160;    public CusImage(Context context, ButtonLayout b) {        super(context);        this.b = b;        init();        // TODO Auto-generated constructor stub    }    public CusImage(Context context, AttributeSet attrs, ButtonLayout b) {        super(context, attrs);        this.b = b;        init();        // TODO Auto-generated constructor stub    }    private void init() {        myPaint = new Paint();        DisplayMetrics metrics = getContext().getResources()                .getDisplayMetrics();        int width = metrics.widthPixels;        int height = metrics.heightPixels;        Log.d("TAG", width + "");        Log.d("TAG", height + "");        float scarea = width * height;        pix = (int) Math.sqrt(scarea * 0.0217);        //抗锯齿        myPaint.setAntiAlias(true);        //stroke表示空心,Fill表示实心        myPaint.setStyle(Paint.Style.STROKE);        //颜色        myPaint.setColor(Color.rgb(0, 161, 234));        //设置线条粗细        myPaint.setStrokeWidth(7);        float startx = (float) (pix * 0.05);        float endx = (float) (pix * 0.95);        float starty = (float) (pix * 0.05);        float endy = (float) (pix * 0.95);        //矩形区域        rect = new RectF(startx, starty, endx, endy);    }    @Override    protected void onDraw(Canvas canvas) {        // 画弧线        // 在rect这个区域内画,开始的角度,扫过的度数而不是结束的角度,false表示不与圆心连线,true通常用来画扇形,画笔。        canvas.drawArc(rect, startAngle, sweepAngle, false, myPaint);        startAngle = -90;        //小于1圈        if (sweepAngle < 360 &&b.flg_frmwrk_mode == 2) {            invalidate();        }else if(b.flg_frmwrk_mode == 1){                            }else {//扫完一圈,调用b.finalAnimation()            sweepAngle = 0;            startAngle = -90;            b.finalAnimation();        }        super.onDraw(canvas);    }    /**     * 控制控件的大小 http://blog.csdn.net/pi9nc/article/details/18764863     **/    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int desiredWidth = pix;        int desiredHeight = pix;        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        int width;        int height;        // 如果控件宽度是指定大小,宽度为指定的尺寸        if (widthMode == MeasureSpec.EXACTLY) {            width = widthSize;        } else if (widthMode == MeasureSpec.AT_MOST) { // 没有限制,默认内容大小            width = Math.min(desiredWidth, widthSize);        } else {            width = desiredWidth;        }        // 如果控件高度是指定大小,高度为指定的尺寸        if (heightMode == MeasureSpec.EXACTLY) {            height = heightSize;        } else if (heightMode == MeasureSpec.AT_MOST) {// 没有限制,默认内容大小            height = Math.min(desiredHeight, heightSize);        } else {            height = desiredHeight;        }        // 设定控件大小        setMeasuredDimension(width, height);    }    // 传入参数    public void setupprogress(int progress) {        sweepAngle = (float) (progress * 3.6);    }    public void reset() {        startAngle = -90;    }}

     

  3. 有了表示进度的view之后,我们要在一个viewgroup控件中组装各个部分来实现整个按钮,这里我用的是framelayout
    这里代码写在一起了,我把它们一个一个拎出来讲解。
    首先是ImageView的初始化
    /**     * 创建各个控件     */    private void initialise() {        // 按钮的进度条        cusView = new CusImage(getContext(), this);        // 按钮中间的形状        buttonimage = new ImageView(getContext());        // 完成进度后显示的图像        fillcircle = new ImageView(getContext());        //外面一圈圆        full_circle_image = new ImageView(getContext());        // 设置控件不接受点击事件        cusView.setClickable(false);        buttonimage.setClickable(false);        fillcircle.setClickable(false);        full_circle_image.setClickable(false);        setClickable(true);    }

    然后是设置动画

    /**     * 设置动画及动画监听器     */    private void setAnimation() {        // Setting up and defining view animations.        // http://blog.csdn.net/congqingbin/article/details/7889778        // RELATIVE_TO_PARENT:与父控件的的中心为重点;RELATIVE_TO_SELF以自己为中心        // 左上角 分别为0.0f 0.0f 中心点为0.5f,0.5f 右下角1.0f,1.0f        /*         * arcRotation = new RotateAnimation(0.0f, 360.0f,         * Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);         */        // 持续时间1000ms        // arcRotation.setDuration(500);        in = new AnimationSet(true);        out = new AnimationSet(true);        // http://blog.csdn.net/jason0539/article/details/16370405        out.setInterpolator(new AccelerateDecelerateInterpolator());        in.setInterpolator(new AccelerateDecelerateInterpolator());        // http://blog.csdn.net/xsl1990/article/details/17096501        scale_in = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f,                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,                0.5f);        scale_out = new ScaleAnimation(1.0f, 3.0f, 1.0f, 3.0f,                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,                0.5f);        // 缩放动画,起始x轴的缩放为0,y轴的缩放为0,动画后,x,y轴大小与图像尺寸相同        // x,y可以把它当做宽度和高度        new_scale_in = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f,                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,                0.5f);        new_scale_in.setDuration(200);        // 透明度的动画        fade_in = new AlphaAnimation(0.0f, 1.0f);        fade_out = new AlphaAnimation(1.0f, 0.0f);        scale_in.setDuration(150);        scale_out.setDuration(150);        fade_in.setDuration(150);        fade_out.setDuration(150);        // 进入的动画集        in.addAnimation(scale_in);        in.addAnimation(fade_in);        // 退出的动画集        out.addAnimation(fade_out);        out.addAnimation(scale_out);        out.setAnimationListener(new AnimationListener() {            @Override            public void onAnimationStart(Animation animation) {                // TODO Auto-generated method stub                System.out.println("print this");            }            @Override            public void onAnimationRepeat(Animation animation) {                // TODO Auto-generated method stub            }            @Override            public void onAnimationEnd(Animation animation) {                // TODO Auto-generated method stub                buttonimage.setVisibility(View.GONE);                buttonimage.setImageBitmap(second_icon_bmp);                buttonimage.setVisibility(View.VISIBLE);                buttonimage.startAnimation(in);                full_circle_image.setVisibility(View.VISIBLE);                cusView.setVisibility(View.VISIBLE);                flg_frmwrk_mode = 2;                System.out.println("flg_frmwrk_mode" + flg_frmwrk_mode);            }        });        new_scale_in.setAnimationListener(new AnimationListener() {            @Override            public void onAnimationStart(Animation animation) {                // TODO Auto-generated method stub            }            @Override            public void onAnimationRepeat(Animation animation) {                // TODO Auto-generated method stub            }            @Override            public void onAnimationEnd(Animation animation) {                // TODO Auto-generated method stub                cusView.setVisibility(View.GONE);                buttonimage.setVisibility(View.VISIBLE);                buttonimage.setImageBitmap(third_icon_bmp);                flg_frmwrk_mode = 3;                buttonimage.startAnimation(in);            }        });    }

    再接着是画出各个形状

    /**     * 设置各个画面的路径     */    private void iconCreate() {        // Creating icons using path        // Create your own icons or feel free to use these        play = new Path();        play.moveTo(pix * 40 / 100, pix * 36 / 100);        play.lineTo(pix * 40 / 100, pix * 63 / 100);        play.lineTo(pix * 69 / 100, pix * 50 / 100);        play.close();        stop = new Path();        stop.moveTo(pix * 38 / 100, pix * 38 / 100);        stop.lineTo(pix * 62 / 100, pix * 38 / 100);        stop.lineTo(pix * 62 / 100, pix * 62 / 100);        stop.lineTo(pix * 38 / 100, pix * 62 / 100);        stop.close();        download_triangle = new Path();        download_triangle.moveTo(pix * 375 / 1000, (pix / 2)                + (pix * 625 / 10000) - (pix * 3 / 100));        download_triangle.lineTo(pix / 2, (pix * 625 / 1000)                + (pix * 625 / 10000) - (pix * 3 / 100));        download_triangle.lineTo(pix * 625 / 1000, (pix / 2)                + (pix * 625 / 10000) - (pix * 3 / 100));        download_triangle.close();        download_rectangle = new Path();        download_rectangle.moveTo(pix * 4375 / 10000, (pix / 2)                + (pix * 625 / 10000) - (pix * 3 / 100));        download_rectangle.lineTo(pix * 5625 / 10000, (pix / 2)                + (pix * 625 / 10000) - (pix * 3 / 100));        download_rectangle.lineTo(pix * 5625 / 10000, (pix * 375 / 1000)                + (pix * 625 / 10000) - (pix * 3 / 100));        download_rectangle.lineTo(pix * 4375 / 10000, (pix * 375 / 1000)                + (pix * 625 / 10000) - (pix * 3 / 100));        download_rectangle.close();        tick = new Path();        tick.moveTo(pix * 30 / 100, pix * 50 / 100);        tick.lineTo(pix * 45 / 100, pix * 625 / 1000);        tick.lineTo(pix * 65 / 100, pix * 350 / 1000);    }    /**     * 创建各个bitmap添加到framelayout中     */    public void init() {        // Defining and drawing bitmaps and assigning views to the layout        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(                FrameLayout.LayoutParams.WRAP_CONTENT,                FrameLayout.LayoutParams.WRAP_CONTENT);        lp.setMargins(10, 10, 10, 10);        fillcircle.setVisibility(View.GONE);        Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types        Bitmap full_circle_bmp = Bitmap.createBitmap(pix, pix, conf);        Bitmap fill_circle_bmp = Bitmap.createBitmap(pix, pix, conf);        first_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw                                                                // first icon(                                                                // Default -                                                                // Play )        second_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw                                                                // second icon(                                                                // Default -                                                                // Stop )        third_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw                                                                // third icon(                                                                // Default -                                                                // Tick )        Canvas first_icon_canvas = new Canvas(first_icon_bmp);        Canvas second_icon_canvas = new Canvas(second_icon_bmp);        Canvas third_icon_canvas = new Canvas(third_icon_bmp);        Canvas fill_circle_canvas = new Canvas(fill_circle_bmp);        Canvas full_circle_canvas = new Canvas(full_circle_bmp);        float startx = (float) (pix * 0.05);        float endx = (float) (pix * 0.95);        System.out.println("full circle " + full_circle_canvas.getWidth()                + full_circle_canvas.getHeight());        float starty = (float) (pix * 0.05);        float endy = (float) (pix * 0.95);        rect = new RectF(startx, starty, endx, endy);        first_icon_canvas.drawPath(play, fill_color); // Draw second icon on                                                        // canvas( Default -                                                        // Stop ).                                                        // *****Set your second                                                        // icon here****        second_icon_canvas.drawPath(stop, icon_color); // Draw second icon on                                                        // canvas( Default -                                                        // Stop ).                                                        // *****Set your second                                                        // icon here****        third_icon_canvas.drawPath(tick, final_icon_color); // Draw second icon                                                            // on canvas(                                                            // Default - Stop ).                                                            // *****Set your                                                            // second icon                                                            // here****        full_circle_canvas.drawArc(rect, 0, 360, false, stroke_color);        fill_circle_canvas.drawArc(rect, 0, 360, false, fill_color);        buttonimage.setImageBitmap(first_icon_bmp);        flg_frmwrk_mode = 1;        fillcircle.setImageBitmap(fill_circle_bmp);        full_circle_image.setImageBitmap(full_circle_bmp);        cusView.setVisibility(View.GONE);        addView(full_circle_image, lp);        addView(fillcircle, lp);        addView(buttonimage, lp);        addView(cusView, lp);    }

    最后加上点击按钮时各个状态切换的逻辑关系,这个按钮的布局就完成了。
    附上整个类的代码

      1 package com.example.mybutton;  2   3 import android.content.Context;  4 import android.graphics.Bitmap;  5 import android.graphics.Canvas;  6 import android.graphics.Color;  7 import android.graphics.Paint;  8 import android.graphics.Path;  9 import android.graphics.RectF; 10 import android.util.AttributeSet; 11 import android.util.DisplayMetrics; 12 import android.view.View; 13 import android.view.View.OnClickListener; 14 import android.view.animation.AccelerateDecelerateInterpolator; 15 import android.view.animation.AlphaAnimation; 16 import android.view.animation.Animation; 17 import android.view.animation.AnimationSet; 18 import android.view.animation.ScaleAnimation; 19 import android.view.animation.Animation.AnimationListener; 20 import android.widget.FrameLayout; 21 import android.widget.ImageView; 22  23 public class ButtonLayout extends FrameLayout implements OnClickListener { 24  25     public CusImage cusView; 26     public int pix = 0; 27     public RectF rect; 28     // 图像视图 29     // ImageView类可以加载各种来源的图片(如资源或图片库),需要计算图像的尺寸,比便它可以在其他布局中使用,并提供例如缩放和着色(渲染)各种显示选项。 30     private ImageView circle_image, buttonimage, fillcircle, full_circle_image; 31  32     // 可以用他来画几何图形、画曲线、画基于路径的文本。这是个绘图的路径类 33     private Path stop, tick, play, download_triangle, download_rectangle; 34  35     // 位图类 36     private Bitmap third_icon_bmp, second_icon_bmp, first_icon_bmp; 37  38     // 画笔类 39     private Paint stroke_color, fill_color, icon_color, final_icon_color; 40  41     // AnimationSet类是Android系统中的动画集合类,用于控制View对象进行多个动作的组合,该类继承于Animation类 42     private AnimationSet in, out; 43  44     // RotateAnimation类是Android系统中的旋转变化动画类,用于控制View对象的旋转动作,该类继承于Animation类 45     // private RotateAnimation arcRotation; 46  47     // 缩放动画类 48     private ScaleAnimation new_scale_in, scale_in, scale_out; 49  50     // 透明度动画 51     private AlphaAnimation fade_in, fade_out; 52  53     public int flg_frmwrk_mode = 0; 54     boolean first_click = false; 55  56     public ButtonLayout(Context context, AttributeSet attrs) { 57         super(context, attrs); 58         setOnClickListener(this); 59  60         initialise(); 61         setpaint(); 62         setAnimation(); 63         displayMetrics(); 64         iconCreate(); 65         init(); 66         // TODO Auto-generated constructor stub 67     } 68  69     public ButtonLayout(Context context) { 70         super(context); 71         setOnClickListener(this); 72         setBackgroundColor(Color.CYAN); 73         initialise(); 74         setpaint(); 75         setAnimation(); 76         displayMetrics(); 77         iconCreate(); 78         init(); 79     } 80  81     /** 82      * 创建各个控件 83      */ 84     private void initialise() { 85         // 按钮的进度条 86         cusView = new CusImage(getContext(), this); 87         // 按钮中间的形状 88         buttonimage = new ImageView(getContext()); 89         // 完成进度后显示的图像 90         fillcircle = new ImageView(getContext()); 91         //外面一圈圆 92         full_circle_image = new ImageView(getContext()); 93         // 设置控件不接受点击事件 94         cusView.setClickable(false); 95         buttonimage.setClickable(false); 96         fillcircle.setClickable(false); 97         full_circle_image.setClickable(false); 98  99         setClickable(true);100 101     }102 103     /**104      * 设置各类画笔105      */106     private void setpaint() {107 108         // Setting up color109         // Paint.ANTI_ALIAS_FLAG是使位图抗锯齿的标志110         stroke_color = new Paint(Paint.ANTI_ALIAS_FLAG);111         stroke_color.setAntiAlias(true);112         stroke_color.setColor(Color.rgb(0, 161, 234)); // Edit this to change113         stroke_color.setStrokeWidth(3);114         stroke_color.setStyle(Paint.Style.STROKE);115 116         icon_color = new Paint(Paint.ANTI_ALIAS_FLAG);117         icon_color.setColor(Color.rgb(0, 161, 234));118         // 填充119         icon_color.setStyle(Paint.Style.FILL_AND_STROKE); // Edit this to change120         icon_color.setAntiAlias(true);121 122         final_icon_color = new Paint(Paint.ANTI_ALIAS_FLAG);123         final_icon_color.setColor(Color.WHITE); // Edit this to change the final124         final_icon_color.setStrokeWidth(12);125         final_icon_color.setStyle(Paint.Style.STROKE);126         final_icon_color.setAntiAlias(true);127 128         fill_color = new Paint(Paint.ANTI_ALIAS_FLAG);129         fill_color.setColor(Color.rgb(0, 161, 234)); // Edit this to change the130         fill_color.setStyle(Paint.Style.FILL_AND_STROKE);131         fill_color.setAntiAlias(true);132 133     }134 135     /**136      * 设置动画及动画监听器137      */138     private void setAnimation() {139 140         // Setting up and defining view animations.141 142         // http://blog.csdn.net/congqingbin/article/details/7889778143         // RELATIVE_TO_PARENT:与父控件的的中心为重点;RELATIVE_TO_SELF以自己为中心144         // 左上角 分别为0.0f 0.0f 中心点为0.5f,0.5f 右下角1.0f,1.0f145         /*146          * arcRotation = new RotateAnimation(0.0f, 360.0f,147          * Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);148          */149         // 持续时间1000ms150         // arcRotation.setDuration(500);151 152         in = new AnimationSet(true);153         out = new AnimationSet(true);154 155         // http://blog.csdn.net/jason0539/article/details/16370405156         out.setInterpolator(new AccelerateDecelerateInterpolator());157         in.setInterpolator(new AccelerateDecelerateInterpolator());158 159         // http://blog.csdn.net/xsl1990/article/details/17096501160         scale_in = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f,161                 Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,162                 0.5f);163         scale_out = new ScaleAnimation(1.0f, 3.0f, 1.0f, 3.0f,164                 Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,165                 0.5f);166 167         // 缩放动画,起始x轴的缩放为0,y轴的缩放为0,动画后,x,y轴大小与图像尺寸相同168         // x,y可以把它当做宽度和高度169         new_scale_in = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f,170                 Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,171                 0.5f);172 173         new_scale_in.setDuration(200);174 175         // 透明度的动画176         fade_in = new AlphaAnimation(0.0f, 1.0f);177         fade_out = new AlphaAnimation(1.0f, 0.0f);178 179         scale_in.setDuration(150);180         scale_out.setDuration(150);181         fade_in.setDuration(150);182         fade_out.setDuration(150);183 184         // 进入的动画集185         in.addAnimation(scale_in);186         in.addAnimation(fade_in);187         // 退出的动画集188         out.addAnimation(fade_out);189         out.addAnimation(scale_out);190 191         out.setAnimationListener(new AnimationListener() {192 193             @Override194             public void onAnimationStart(Animation animation) {195                 // TODO Auto-generated method stub196                 System.out.println("print this");197             }198 199             @Override200             public void onAnimationRepeat(Animation animation) {201                 // TODO Auto-generated method stub202 203             }204 205             @Override206             public void onAnimationEnd(Animation animation) {207                 // TODO Auto-generated method stub208 209                 buttonimage.setVisibility(View.GONE);210                 buttonimage.setImageBitmap(second_icon_bmp);211                 buttonimage.setVisibility(View.VISIBLE);212                 buttonimage.startAnimation(in);213                 full_circle_image.setVisibility(View.VISIBLE);214                 cusView.setVisibility(View.VISIBLE);215 216                 flg_frmwrk_mode = 2;217 218                 System.out.println("flg_frmwrk_mode" + flg_frmwrk_mode);219 220             }221         });222 223         new_scale_in.setAnimationListener(new AnimationListener() {224 225             @Override226             public void onAnimationStart(Animation animation) {227                 // TODO Auto-generated method stub228 229             }230 231             @Override232             public void onAnimationRepeat(Animation animation) {233                 // TODO Auto-generated method stub234 235             }236 237             @Override238             public void onAnimationEnd(Animation animation) {239                 // TODO Auto-generated method stub240                 cusView.setVisibility(View.GONE);241                 buttonimage.setVisibility(View.VISIBLE);242                 buttonimage.setImageBitmap(third_icon_bmp);243                 flg_frmwrk_mode = 3;244                 buttonimage.startAnimation(in);245 246             }247         });248 249     }250 251     /**252      * 设置自定义控件的大小253      */254     private void displayMetrics() {255         // Responsible for calculating the size of views and canvas based upon256         // screen resolution.257         DisplayMetrics metrics = getContext().getResources()258                 .getDisplayMetrics();259         int width = metrics.widthPixels;260         int height = metrics.heightPixels;261         float scarea = width * height;262         pix = (int) Math.sqrt(scarea * 0.0217);263 264     }265 266     /**267      * 设置各个画面的路径268      */269     private void iconCreate() {270 271         // Creating icons using path272         // Create your own icons or feel free to use these273 274         play = new Path();275         play.moveTo(pix * 40 / 100, pix * 36 / 100);276         play.lineTo(pix * 40 / 100, pix * 63 / 100);277         play.lineTo(pix * 69 / 100, pix * 50 / 100);278         play.close();279 280         stop = new Path();281         stop.moveTo(pix * 38 / 100, pix * 38 / 100);282         stop.lineTo(pix * 62 / 100, pix * 38 / 100);283         stop.lineTo(pix * 62 / 100, pix * 62 / 100);284         stop.lineTo(pix * 38 / 100, pix * 62 / 100);285         stop.close();286 287         download_triangle = new Path();288         download_triangle.moveTo(pix * 375 / 1000, (pix / 2)289                 + (pix * 625 / 10000) - (pix * 3 / 100));290         download_triangle.lineTo(pix / 2, (pix * 625 / 1000)291                 + (pix * 625 / 10000) - (pix * 3 / 100));292         download_triangle.lineTo(pix * 625 / 1000, (pix / 2)293                 + (pix * 625 / 10000) - (pix * 3 / 100));294         download_triangle.close();295 296         download_rectangle = new Path();297         download_rectangle.moveTo(pix * 4375 / 10000, (pix / 2)298                 + (pix * 625 / 10000) - (pix * 3 / 100));299         download_rectangle.lineTo(pix * 5625 / 10000, (pix / 2)300                 + (pix * 625 / 10000) - (pix * 3 / 100));301         download_rectangle.lineTo(pix * 5625 / 10000, (pix * 375 / 1000)302                 + (pix * 625 / 10000) - (pix * 3 / 100));303         download_rectangle.lineTo(pix * 4375 / 10000, (pix * 375 / 1000)304                 + (pix * 625 / 10000) - (pix * 3 / 100));305         download_rectangle.close();306 307         tick = new Path();308         tick.moveTo(pix * 30 / 100, pix * 50 / 100);309         tick.lineTo(pix * 45 / 100, pix * 625 / 1000);310         tick.lineTo(pix * 65 / 100, pix * 350 / 1000);311 312     }313 314     /**315      * 创建各个bitmap添加到framelayout中316      */317     public void init() {318 319         // Defining and drawing bitmaps and assigning views to the layout320 321         FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(322                 FrameLayout.LayoutParams.WRAP_CONTENT,323                 FrameLayout.LayoutParams.WRAP_CONTENT);324 325         lp.setMargins(10, 10, 10, 10);326 327         fillcircle.setVisibility(View.GONE);328 329         Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types330         Bitmap full_circle_bmp = Bitmap.createBitmap(pix, pix, conf);331         Bitmap fill_circle_bmp = Bitmap.createBitmap(pix, pix, conf);332 333         first_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw334                                                                 // first icon(335                                                                 // Default -336                                                                 // Play )337 338         second_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw339                                                                 // second icon(340                                                                 // Default -341                                                                 // Stop )342 343         third_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw344                                                                 // third icon(345                                                                 // Default -346                                                                 // Tick )347 348         Canvas first_icon_canvas = new Canvas(first_icon_bmp);349         Canvas second_icon_canvas = new Canvas(second_icon_bmp);350         Canvas third_icon_canvas = new Canvas(third_icon_bmp);351         Canvas fill_circle_canvas = new Canvas(fill_circle_bmp);352         Canvas full_circle_canvas = new Canvas(full_circle_bmp);353         float startx = (float) (pix * 0.05);354         float endx = (float) (pix * 0.95);355         System.out.println("full circle " + full_circle_canvas.getWidth()356                 + full_circle_canvas.getHeight());357         float starty = (float) (pix * 0.05);358         float endy = (float) (pix * 0.95);359         rect = new RectF(startx, starty, endx, endy);360 361         first_icon_canvas.drawPath(play, fill_color); // Draw second icon on362                                                         // canvas( Default -363                                                         // Stop ).364                                                         // *****Set your second365                                                         // icon here****366 367         second_icon_canvas.drawPath(stop, icon_color); // Draw second icon on368                                                         // canvas( Default -369                                                         // Stop ).370                                                         // *****Set your second371                                                         // icon here****372 373         third_icon_canvas.drawPath(tick, final_icon_color); // Draw second icon374                                                             // on canvas(375                                                             // Default - Stop ).376                                                             // *****Set your377                                                             // second icon378                                                             // here****379 380         full_circle_canvas.drawArc(rect, 0, 360, false, stroke_color);381         fill_circle_canvas.drawArc(rect, 0, 360, false, fill_color);382 383         buttonimage.setImageBitmap(first_icon_bmp);384         flg_frmwrk_mode = 1;385         fillcircle.setImageBitmap(fill_circle_bmp);386         full_circle_image.setImageBitmap(full_circle_bmp);387 388         cusView.setVisibility(View.GONE);389 390         addView(full_circle_image, lp);391         addView(fillcircle, lp);392         addView(buttonimage, lp);393         addView(cusView, lp);394 395     }396 397     public void animation() {398 399         // Starting view animation and setting flag values400 401         if (flg_frmwrk_mode == 1) {402             //full_circle_image.setVisibility(View.GONE);403             buttonimage.startAnimation(out);404         }405 406     }407 408     public void finalAnimation() {409 410         // Responsible for final fill up animation411 412         buttonimage.setVisibility(View.GONE);413         fillcircle.setVisibility(View.VISIBLE);414         fillcircle.startAnimation(new_scale_in);415 416     }417 418     public void stop() {419 420         // Responsible for resetting the state of view when Stop is clicked421 422         cusView.reset();423         buttonimage.setImageBitmap(first_icon_bmp);424         flg_frmwrk_mode = 1;425 426     }427 428     @Override429     public void onClick(View v) {430         // TODO Auto-generated method stub431         animation();432     }433 434 }
    View Code
  4. 按钮做好了我们可以在Activity中调用它了
    首先是写入到布局文件中

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"         >    <com.example.mybutton.ButtonLayout        android:id="@+id/ButtonLayout01"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerHorizontal="true"        android:layout_centerVertical="true"        android:clickable="true" >    </com.example.mybutton.ButtonLayout></RelativeLayout>


    然后在activity中设置

      1 public class MainActivity extends Activity {  2   3     private static ButtonLayout buttonLayout;  4   5     @Override  6     protected void onCreate(Bundle savedInstanceState) {  7         super.onCreate(savedInstanceState);  8         setContentView(R.layout.activity_main);  9         buttonLayout = (ButtonLayout) findViewById(R.id.ButtonLayout01); 10         buttonLayout.setOnClickListener(new OnClickListener() { 11  12             @Override 13             public void onClick(View v) { 14                 // TODO Auto-generated method stub 15                 buttonLayout.animation(); // Need to call this method for 16                 // animation and progression 17  18                 if (buttonLayout.flg_frmwrk_mode == 1) { 19  20                     // Start state. Call any method that you want to execute 21  22                     runOnUiThread(new Runnable() { 23  24                         @Override 25                         public void run() { 26                             // TODO Auto-generated method stub 27                             Toast.makeText(MainActivity.this, 28                                     "Starting download", Toast.LENGTH_SHORT) 29                                     .show(); 30                         } 31                     }); 32                     new DownLoadSigTask().execute(); 33                 } 34                 if (buttonLayout.flg_frmwrk_mode == 2) { 35  36                     // Running state. Call any method that you want to execute 37  38                     new DownLoadSigTask().cancel(true); 39                     buttonLayout.stop(); 40                     runOnUiThread(new Runnable() { 41  42                         @Override 43                         public void run() { 44                             // TODO Auto-generated method stub 45                             Toast.makeText(MainActivity.this, 46                                     "Download stopped", Toast.LENGTH_SHORT) 47                                     .show(); 48                         } 49                     }); 50                 } 51                 if (buttonLayout.flg_frmwrk_mode == 3) { 52  53                     // End state. Call any method that you want to execute. 54  55                     runOnUiThread(new Runnable() { 56  57                         @Override 58                         public void run() { 59                             // TODO Auto-generated method stub 60                             Toast.makeText(MainActivity.this, 61                                     "Download complete", Toast.LENGTH_SHORT) 62                                     .show(); 63                         } 64                     }); 65                 } 66             } 67  68         }); 69     } 70  71     static class DownLoadSigTask extends AsyncTask<String, Integer, String> { 72  73         @Override 74         protected void onPreExecute() { 75  76         } 77  78         @Override 79         protected String doInBackground(final String... args) { 80  81             // Creating dummy task and updating progress 82  83             for (int i = 0; i <= 100;) { 84                 try { 85                     Thread.sleep(50); 86  87                 } catch (InterruptedException e) { 88  89                     e.printStackTrace(); 90                 } 91                 if (buttonLayout.flg_frmwrk_mode == 2 &&i<=100){ 92                     i++; 93                     publishProgress(i); 94                 } 95             } 96  97             return null; 98         } 99 100         @Override101         protected void onProgressUpdate(Integer... progress) {102 103             // publishing progress to progress arc104 105             buttonLayout.cusView.setupprogress(progress[0]);106         }107 108     }109 110 }

     

 

三、结束语

这个按钮我是仿照一个开源项目写的,它的地址是https://github.com/torryharris/TH-ProgressButton。

我在代码中掺杂了一些网址,这些都是我在看这整个开源代码时查阅的资料,如果你也不懂的话也可以去这些地址看看资料。

说实话,自定义控件设计的东西太多,不适合在入门的时候学习,不过有个概念,以此来抛砖引玉也是挺好的。

接下来不久的时间内我也会把今天遇到的一些概念,比如说animation,path,canvas一一介绍下来的。

那么今天到此结束~

 

========================================

 

作者:cpacm
出处:(http://www.cnblogs.com/cpacm/p/3969840.html)

 

【Android的从零单排开发日记】之入门篇(十四)——Button控件+自定义Button控件