zoukankan      html  css  js  c++  java
  • 【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控件/

  • 相关阅读:
    关于Application.Lock和Lock(obj)
    ViewState保存在服务器,可定时清空
    firefox选中flash会出现虚线框
    png for ie6背景透明
    用SQL Server Profiler看sql效率时,发现会隔几秒自动执行一些东西
    ServerXMLHTTP的setTimeouts超时设置
    asp.net 正则表达式过滤所有html标签
    .NET技术开发、VS2005快捷键大全
    在TOMCAT中使用JNDI连接数据源
    设计模式系列之Factory深入研究
  • 原文地址:https://www.cnblogs.com/cpacm/p/3969840.html
Copyright © 2011-2022 走看看