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) {

        }
    });
}兩種方式對比,個人覺得自定義體驗更好,動畫更簡單

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