android开发自定义动态Button

来源:互联网 发布:程序员刚入职很痛苦 编辑:程序博客网 时间:2024/04/28 08:14
package com.example.mybutton;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.Shader;import android.graphics.SweepGradient;import android.util.AttributeSet;import android.util.Log;import android.widget.Button;public class MyButton extends Button {private Paint mTextPaint, mPaint;private String mText;private int mAscent;private Shader mShader;private Matrix mMatrix = new Matrix();// 一个3*3的矩阵,通过该矩阵可以完成平移旋转private float mStart;//下一次画椭圆的起点private float mSweep;// 用来表示绘制的角度,也就是扫描(抹掉)的角度private float mRotate;// 用来表示闪动的频率private static final float SWEEP_INC = 2;private static final float START_INC = 15;/** * 2个构造函数初始化Paint画笔,以及padding *  * @param context */public MyButton(Context context) {super(context);initLabelView();}public MyButton(Context context, AttributeSet attrs) {super(context, attrs);initLabelView();}private final void initLabelView() {mTextPaint = new Paint();mTextPaint.setAntiAlias(true);mTextPaint.setTextSize(16);mTextPaint.setColor(0xff000000);setPadding(15, 15, 15, 15);mPaint = new Paint();mPaint.setAntiAlias(true);mPaint.setStrokeWidth(4);mPaint.setAntiAlias(true);// 抗锯齿,图像边缘稍微清晰一点,没有锯齿,是图像的边缘mPaint.setStyle(Paint.Style.STROKE);// colors The colors to be distributed between around the// center,第三个参数表示圆圈的颜色变化,第一个颜色是主要的颜色// 最后一个颜色会闪动,中间的颜色不显示mShader = new SweepGradient(this.getMeasuredWidth(),this.getMeasuredHeight(), new int[] { Color.GREEN,Color.DKGRAY, Color.BLUE }, null);mPaint.setShader(mShader);// 设置颤抖效果}/** * setText和setTextSize都可能会改变大小,这就需要requestLayout * setText和setTextSize、setTextColor调用后都需要重绘 *  * @param text */public void setText(String text) {mText = text;requestLayout();invalidate();}public void setTextSize(int size) {mTextPaint.setTextSize(size);requestLayout();invalidate();}public void setTextColor(int color) {mTextPaint.setColor(color);invalidate();}// 自定义视图关键一步,必须调用setMeasuredDimension(int width, int// height)来存储测量得到的宽度和高度值,如果没有这么去做会触发异常IllegalStateException。@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension(measureWidth(widthMeasureSpec),// dimension:尺寸measureHeight(heightMeasureSpec));}/** * 获取宽度 *  * @param measureSpec * @return */private int measureWidth(int measureSpec) {int result = 0;int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);if (specMode == MeasureSpec.EXACTLY) {// we were told how big to be.result = specSize;} else {// measure the text// 这是UNSPECIFIED情况下的resultresult = (int) mTextPaint.measureText(mText) + getPaddingLeft()+ getPaddingRight();if (specMode == MeasureSpec.AT_MOST) {// at most至多的意思result = Math.min(result, specSize);// 使用的不能超过specSize,如果小于specSize就想用多少用多少}}return result;}private int measureHeight(int measureSpec) {int result = 0;int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);mAscent = (int) mTextPaint.ascent();if (specMode == MeasureSpec.EXACTLY) {// we were told how big to beresult = specSize;} else {// Measure the Text(beware: ascent is a negative number)result = (int) (mTextPaint.descent() - mAscent) + getPaddingTop()+ getPaddingBottom();if (specMode == MeasureSpec.AT_MOST) {Log.v("Measure Height", "At Most Height:" + specSize);result = Math.min(specSize, result);}}return result;}private void drawArcs(Canvas canvas, RectF oval, boolean useCenter,Paint paint) {canvas.drawArc(oval, mStart, mSweep, useCenter, paint);// mStart和mSweep都没有初始化就是0咯}// onDraw方法的调用后除了开始调用还会在每次的click后调用,还会在invalidate()里面调用,所以invalidate和onDraw一直互相调用@Overrideprotected void onDraw(Canvas canvas) {measure(0, 0);//由于调用过this.getMeasuredWidth所以得先测量下mMatrix.setRotate(mRotate, this.getMeasuredWidth() / 2,this.getMeasuredHeight() / 2);// 设置闪动的的频率和中心mShader.setLocalMatrix(mMatrix);// mShader最后会被设置到mPaint上mRotate += 10;// 设置闪动的频率,越来越快直到360if (mRotate >= 360) {mRotate = 0;}RectF drawRect = new RectF();//容纳4个点的容器drawRect.set(this.getWidth() - mTextPaint.measureText(mText),(this.getHeight() - mTextPaint.getTextSize()) / 2,mTextPaint.measureText(mText),this.getHeight()- (this.getHeight() - mTextPaint.getTextSize()) / 2);drawArcs(canvas, drawRect, false, mPaint);// 这里该画笔控制每次画多少逐渐的画完360mSweep += SWEEP_INC;if (mSweep > 360) {mSweep -= 360;mStart += START_INC;// 每次移动15等24次移动一周,此时已经画了24个椭圆if (mStart > 360) {mStart -= 360;}}if (mSweep > 180) {canvas.drawText(mText, getPaddingLeft(), getPaddingTop() - mAscent,mTextPaint);}invalidate();/*if(b){b=false;invalidate();}*/}boolean b=true;}

上面的Button这样设置到布局文件里面

    <com.example.mybutton.MyButton        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/mybutton1"/>

在主Activity里面:

mButton=(MyButton) findViewById(R.id.mybutton1);mButton.setText("Custom Button");mButton.setTextSize(40f);mButton.setTextColor(Color.RED);


于是我们可以看见一个动态的Button,如何让它慢点或者停止呢,只需要不让onDraw里面持续调用invalidate就就行了

注释掉invalidate,然后取消下面if(){}外面的注释,运行一下,每次点击后就重新invalidate一次,这样就看到慢点的Button了

0 0