看到android 5.0有一个按钮点击效果非常棒,先来看效果图:
但是这种效果只能在5.0的系统上有效果,如何在低版本上实现呢?
这种效果网上也有人实现了,
blog 地址http://blog.csdn.net/singwhatiwanna/article/details/42614953
ok,直接进入主题,
要实现这种动画效果也不难,原理可以用一句话概括:就是,在我们按下view的时候,从按下的位置开始绘制圆,圆的半径一直增大,直至把View全部覆盖掉。
通过实现原理我们可以分析出,要实现这种效果,需要重写onDraw方法,onTouchEvent方法,如果有必要还需要通过onMeasure方法来获取View的size
1、onDraw方法,就是不断的绘制圆,这里需要循环调用,
2、onTouchEvent方法:通过MotionEvent.ACTION_DOWN和MotionEvent.ACTION_UP做相应的操作并触发onDraw方法
3、onMeasure计算View的size,通过size加上MotionEvent.ACTION_DOWN起始点计算出圆的最大半径
代码实现:
保存view的大小,用于计算绘制 圆的最大半径
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
}
手指按下view的时候,计算按下点的位置,并触发onDraw方法
public boolean onTouchEvent(MotionEvent event) {
final int action = MotionEventCompat.getActionMasked(event);
switch (action) {
case MotionEvent.ACTION_DOWN: {
mDrawFinish = false;
int index = MotionEventCompat.getActionIndex(event);
int eventId = MotionEventCompat.getPointerId(event, index);
if (eventId != -1) {
mInitX = (int) MotionEventCompat.getX(event, index);
mInitY = (int) MotionEventCompat.getY(event, index);
updateDrawData();
ViewCompat.postInvalidateOnAnimation(this);
}
return true;
}
更新数据,重新计算圆的半径和步长
private void updateDrawData() {
int radiusLeftTop = (int) Math.sqrt((mRect.left - mInitX) * (mRect.left - mInitX) +
(mRect.top - mInitY) * (mRect.top - mInitY));
int radiusRightTop = (int) Math.sqrt((mRect.right - mInitX) * (mRect.right - mInitX) +
(mRect.top - mInitY) * (mRect.top - mInitY));
int radiusLeftBottom = (int) Math.sqrt((mRect.left - mInitX) * (mRect.left - mInitX) +
(mRect.bottom - mInitY) * (mRect.bottom - mInitY));
int radiusRightBottom = (int) Math.sqrt((mRect.right - mInitX) * (mRect.right - mInitX) +
(mRect.bottom - mInitY) * (mRect.bottom - mInitY));
mRadius = getMax(radiusLeftTop, radiusRightTop, radiusLeftBottom, radiusRightBottom);
mStep = mRadius/mCycle;
}
手指抬起的时候需要做的操做,把步长加大2.5倍,加快圆的绘制
@Override
public boolean onTouchEvent(MotionEvent event) {
final int action = MotionEventCompat.getActionMasked(event);
switch (action) {
//..
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mStep = (int) (2.5f * mStep);
mDrawBack = true ;
break;
}
return super.onTouchEvent(event);
}
最后就是绘制圆了,这里需要做判断,如果当前绘制的圆半径没有达到我们计算的最大半径,需要继续绘制
@Override
protected void onDraw(Canvas canvas) {
if (mDrawFinish) {
super.onDraw(canvas);
return;
}
canvas.drawColor(0x08000000);
super.onDraw(canvas);
if (mStep == 0) {
return;
}
mDrawRadius = mDrawRadius + mStep;
if (mDrawRadius > mRadius) {
mDrawRadius = 0;
canvas.drawCircle(mInitX, mInitY, mRadius, mRevealPaint);
mDrawFinish = true;
ViewCompat.postInvalidateOnAnimation(this);
return;
}
canvas.drawCircle(mInitX, mInitY, mDrawRadius, mRevealPaint);
ViewCompat.postInvalidateOnAnimation(this);
}
整个效果的实现,相对比较简单,只是很无聊的一直绘圆。
最后要说明一点,如果你想对TextView做这种效果,则继承TextView即可,LinearLayout等其他组件同理;
demo下载