1. 程式人生 > >自定義View——水波紋效果

自定義View——水波紋效果

我儘量不打錯別字,用詞準確,不造成閱讀障礙。

本文實現一個水波紋狀的自定義View,很簡單的程式碼,沒什麼計算難度。

效果如下:

waveView

程式碼:

1.首先在values下的attrs中新增如下自定義屬性:

 <declare-styleable name="MyWaveView">
        <attr name="waveColor" format="color" />
        <attr name="oneWaveDuration" format="integer" />
        <attr name="newWaveSpeed"
format="integer" />
<attr name="textContent" format="string|reference" /> </declare-styleable>

2.自定義View的主要程式碼:

public class MyWaveView extends View {
    private int mInitialRadius;           //初始波紋大小
    private int mMaxRadius;               //最大波紋大小
    private int mOneWaveDuration =
5000; //一個波紋從建立到消失時間為5秒 private int mNewWaveSpeed = 750; //新的波紋建立的速度為750毫秒 private String text; private Rect textBound = new Rect(); private ArrayList<Circle> mCircleList = new ArrayList<>(); private Paint mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); //畫圓的畫筆 private
Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); //寫字的畫筆 private Interpolator mInterpolator = new LinearInterpolator(); private long mLastCreateTime; private int waveColor; private Runnable mCreateCircle = new Runnable() { @Override public void run() { newCircle(); postDelayed(mCreateCircle, mNewWaveSpeed); //迴圈呼叫runable,持續向list新增資料來源 } }; public MyWaveView(Context context) { this(context, null); } public MyWaveView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public MyWaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(attrs); } //獲取屬性 public void init(AttributeSet attrs) { TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MyWaveView); waveColor = typedArray.getColor(R.styleable.MyWaveView_waveColor, 0); text = typedArray.getString(R.styleable.MyWaveView_textContent); mOneWaveDuration = typedArray.getInteger(R.styleable.MyWaveView_oneWaveDuration, 5000); mNewWaveSpeed = typedArray.getInteger(R.styleable.MyWaveView_newWaveSpeed, 750); typedArray.recycle(); } @Override protected void onDraw(Canvas canvas) { Iterator<Circle> iterator = mCircleList.iterator(); mTextPaint.setTextSize(getResources().getDimension(R.dimen.textsp)); mTextPaint.setColor(Color.WHITE); mTextPaint.setAntiAlias(true); mTextPaint.setStyle(Paint.Style.FILL); mTextPaint.getTextBounds(text, 0, text.length(), textBound); mCirclePaint.setColor(waveColor); mCirclePaint.setAntiAlias(true); mCirclePaint.setStyle(Paint.Style.FILL); mCirclePaint.setAlpha((int) (255 * 0.3)); mInitialRadius = getWidth() / 7; //設定初始波紋的大小 mMaxRadius = getWidth() / 2; //設定最大波紋的大小 while (iterator.hasNext()) { Circle circle = iterator.next(); float radius = circle.getCurrentRadius(); canvas.drawText(text, getWidth() / 2 - textBound.width() / 2, getHeight() / 2, mTextPaint); if (System.currentTimeMillis() - circle.mCreateTime < mOneWaveDuration) { mCirclePaint.setAlpha(circle.getAlpha()); //真正畫波紋 canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, mCirclePaint); } else { iterator.remove(); } if (mCircleList.size() > 0) { postInvalidateDelayed(10);//每10毫秒重新整理view,讓動畫看起來連貫 } } } private void newCircle() { long currentTime = System.currentTimeMillis(); if (currentTime - mLastCreateTime >= mNewWaveSpeed) { Circle circle = new Circle(); mCircleList.add(circle); invalidate(); mLastCreateTime = currentTime; } } public void start() { mCreateCircle.run(); } public class Circle { private long mCreateTime; Circle() { mCreateTime = System.currentTimeMillis(); } public int getAlpha() { float percent = (getCurrentRadius() - mInitialRadius) / (mMaxRadius - mInitialRadius); return (int) ((int) (255 - mInterpolator.getInterpolation(percent) * 255) * 0.3); } public float getCurrentRadius() { float percent = (System.currentTimeMillis() - mCreateTime) * 1.0f / mOneWaveDuration; return mInitialRadius + mInterpolator.getInterpolation(percent) * (mMaxRadius - mInitialRadius); } } }

3.xml佈局檔案中:

 <com.teststudy.longl.myapplication3.Views.MyWaveView
        android:id="@+id/wv_my_test"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        app:newWaveSpeed="750"
        app:oneWaveDuration="5000"
        app:textContent="進行中..."
        app:waveColor="@color/colorPrimaryDark" />

4.Activity中:

MyWaveView myWaveView = findViewById(R.id.wv_my_test);
myWaveView.start();

這個動畫效果其實可以用其他更高階的方式實現,這裡只是寫出一種方式,記錄的同時可以給大家一下思路,有問題歡迎評論。