android ripple 大小,Android Ripple 按钮水波纹效果(二)优化

2015-05-01

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

有两处需要优化的 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;12345678

全部实现代码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.

*/public class RippleLinearLayout extends LinearLayout {

/*起始点*/

private int mInitX;    private int mInitY;    private float mCurrentX;    private float mCurrentY;    /*高度和宽度*/

private int mWidth;    private int mHeight;    /*绘制的半径*/

private float mRadius;    private float mStepRadius;    private float mStepOriginX;    private float mStepOriginY;    private float mDrawRadius;    private boolean mDrawFinish;    private final int DURATION = 150;    private final int 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);

}    private void initView(Context context) {

mRevealPaint.setColor(0x25000000);

mCycle = DURATION / FREQUENCY;        final float density = getResources().getDisplayMetrics().density ;

mCycle = (density*mCycle);

mDrawFinish = true;

}    @Override

protected void onDraw(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);

}    @Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

mRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());

}    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);

/*最大半径*/

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;

}    @Override

public boolean onTouchEvent(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);

}    private int getMax(int... radius) {        if (radius.length == 0) {            return 0;

}        int max = radius[0];        for (int m : radius) {            if (m > max) {

max = m;

}

}        return max;

}    @Override

public boolean performClick() {

postDelayed(new Runnable() {            @Override

public void run() {

RippleLinearLayout.super.performClick();

}

}, 150);        return true;

}

}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183

效果图对比

851ee6e406f040baa4f95c06cbb203c8.gif

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值