您的位置:首页 > 移动开发 > Android开发

自定义view实现android5.0 ripple效果

2015-11-14 21:40 507 查看
思路:

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



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

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

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="RippleView">
<attr name="rb_rippleColor" format="color" />
<attr name="rb_alphaFactor" format="float" />
</declare-styleable>
</resources>


       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

         
        
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: