Android 水波纹效果

有两种实现方式,

原文出处:https://blog.csdn.net/tx467220125/article/details/79853303#comments,他的文章是达到一定条件添加一个新的波纹,我修改之后,触发条件为点击手动触发添加。

1.自定义View

通过paint + canvas绘制

public class WaveView extends View {

    private Paint mCenterPaint; //中心圆paint
    private int mRadius = 0; //中心圆半径  默认0
    private Paint mSpreadPaint; //扩散圆paint
    private float centerX;//圆心x
    private float centerY;//圆心y
    private int mMaxRadius = 0; //最大圆半径,默认扩展到屏幕两边
    private List<Integer> spreadRadius = new ArrayList<>();//扩散圆层级数,元素为扩散的距离
    private List<Integer> alphas = new ArrayList<>();//对应每层圆的透明度
    private int mAlphaScale = 3;

    public WaveView(Context context) {
        this(context, null);
    }

    public WaveView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WaveView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
//        radius = (int) getResources().getDisplayMetrics().density * 50;
        mMaxRadius = getResources().getDisplayMetrics().widthPixels / 2;
        int centerColor = context.getResources().getColor(R.color.colorPrimaryDark);
        int spreadColor = context.getResources().getColor(R.color.colorPrimaryDark);

        mCenterPaint = new Paint();
        mCenterPaint.setColor(centerColor);
        mCenterPaint.setAntiAlias(true);

        mSpreadPaint = new Paint();
        mSpreadPaint.setAntiAlias(true);
        mSpreadPaint.setAlpha(255);
        mSpreadPaint.setColor(spreadColor);
    }

    /**
     * 设置相关参数
     *
     * @param nradius     中心园半径,起始位置
     * @param maxwidth    最大扩展距离
     * @param alphaScale  每次透明度变化的大小
     * @param centerColor 中心园颜色
     * @param spreadColor 扩散颜色
     */
    public void setparams(int nradius, int maxwidth, int alphaScale, int centerColor, int spreadColor) {
        mRadius = nradius;
        if (maxwidth < nradius) {
            mMaxRadius = nradius;
        } else {
            mMaxRadius = maxwidth;
        }
        mAlphaScale = alphaScale;
        mCenterPaint.setColor(centerColor);
        mSpreadPaint.setColor(spreadColor);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        centerX = w / 2;
        centerY = h / 2;
    }

    public void click() {
        if (alphas != null) {
            alphas.add(255);
        }
        if (spreadRadius != null)
            spreadRadius.add(0);
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (spreadRadius.isEmpty()) {
            return;
        }
        for (int i = 0; i < spreadRadius.size(); i++) {//一层一层绘制渐变扩散
            int alpha = alphas.get(i);
            mSpreadPaint.setAlpha(alpha);
            int width = spreadRadius.get(i);
            //绘制扩散的圆
            canvas.drawCircle(centerX, centerY, mRadius + width, mSpreadPaint);

            //每次扩散圆半径递增,圆透明度递减
            if (alpha > 0) {
                alpha = alpha - mAlphaScale > 0 ? alpha - mAlphaScale : 0;
                alphas.set(i, alpha);
                spreadRadius.set(i, width + (mMaxRadius - mRadius) * mAlphaScale / 255);
            }
        }
        //当最外层扩散圆半径达到最大半径时添加新扩散圆
        if (spreadRadius.get(spreadRadius.size() - 1) >= mMaxRadius) {
            //扩散到最大  移除最外圈
            alphas.remove(0);
            spreadRadius.remove(0);
        }
        invalidate();
//        postInvalidateDelayed(10);//不能延时  不然会有卡顿感
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            click();
        }
        return super.onTouchEvent(event);
    }
}

这个是自定义view,添加到布局中,点击即可看见水波纹

2.动画

这里采用动态添加和动画集合的方式实现

private RelativeLayout layoutAnimation;
private float mAnimationScaleSize = 0;
/**
 * 启动一个水波纹动画
 */
private void startAnimation() {
    int nWidth = (int) getResources().getDisplayMetrics().density * 50;//动画view初始大小
    if (mAnimationScaleSize == 0) {
        //根据宽高,计算缩放的比例
        int max = layoutAnimation.getWidth() < layoutAnimation.getHeight() ?
                layoutAnimation.getHeight() : layoutAnimation.getWidth();
        mAnimationScaleSize = max * 1.0f / nWidth;
    }
    final ImageView nImg = new ImageView(WaveActivity.this);
    layoutAnimation.addView(nImg);//动态添加
    RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(nWidth, nWidth);
    param.addRule(RelativeLayout.CENTER_IN_PARENT);//居中
    nImg.setImageResource(R.drawable.wave_bg);//背景
    nImg.setLayoutParams(param);
    AnimationSet set = new AnimationSet(true);
    ScaleAnimation sAni = new ScaleAnimation(1.0f, mAnimationScaleSize, 1.0f, mAnimationScaleSize,
            ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
            ScaleAnimation.RELATIVE_TO_SELF, 0.5f);//缩放动画
    AlphaAnimation aAni = new AlphaAnimation(1.0f, 0.0f);//透明度动画
    sAni.setDuration(1000);
    set.setDuration(1000);
    set.addAnimation(sAni);
    set.addAnimation(aAni);
    nImg.startAnimation(set);//开启动画
    set.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {

        }

        @Override
        public void onAnimationEnd(Animation animation) {
            layoutAnimation.post(new Runnable() {
                @Override
                public void run() {
                    nImg.clearAnimation();
                    layoutAnimation.removeView(nImg);
                    //动画完成之后  清除,移除
                }
            });
        }

        @Override
        public void onAnimationRepeat(Animation animation) {

        }
    });
}两种方式对比,个人觉得自定义体验更好,动画更简单

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章