我尽量不打错别字,用词准确,不造成阅读障碍。
本文实现一个水波纹状的自定义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();
这个动画效果其实可以用其他更高端的方式实现,这里只是写出一种方式,记录的同时可以给大家一下思路,有问题欢迎评论。
集合了一些简单自定义View的github地址:
https://github.com/longlong-2l/MySelfViewDemo
很简单,没有太多高深的用法,适合学习入门。