android自定义view实现5.0 Ripple效果

思路:

      重写Button在onTouchEvent中监听action_down事件,然后播放一个属性动画,动态的改变圆圈的半径,这样就产生了波纹效果



      


       1.首先是RippleButton直接继承自Button

       2.在attrs.xml中自定义两个属性一个是波纹的颜色rb_rippleColor,一个是波纹的透明度rb_alphaFactor;



    
        
        
    

       3.在构造函数中初始化这两个属性

public RippleButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setAlpha(100);
        mPath = new Path();

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RippleView);
        mRippleColor = a.getColor(R.styleable.RippleView_rb_rippleColor, mRippleColor);
        mAlphaFactor = a.getFloat(R.styleable.RippleView_rb_alphaFactor, mAlphaFactor);
        if (mAlphaFactor > 0 && mAlphaFactor <= 1) {
            mPaint.setAlpha((int) Math.floor(255 * mAlphaFactor));
        }
        a.recycle();
    }

        4.重写onTouchEvent

    

 public boolean onTouchEvent(MotionEvent event) {
        boolean superResult = super.onTouchEvent(event);
        mDownX = event.getX();
        mDownY = event.getY();
        if (isEnabled() && !isAnimatorPlaying && event.getActionMasked() == MotionEvent.ACTION_DOWN) {
            //calculate ripple's radius
            float offsetX = Math.max(mDownX - getLeft(), getRight() - mDownX);
            float offsetY = Math.max(mDownY - getTop(), getBottom() - mDownY);
            mMaxRadius = (float) Math.sqrt(Math.pow(offsetX, 2) + Math.pow(offsetY, 2));
            ObjectAnimator mScaleAnimator = ObjectAnimator.ofFloat(this, "radius", 0, mMaxRadius);
            mScaleAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                    isAnimatorPlaying = true;
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    setRadius(0);
                    isAnimatorPlaying = false;
                    if (onRippleFinished != null) {
                        onRippleFinished.onRippleFinished(RippleButton.this);
                    }
                }

                @Override
                public void onAnimationCancel(Animator animation) {
                    isAnimatorPlaying = false;
                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });
            mScaleAnimator.setInterpolator(new AccelerateInterpolator());
            mScaleAnimator.setDuration(500);
            mScaleAnimator.start();
        }
        return superResult;

    }
这里边主要是对手指按下这个事件作出了相应,给一个属性动画,也就是对半径作出改变,下面一个重要的方法就是setRadius(float radius)

        5.实现setRadius方法

 protected void setRadius(float radius) {
        mMaxRadius = radius;
        if (radius > 0) {
            RadialGradient mRadialGradient = new RadialGradient(mDownX, mDownY, radius, adjustAlpha(mRippleColor, mAlphaFactor), mRippleColor, Shader.TileMode.MIRROR);
            mPaint.setShader(mRadialGradient);
        }
        invalidate();
    }
这里面是根据属性动画里不断传递过来的半径,对RadialGradient不断的改变其大小,然后重新绘制真个view


         6.更新view

protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (isInEditMode()) {
            return;
        }

        canvas.save(Canvas.CLIP_SAVE_FLAG);

        mPath.reset();
        mPath.addCircle(mDownX, mDownY, mMaxRadius, Path.Direction.CW);
        canvas.clipPath(mPath);

        canvas.restore();
        canvas.drawCircle(mDownX, mDownY, mMaxRadius, mPaint);
    }
这里面主要就是根据panint画出一个圆,这样就实现了ripple效果啦

      

         7.最后是给动画结束添加一个回调函数

  

public interface OnRippleFinished {
        void onRippleFinished(View rippleButton);
    }
public void setOnRippleFinished(OnRippleFinished onRippleFinished) {
        this.onRippleFinished = onRippleFinished;
    }



源码地址:https://github.com/zlidentify/RippleButton

参考实现:https://github.com/siriscac/RippleView

         

        

你可能感兴趣的:(android)