Android Ripple 按钮水波纹效果(二)优化

上一篇中我们讲了自定义ripple 水波纹效果,先来回顾一下效果吧!

看了以后感觉没甚么问题,我一开始也觉得很满意了,那好,我们拿Android 5.0自带的效果来对比一下

发现了不同之处没?点击中间的时候是看不出什么区别,但是点击两边的时候,就很明显了,我们自定义的效果,波纹向两边同速度的扩散,所以就会出现,如果点击点不在中心的时候,距离短的一边波纹先到达,而距离长的一边后到达,不能同时到达边缘!而系统自带的则不存在这种情况,所以这是一个优化点;另一个优化点是:我们自定义的效果,在波纹全部覆盖以后,按钮的选中效果没了。

有两处需要优化的 1、实现不管是否点击中间点都能实现波纹同步到达边缘 2、当手指未松开时,选中效果不消失

实现: 第二点好实现,我们主要讲一下第一点, 第一点我们观察系统的效果,看似两边速度不一致导致的,其实我们知道实现原理的话,很容易想到,它是不断改变圆的圆心来实现,我们上一篇中的实现方法是圆形固定,,就是在我们手指按下的位置,而不断改变半径来实现, 很明显,这里也需要改变半径来实现,我记得我们上一篇中半径的最大值是需要计算,而这种效果是不需要计算的,因为其最大值是固定的,就是按钮对角线的一半! 确定了半径的最大值,我们还需要确定圆心X、Y的偏移量,相当于步长吧,其圆心从按下的点到按钮正中间的时间因该是和半径从0到最大值的时间保持一致,所以我们可以通过一下代码来获取圆心的偏移量和最大半径。

/*最大半径*/mRadius = (float) Math.sqrt(mRect.width() / 2 * mRect.width() / 2 + mRect.height() / 2 * mRect.height() / 2);/*半径的偏移量*/mStepRadius = mRadius / mCycle;/*圆心X的偏移量*/mStepOriginX = (mRect.width() / 2 – mInitX) / mCycle;/*圆心Y的偏移量*/mStepOriginY = (mRect.height() / 2 – mInitY) / mCycle;

全部实现代码

package eyeclip.myapplication;import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Rect;import android.support.v4.view.MotionEventCompat;import android.support.v4.view.ViewCompat;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.LinearLayout;/** * Created by moon.zhong on 2015/4/27. */{mInitX;private int mInitY;private float mCurrentX;private float mCurrentY;mWidth;private int mHeight;mRadius;private float mStepRadius;private float mStepOriginX;private float mStepOriginY;private float mDrawRadius;private boolean mDrawFinish;DURATION = 150;FREQUENCY = 10;private float mCycle;private final Rect mRect = new Rect();private boolean mPressUp = false;private Paint mRevealPaint = new Paint(Paint.ANTI_ALIAS_FLAG);public RippleLinearLayout(Context context) {super(context);initView(context);}public RippleLinearLayout(Context context, AttributeSet attrs) {super(context, attrs);initView(context);}public RippleLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initView(context);}(Context context) {mRevealPaint.setColor(0x25000000);mCycle = DURATION / FREQUENCY;final float density = getResources().getDisplayMetrics().density ;mCycle = (density*mCycle);mDrawFinish = true;}(Canvas canvas) {if (mDrawFinish) {super.onDraw(canvas);return;}canvas.drawColor(0x15000000);super.onDraw(canvas);if (mStepRadius == 0) {return;}mDrawRadius = mDrawRadius + mStepRadius;mCurrentX = mCurrentX + mStepOriginX;mCurrentY = mCurrentY + mStepOriginY;if (mDrawRadius > mRadius) {mDrawRadius = 0;canvas.drawCircle(mRect.width() / 2, mRect.height() / 2, mRadius, mRevealPaint);mDrawFinish = true;if (mPressUp)invalidate();return;}canvas.drawCircle(mCurrentX, mCurrentY, mDrawRadius, mRevealPaint);ViewCompat.postInvalidateOnAnimation(this);}(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());}() {mRadius = (float) Math.sqrt(mRect.width() / 2 * mRect.width() / 2 + mRect.height() / 2 * mRect.height() / 2);;/*半径的偏移量*/mStepRadius = mRadius / mCycle;/*圆心X的偏移量*/mStepOriginX = (mRect.width() / 2 – mInitX) / mCycle;/*圆心Y的偏移量*/mStepOriginY = (mRect.height() / 2 – mInitY) / mCycle;mCurrentX = mInitX;mCurrentY = mInitY;}(MotionEvent event) {final int action = MotionEventCompat.getActionMasked(event);switch (action) {case MotionEvent.ACTION_DOWN: {mPressUp = false;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();invalidate();}break;}case MotionEvent.ACTION_CANCEL:case MotionEvent.ACTION_UP:mStepRadius = (int) (5 * mStepRadius);mStepOriginX = (int) (5 * mStepOriginX);mStepOriginY = (int) (5 * mStepOriginY);mPressUp = true;invalidate();break;}return super.onTouchEvent(event);}(int… radius) {if (radius.length == 0) {return 0;}int max = radius[0];for (int m : radius) {if (m > max) {max = m;}}return max;}() {postDelayed(new Runnable() {() {RippleLinearLayout.super.performClick();}}, 150);return true;}}

效果图对比

这篇主要是对上一篇的内容进行优化,当然你觉得不优化也行!

demo下载

如果寒暄只是打个招呼就了事的话,那与猴子的呼叫声有什么不同呢?事实上,

Android Ripple 按钮水波纹效果(二)优化

相关文章:

你感兴趣的文章:

标签云: