首页 > 代码库 > 【Android的从零单排开发日记】之入门篇(十四)——Button控件+自定义Button控件
【Android的从零单排开发日记】之入门篇(十四)——Button控件+自定义Button控件
好久不见,又是一个新的学期开始了,为什么我感觉好惆怅啊!这一周也发生了不少事情,节假日放了三天的假(好久没有这么悠闲过了),实习公司那边被组长半强制性的要求去解决一个后台登陆的问题,结果就是把Android这块放在一边了,滚去看PHP的后台框架了(人家只是一个Android实习生,不带这么玩的),学校那边老师布置了一个hibernate的项目,还说我给你们一个月时间,慢慢看,慢慢学习(结果就是在群上发了一大堆的hibernate的视频教程,还真的是慢慢看慢慢学习了,而且视频还是极老的,hibernate还是版本3),遇到这种老师我也是醉了。顺便求点hibernate的教程,简单易上手最好了。〈(_ _)〉
好了,进入正题吧,今天要做的是button这个控件。按钮在窗口应用程序中是最常见的控件了,也算是程序与用户进行交互的常见手段了。按钮触发的事件处理,我们称为Evenr Handler,而在Android中,按钮事件是由系统的Button.OnClickListener所控制。那么接下来先看看最基本的button控件是怎么实现的。
一、基本Button控件
- 首先第一步就是往布局文件里拖一个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>
当然,一个控件的布局属性还有很多,这些都是需要我们多用多熟悉才行。
- 然后再在程序中调用它
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控件就完成了。但当然,这不是我们今天要讲的重点,重点是我们如何自定义一个按钮,而不是使用系统给我们的按钮。
二、自定义按钮
我们先来看看效果图吧
这是一个自带进度条的按钮,它可以显示异步任务的进度,当完成后结束操作。我们来看看具体是怎么实现的吧。
- 拆分这个按钮。仔细观察上面的效果图,我们可以把这个按钮分成3个部分,首先是最简单的外面一圈圆,基本上画出个圆放在那里就行了。接着是中间的三角形,正方形以及完成的勾,这个我们可以使用view里的画图类勾勒出来,再使用简单的动画Animation来切换。最后的一部分是覆盖在圆圈上的不断在表示进度的圆圈,这个我们可以不断调用这个view的ondraw来刷新进度。这就是整个按钮的设计思路。我们来看看实际的代码吧。
- 首先是表示进度的圆圈,我们来新建一个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; }}
- 有了表示进度的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); }
最后加上点击按钮时各个状态切换的逻辑关系,这个按钮的布局就完成了。
附上整个类的代码View Code1 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 }
按钮做好了我们可以在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控件