自定義View——水波紋效果
阿新 • • 發佈:2018-12-15
我儘量不打錯別字,用詞準確,不造成閱讀障礙。
本文實現一個水波紋狀的自定義View,很簡單的程式碼,沒什麼計算難度。
效果如下:
程式碼:
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();
這個動畫效果其實可以用其他更高階的方式實現,這裡只是寫出一種方式,記錄的同時可以給大家一下思路,有問題歡迎評論。