第一种
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;
}
}
第二种
使用属性动画,动态改变画圆球的半径,在此就不上代码了.
其中
<declare-styleable name="MaterialButton">
<attr name="textSize" format="dimension" />
<attr name="textColor" format="color" />
<attr name="text" format="string" />
<attr name="isCenterRipple" format="boolean" />
</declare-styleable>