【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 color
    109         // 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 change
    113         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 change
    120         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 final
    124         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 the
    130         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/7889778
    143         // RELATIVE_TO_PARENT:与父控件的的中心为重点;RELATIVE_TO_SELF以自己为中心
    144         // 左上角 分别为0.0f 0.0f 中心点为0.5f,0.5f 右下角1.0f,1.0f
    145         /*
    146          * arcRotation = new RotateAnimation(0.0f, 360.0f,
    147          * Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    148          */
    149         // 持续时间1000ms
    150         // arcRotation.setDuration(500);
    151 
    152         in = new AnimationSet(true);
    153         out = new AnimationSet(true);
    154 
    155         // http://blog.csdn.net/jason0539/article/details/16370405
    156         out.setInterpolator(new AccelerateDecelerateInterpolator());
    157         in.setInterpolator(new AccelerateDecelerateInterpolator());
    158 
    159         // http://blog.csdn.net/xsl1990/article/details/17096501
    160         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             @Override
    194             public void onAnimationStart(Animation animation) {
    195                 // TODO Auto-generated method stub
    196                 System.out.println("print this");
    197             }
    198 
    199             @Override
    200             public void onAnimationRepeat(Animation animation) {
    201                 // TODO Auto-generated method stub
    202 
    203             }
    204 
    205             @Override
    206             public void onAnimationEnd(Animation animation) {
    207                 // TODO Auto-generated method stub
    208 
    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             @Override
    226             public void onAnimationStart(Animation animation) {
    227                 // TODO Auto-generated method stub
    228 
    229             }
    230 
    231             @Override
    232             public void onAnimationRepeat(Animation animation) {
    233                 // TODO Auto-generated method stub
    234 
    235             }
    236 
    237             @Override
    238             public void onAnimationEnd(Animation animation) {
    239                 // TODO Auto-generated method stub
    240                 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 upon
    256         // 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 path
    272         // Create your own icons or feel free to use these
    273 
    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 layout
    320 
    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 types
    330         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 draw
    334                                                                 // first icon(
    335                                                                 // Default -
    336                                                                 // Play )
    337 
    338         second_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw
    339                                                                 // second icon(
    340                                                                 // Default -
    341                                                                 // Stop )
    342 
    343         third_icon_bmp = Bitmap.createBitmap(pix, pix, conf); // Bitmap to draw
    344                                                                 // 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 on
    362                                                         // canvas( Default -
    363                                                         // Stop ).
    364                                                         // *****Set your second
    365                                                         // icon here****
    366 
    367         second_icon_canvas.drawPath(stop, icon_color); // Draw second icon on
    368                                                         // canvas( Default -
    369                                                         // Stop ).
    370                                                         // *****Set your second
    371                                                         // icon here****
    372 
    373         third_icon_canvas.drawPath(tick, final_icon_color); // Draw second icon
    374                                                             // on canvas(
    375                                                             // Default - Stop ).
    376                                                             // *****Set your
    377                                                             // second icon
    378                                                             // 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 values
    400 
    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 animation
    411 
    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 clicked
    421 
    422         cusView.reset();
    423         buttonimage.setImageBitmap(first_icon_bmp);
    424         flg_frmwrk_mode = 1;
    425 
    426     }
    427 
    428     @Override
    429     public void onClick(View v) {
    430         // TODO Auto-generated method stub
    431         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         @Override
    101         protected void onProgressUpdate(Integer... progress) {
    102 
    103             // publishing progress to progress arc
    104 
    105             buttonLayout.cusView.setupprogress(progress[0]);
    106         }
    107 
    108     }
    109 
    110 }

     

 

三、结束语

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

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

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

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

那么今天到此结束~

 

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

 

作者:cpacm
出处:(http://www.cpacm.net/2015/04/01/Android开发日记(十一)——Button控件-自定义Button控件/

 

posted @ 2014-09-17 14:18  cpacm  阅读(6950)  评论(3编辑  收藏  举报