两种方式实现MaterialButton

第一种

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;


public class MaterialButton extends View {

    private static final int DEFAULT_TEXT_SIZE = 10;
    private static final int DEFAULT_TEXT_COLOR = Color.WHITE;
    private static final int MAX_PROGRESS = 50;
    private static final int MSG_CONTINUE_DRAW = 1;

    private Paint textPaint = new Paint();
    private Paint ripplePaint = new Paint();

    private int textColor;
    private int textSize;
    private String textContent = "";
    private boolean isCenterRipple;


    /*波纹边界*/
    private float rippleBorder;
    /*起始点*/
    private PointF pointTouchPosition;
    /*进度*/
    private int progress = 0;


    public MaterialButton(Context context) {
        super(context);
        init();
    }

    public MaterialButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        getAttributes(attrs);
        init();
    }

    private void init() {
        textPaint.setTextSize(textSize);
        textPaint.setColor(textColor);
        ripplePaint.setColor(Color.parseColor("#999999"));
        rippleBorder = Math.max(getWidth(), getHeight());
        postInvalidate();
    }

    private void getAttributes(AttributeSet attrs) {
        final TypedArray attributes = getContext().obtainStyledAttributes(
                attrs, com.kot32.materialprogressbutton.R.styleable.MaterialButton);
        textColor = attributes.getColor(
                R.styleable.MaterialButton_textColor, DEFAULT_TEXT_COLOR);
        textSize = (int) attributes.getDimension(
                R.styleable.MaterialButton_textSize, sp2px(DEFAULT_TEXT_SIZE));
        textContent = attributes.getString(R.styleable.MaterialButton_text);
        isCenterRipple = attributes.getBoolean(R.styleable.MaterialButton_isCenterRipple, false);
        attributes.recycle();
    }


    @Override
    protected synchronized void onDraw(Canvas canvas) {
        float rippleRadius = rippleBorder * ((progress * 1.0f) / MAX_PROGRESS);
        drawRipple(canvas, rippleRadius);
        drawText(canvas);
        if (rippleRadius >= rippleBorder) {
            progress = 0;
        }
    }

    private void drawRipple(Canvas canvas, float rippleRadius) {
        if (pointTouchPosition != null) {
            canvas.drawCircle(pointTouchPosition.x, pointTouchPosition.y, rippleRadius, ripplePaint);
        }
    }

    private void drawText(Canvas canvas) {
        float textWidth = textPaint.measureText(textContent);
        float textHeight = (textPaint.descent() + textPaint.ascent()) / 2;
        canvas.drawText(textContent, (getWidth() - textWidth) / 2 + 5, (getHeight() - textHeight) / 2 + 10, textPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
            handler.sendEmptyMessage(1);
            reSetRippleBorder(isCenterRipple, event);
        }
        return super.onTouchEvent(event);
    }

    private void reSetRippleBorder(boolean isCenterFlipper, MotionEvent event) {
        pointTouchPosition = new PointF();
        if (!isCenterFlipper) {
            //此时rippleBorder应为pointTouchPosition与View四个角之间的最大距离
            pointTouchPosition.x = event.getX();
            pointTouchPosition.y = event.getY();
            float borderA = (float) getDistance(pointTouchPosition, new PointF(0, 0));
            float borderB = (float) getDistance(pointTouchPosition, new PointF(getWidth(), 0));
            float borderC = (float) getDistance(pointTouchPosition, new PointF(0, getHeight()));
            float borderD = (float) getDistance(pointTouchPosition, new PointF(getWidth(), getHeight()));
            rippleBorder = getMax(borderA, borderB, borderC, borderD);
            return;
        }
        pointTouchPosition.x = this.getWidth() / 2;
        pointTouchPosition.y = this.getHeight() / 2;
        rippleBorder = Math.min(pointTouchPosition.x, pointTouchPosition.y);
    }

    protected int sp2px(int spVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal, getResources().getDisplayMetrics());
    }

    private double getDistance(PointF pA, PointF pB) {
        double x = Math.abs(pA.x - pB.x);
        double y = Math.abs(pA.y - pB.y);
        return Math.sqrt(x * x + y * y);
    }

    private float getMax(float... args) {
        float max = 0;
        for (float i : args) {
            if (i >= max) {
                max = i;
            }
        }
        return max;
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == MSG_CONTINUE_DRAW) {
                continueDraw();
            }
            super.handleMessage(msg);
        }
    };

    private void continueDraw() {
        ++progress;
        postInvalidate();
        if (progress < MAX_PROGRESS) {
            handler.sendEmptyMessage(MSG_CONTINUE_DRAW);
        }
        /*else stop draw*/
    }

    public void setText(String text) {
        textContent = text;
    }
}

第二种

使用属性动画,动态改变画圆球的半径,在此就不上代码了.




其中

 
        
        
        
        
    


你可能感兴趣的:(两种方式实现MaterialButton)