首先***步就是往布局文件里拖一个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);
- }
***加上点击按钮时各个状态切换的逻辑关系,这个按钮的布局就完成了。
附上整个类的代码
- package com.example.mybutton;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Path;
- import android.graphics.RectF;
- import android.util.AttributeSet;
- import android.util.DisplayMetrics;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.animation.AccelerateDecelerateInterpolator;
- import android.view.animation.AlphaAnimation;
- import android.view.animation.Animation;
- import android.view.animation.AnimationSet;
- import android.view.animation.ScaleAnimation;
- import android.view.animation.Animation.AnimationListener;
- import android.widget.FrameLayout;
- import android.widget.ImageView;
- public class ButtonLayout extends FrameLayout implements OnClickListener {
- public CusImage cusView;
- public int pix = 0;
- public RectF rect;
- // 图像视图
- // ImageView类可以加载各种来源的图片(如资源或图片库),需要计算图像的尺寸,比便它可以在其他布局中使用,并提供例如缩放和着色(渲染)各种显示选项。
- private ImageView circle_image, buttonimage, fillcircle, full_circle_image;
- // 可以用他来画几何图形、画曲线、画基于路径的文本。这是个绘图的路径类
- private Path stop, tick, play, download_triangle, download_rectangle;
- // 位图类
- private Bitmap third_icon_bmp, second_icon_bmp, first_icon_bmp;
- // 画笔类
- private Paint stroke_color, fill_color, icon_color, final_icon_color;
- // AnimationSet类是Android系统中的动画集合类,用于控制View对象进行多个动作的组合,该类继承于Animation类
- private AnimationSet in, out;
- // RotateAnimation类是Android系统中的旋转变化动画类,用于控制View对象的旋转动作,该类继承于Animation类
- // private RotateAnimation arcRotation;
- // 缩放动画类
- private ScaleAnimation new_scale_in, scale_in, scale_out;
- // 透明度动画
- private AlphaAnimation fade_in, fade_out;
- public int flg_frmwrk_mode = 0;
- boolean first_click = false;
- public ButtonLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- setOnClickListener(this);
- initialise();
- setpaint();
- setAnimation();
- displayMetrics();
- iconCreate();
- init();
- // TODO Auto-generated constructor stub
- }
- public ButtonLayout(Context context) {
- super(context);
- setOnClickListener(this);
- setBackgroundColor(Color.CYAN);
- initialise();
- setpaint();
- setAnimation();
- displayMetrics();
- iconCreate();
- init();
- }
- /**
- * 创建各个控件
- */
- 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 setpaint() {
- // Setting up color
- // Paint.ANTI_ALIAS_FLAG是使位图抗锯齿的标志
- stroke_color = new Paint(Paint.ANTI_ALIAS_FLAG);
- stroke_color.setAntiAlias(true);
- stroke_color.setColor(Color.rgb(0, 161, 234)); // Edit this to change
- stroke_color.setStrokeWidth(3);
- stroke_color.setStyle(Paint.Style.STROKE);
- icon_color = new Paint(Paint.ANTI_ALIAS_FLAG);
- icon_color.setColor(Color.rgb(0, 161, 234));
- // 填充
- icon_color.setStyle(Paint.Style.FILL_AND_STROKE); // Edit this to change
- icon_color.setAntiAlias(true);
- final_icon_color = new Paint(Paint.ANTI_ALIAS_FLAG);
- final_icon_color.setColor(Color.WHITE); // Edit this to change the final
- final_icon_color.setStrokeWidth(12);
- final_icon_color.setStyle(Paint.Style.STROKE);
- final_icon_color.setAntiAlias(true);
- fill_color = new Paint(Paint.ANTI_ALIAS_FLAG);
- fill_color.setColor(Color.rgb(0, 161, 234)); // Edit this to change the
- fill_color.setStyle(Paint.Style.FILL_AND_STROKE);
- fill_color.setAntiAlias(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 displayMetrics() {
- // Responsible for calculating the size of views and canvas based upon
- // screen resolution.
- DisplayMetrics metrics = getContext().getResources()
- .getDisplayMetrics();
- int width = metrics.widthPixels;
- int height = metrics.heightPixels;
- float scarea = width * height;
- pix = (int) Math.sqrt(scarea * 0.0217);
- }
- /**
- * 设置各个画面的路径
- */
- 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);
- }
- public void animation() {
- // Starting view animation and setting flag values
- if (flg_frmwrk_mode == 1) {
- //full_circle_image.setVisibility(View.GONE);
- buttonimage.startAnimation(out);
- }
- }
- public void finalAnimation() {
- // Responsible for final fill up animation
- buttonimage.setVisibility(View.GONE);
- fillcircle.setVisibility(View.VISIBLE);
- fillcircle.startAnimation(new_scale_in);
- }
- public void stop() {
- // Responsible for resetting the state of view when Stop is clicked
- cusView.reset();
- buttonimage.setImageBitmap(first_icon_bmp);
- flg_frmwrk_mode = 1;
- }
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- animation();
- }
- }
按钮做好了我们可以在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中设置
- 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一一介绍下来的。
那么今天到此结束~