welcome
效果
;
技术基础思路
- 自定义 Button
- 自定义 Drawable
项目源码
自定义button
其实这只是一些说法
自定义button,我们只需要将子类继承 button
public class AnimationButton extends Button {
public AnimationButton(Context context) {
super(context);
initFunction(context, null, 0);
}
public AnimationButton(Context context, AttributeSet attrs) {
super(context, attrs);
initFunction(context, attrs, 0);
}
public AnimationButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initFunction(context, attrs, defStyleAttr);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
//初始化操作方法
private void initFunction(Context context, AttributeSet attrs, int defStyleAttr) {
//获取自定义属性
if (attrs != null) {
TypedArray typedArray =context.obtainStyledAttributes(attrs,R.styleable.AnimationButton);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
//验证 drawable
@Override
protected boolean verifyDrawable(Drawable who) {
return who == mDrawable || super.verifyDrawable(who);
}
//触摸事件
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
}
上述只是开发一个自定义View常用的思路
自定义 drawable
public class AnimationButtonDrawable extends Drawable {
//默认 透明度
private int mAlpha = 255;
//默认画笔
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//默认颜色
private int mColor = 0;
//绘制的区域
private int mWidth, mHeight;
//波纹圆形的 圆心与半径
private float mCirculX, mCirculY, mCirculRadus;
private Handler mHandler = new Handler(Looper.getMainLooper());
private int mBackGroundNormalColor = Color.parseColor("#ffffff");
//背景颜色
private int mBackGroundColor = mBackGroundNormalColor;
//背景矩形
private RectF mBackGroundRect;
private float rx, ry;
//点击圆形颜色
private int mAnimationCircleColor = Color.BLUE;
//点击 按钮 down 颜色
private int mBackGroundDownColor = Color.GRAY;
public AnimationButtonDrawable() {
//设置抗锯齿
this.mPaint.setAntiAlias(true);
//设置防抖动
this.mPaint.setDither(true);
}
//绘制功能
@Override
public void draw(Canvas canvas) {
}
@Override
public int getAlpha() {
return mAlpha;
}
//设置透明度
@Override
public void setAlpha(int alpha) {
//设置 drawable的透明度
mAlpha = alpha;
onColorOrAlphaChange();
}
//设置颜色滤镜
@Override
public void setColorFilter(ColorFilter colorFilter) {
if (mPaint.getColorFilter() != colorFilter) {
mPaint.setColorFilter(colorFilter);
}
}
//确认drawable是否有透明度
@Override
public int getOpacity() {
int alpha = mPaint.getAlpha();
if (alpha == 255) {
//不透明
return PixelFormat.OPAQUE;
} else if (alpha == 0) {
//全透明
return PixelFormat.TRANSPARENT;
} else {
//半透明
return PixelFormat.TRANSLUCENT;
}
}
public void onColorOrAlphaChange() {
mPaint.setColor(mColor);
//获取画笔透明度
if (mAlpha != 255) {
int paintAlpha = mPaint.getAlpha();
int realAppha = (int) (paintAlpha * (mAlpha / 255f));
mPaint.setAlpha(realAppha);
}
}
}
- 在这里,我们定义实现了一个基本的drawble AnimationButtonDrawable
- 一个button ,要初始化使用的变量有
有正常显示的背景颜色,
有按下的背景颜色,
当点击抬起时,绘制波纹的颜色,
绘制波纹的位置与半径
-
最重要的步骤是在draw方法中
通过方法
canvas.drawRoundRect(mBackGroundRect, rx, ry, mPaint);
来绘制圆角矩形背景通过方法
canvas.drawCircle(mCirculX, mCirculY, mCirculRadus, mPaint);
来绘制点击后抬起的圆角矩形通过设置模式来解决边框圆角被覆盖问题
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));完整的draw方法
//绘制功能
@Override
public void draw(Canvas canvas) {
//绘制区域
int canvasWidth = canvas.getWidth();
int canvasHeight = canvas.getHeight();
//新建图层
int layerId = canvas.saveLayer(0, 0, canvasWidth, canvasHeight, null, Canvas.ALL_SAVE_FLAG);
mPaint.setColor(mBackGroundColor);
//绘制背景 圆角矩形
if (mBackGroundRect != null) {
canvas.drawRoundRect(mBackGroundRect, rx, ry, mPaint);
}
//设置图层重叠模式
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
mPaint.setColor(mAnimationCircleColor);
//绘制圆形波纹
canvas.drawCircle(mCirculX, mCirculY, mCirculRadus, mPaint);
//最后将画笔去除Xfermode
mPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
button 与 drawable结合
在button中,当button创建的时候,我们创建drawable,
mDrawable = new AnimationButtonDrawable();
然后在button的ondraw方法中,使用drawable的draw方法,这样就通过 canvas 画布将两者关联起来了
@Override
protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
super.onDraw(canvas);
}
设置点击时的button背景颜色
在button中的onTouchEvent方法,监听事件的发生,并将事件传入到drawable中
@Override
public boolean onTouchEvent(MotionEvent event) {
//设置事件
mDrawable.setTouchEvent(event);
return super.onTouchEvent(event);
}
在drawable中的setTouchEvent方法中进行事件处理
public void setTouchEvent(MotionEvent event) {
//刷新
invalidateSelf();
//判断点击操作
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
onTouchDown(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
onTouchMove(event.getX(), event.getY());
break;
case MotionEvent.ACTION_UP:
onTouchUp(event.getX(), event.getY());
break;
case MotionEvent.ACTION_CANCEL:
onTouchCancel(event.getX(), event.getY());
break;
}
}
在ontouchDown方法, 我们更新绘制圆角矩形的颜色为按下时的颜色,并在onTouchUp方法中恢复我们正常情况下显示的背景颜色,就可以达到button点击选择器的风格
在ontouchDown方法中,我们可以开启一个异步任务,在一定的时间内不断的绘制不同半径的圆 叠加在之前绘制好的矩形背景上面,就可以在视觉方面达到一种波纹效果,
在这里 绘制不大小的圆形,是通过 不断改变绘制半径来达到这个效果的
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
invalidateSelf();
if (mCirculRadus <= mWidth) {
isRun = true;
mCirculRadus += 18;
mHandler.postDelayed(mRunnable, 2);
} else {
isRun = false;
mCirculX = 0;
mCirculY = 0;
mCirculRadus = 0;
}
}
};