目标
1.创建一个类继承Button并重写onDraw方法
2.创建一个类继承Drawable,在类中实现以下目标
- 能设定颜色,透明度
- 点击画圆
- 自动淡出圆的动画效果
首先创建Button类代码如下:
public class RippleButton extends android.suppert.v7.widget.AppCompatButton {
private RippleDrawable mRippleDrawable;
public RippleButton(Context context){
this(context,null);
}
public RippleButton(Context context,AttributeSet attrs){
this(context,attrs,0);
}
public RippleButton(Context context,AttributSet attrs,int defStyleAttr){
super(context,attrs,defStyleAttr);
mRippleDrawable = new RippleDrawable();
}
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
mRippleDrawable.draw(canvas);
}
}
创建Drawable类,实现draw方法:
public class RippleDrawable extends Drawable{
public RippleDrawable(){
}
public void draw(Canvas canvas){
}
}
布局设置:
background背景图可放不可放.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.test.android.customviewtest.MainActivity">
<com.test.android.customviewtest.RippleButton
android:layout_width="match_parent"
android:layout_height="400dp"
android:layout_centerInParent="true"
android:background="@drawable/ba"
android:gravity="center"
android:text="Ripple Button"
android:textColor="@color/colorPrimary"
/>
</RelativeLayout>
接下来画涟漪的圆在RippleDrawable类中:
public class RippleDrawable extends Drawable{
private int mRippleColor = 0;
private int mAlpha = 255;
private Paint mPaint = new Paint();
private float mRipplePointX, mRipplePointY;//圆心坐标
private float mRippleRadios = 0;//半径
public RippleDrawable() {
mPaint.setAntiAlias(true);//开启抗锯齿,抗平滑
mPaint.setDither(true);//开启防抖动
setRippleColor(Color.RED);//设置涟漪圆的颜色
//滤镜,可以根据需求来,也可以不设
// setColorFilter(new LightingColorFilter(0xFFFF0000,0x00330000));
}
private int mPaintAlpha = 255;
private int mBackgroundColor;
public void draw(Canvas canvas){
mPaint.setAlpha(mPaintAlpha);
canvas.drawColor(mBackgroundColor);
canvas.drawCircle(mRipplePointX,mRipplePointY,mRippleRadios,mPaint);
}
@Override
public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
mAlpha = alpha;
onColorOrAlphaChange();
}
@Override
public int getAlpha() {
return mAlpha;
}
public void setRippleColor(int color){
mRippleColor = color;
onColorOrAlphaChange();
}
public void onColorOrAlphaChange(){
mPaint.setColor = mRippleColor;
if(mAlpha != 255){
int pAlpha = mPaint.getAlpha();
int realAlpha = (int)(pAlpha * (mAlpha/255f));
mPaint.setAlpha(realAlpha);
mPaint.getColor();
}
invalidateSelf();
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
if (mPaint.getColorFilter() != colorFilter) {
mPaint.setColorFilter(colorFilter);
invalidateSelf();
}
}
@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;
}
}
}
点击事件:
RippleButtion类
圆点击事件实现刷新需要3步
public class RippleButton extends android.support.v7.widget.AppCompatButton {
......
public RippleButton(Context context, AttributeSet attrs, int defStyleAttr) {
......
//1.设置刷新回调
mRippleDrawable.setCallback(this);
}
@Override
protected boolean verifyDrawable(@NonNull Drawable who) {
//2.验证drawable是否OK
return who == mRippleDrawable || super.verifyDrawable(who);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//3.设置drawable重绘和刷新的区域
mRippleDrawable.setBounds(0, 0, getWidth(), getHeight());
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mRippleDrawable.onTouch(event);
super.onTouchEvent(event);
return true;
}
}
RippleDrawable中要实现点击事件,进\退出动画
//用户是否抬起
private boolean mTouchRelease;
public void onTouch(MotionEvent event) {
//getAction()封装了点击的详细信息,是点击抬起还是按下的操作,同时包括点击的坐标信息.
//getActionMasked()仅仅只保留了点击的操作
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;
}
}
private void onTouchDown(float x, float y) {
mDonePointX = x;
mDonePointY = y;
mRippleRadios = 0;
mTouchRelease = false;
startEnterRunnable();
// mRunnable.run();
}
private void onTouchMove(float x, float y) {
}
private void onTouchUp(float x, float y) {
mTouchRelease = true;
if (mEnterDone)
startExitRunnable();
}
private void onTouchCancel(float x, float y) {
mTouchRelease = true;
if (mEnterDone)
startExitRunnable();
}
private boolean mEnterDone;
private float mEnterProgress = 0;
//动画查看器,用于实现从快到慢的效果
private Interpolator mEnterInterpolator = new DecelerateInterpolator(2);
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
mEnterProgress = mEnterProgress + 0.01f;
if (mEnterProgress > 1) {
onEnterDone();
return;
}
float realProgress = mEnterInterpolator.getInterpolation(mEnterProgress);
onEnterProgress(realProgress);
scheduleSelf(this, SystemClock.currentThreadTimeMillis() + 16);
}
};
private void onEnterDone() {
mEnterDone = true;
if (mTouchRelease) {
startExitRunnable();
}
}
private void onEnterProgress(float progress) {
float maxRadius = Math.max(mCenterPointX, mCenterPointY);
mRippleRadios = getProgresValue(0f, maxRadius, progress);
mRipplePointX = getProgresValue(mDonePointX, mCenterPointX, progress);
mRipplePointY = getProgresValue(mDonePointY, mCenterPointY, progress);
int alpha = (int) getProgresValue(0, 64, progress);
mBackgroundColor = changeColorAlpha(0x00000000, alpha);
invalidateSelf();
}
//启动进入动画
private void startEnterRunnable() {
mPaintAlpha = 255;
mEnterDone = false;
mEnterProgress = 0;
unscheduleSelf(mExitRunnable);
unscheduleSelf(mRunnable);
scheduleSelf(mRunnable, SystemClock.uptimeMillis());
}
//启动退出动画
private void startExitRunnable() {
mExitProgress = 0;
unscheduleSelf(mRunnable);
unscheduleSelf(mExitRunnable);
scheduleSelf(mExitRunnable, SystemClock.uptimeMillis());
}
//退出动画进度值
private float mExitProgress = 0;
//动画查看器,用于实现从慢到快的效果
private Interpolator mExitInterpolator = new AccelerateInterpolator(2);
private Runnable mExitRunnable = new Runnable() {
@Override
public void run() {
mExitProgress = mExitProgress + 0.01f;
if (mExitProgress > 1) {
onExitDone();
return;
}
float realProgress = mExitInterpolator.getInterpolation(mExitProgress);
onExitProgress(realProgress);
scheduleSelf(this, SystemClock.currentThreadTimeMillis() + 16);
}
};
private void onExitDone() {
}
/*
退出动画刷新方法
*/
private void onExitProgress(float progress) {
// float maxRadius = Math.max(mCenterPointX,mCenterPointY);
// mRippleRadios = getProgresValue(maxRadius,0f,progress);
int alpha = (int) getProgresValue(64, 0, progress);
mBackgroundColor = changeColorAlpha(0x00000000, alpha);
mPaintAlpha = (int) getProgresValue(255, 0, progress);
invalidateSelf();
}
private float getProgresValue(float start, float end, float progress) {
return start + (end - start) * progress;
}
//按下时的点
private float mDonePointX, mDonePointY;
//控件的中心点
private float mCenterPointX, mCenterPointY;
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mCenterPointX = bounds.centerX();
mCenterPointY = bounds.centerY();
}
private int changeColorAlpha(int color, int alpha) {
int r = (color >> 16) & 0xFF;
int g = (color >> 8) & 0xFF;
int b = (color) & 0xFF;
return (alpha << 24) | (r << 16) | (g << 8) | b;
}