自定义View实现水波纹的效果
记录下来,以后多看看
温故而知新
效果图就是这样
这是 在自定义View类写的代码
package com.example.ripplebackdemo;
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.ImageView;
public class RippleView extends ImageView {
private final static long INTERVAL = 400;// 每个波纹间隔(毫秒)
private final static long SPEED = 6;// 波纹移动速度 数值越大越慢
private final static float IMGAE_SCALE = 0.25f;// 按钮占整个区域的大小比例 值越大按钮越大
private boolean run;// 动画开始标识
private long startTime;// 动画开始时间
private long MAX_RADIUS;
private Paint paint;// 波纹属性
private Paint imagePaint;// 按钮属性
private ArrayList<Ripple> rippleList; //波纹集合
private Bitmap image;
private Rect imageRect = new Rect();
private int width;
private int height;
public RippleView(Context context) {
super(context);
init();
}
public RippleView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RippleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
// 初始化paint对象
private void init() {
imagePaint = new Paint();
imagePaint.setAntiAlias(true);
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
rippleList = new ArrayList<RippleView.Ripple>();
image = BitmapFactory.decodeResource(getContext().getResources(),
R.drawable.fy_id_select);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
MAX_RADIUS = Math.max(w, h) / 2;
width = w;
height = h;
imageRect.set((int) (w - w * IMGAE_SCALE) / 2, (int) (h - h
* IMGAE_SCALE), (int) (w + w * IMGAE_SCALE) / 2, h);
}
// 开始动画
public void start() {
run = true;
startTime = System.currentTimeMillis();
postInvalidate();
}
// 结束动画
public void stop() {
if (!run) {
return;
}
rippleList.clear();
run = false;
}
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
if (run) {
long current = System.currentTimeMillis();
long coast = current - startTime;
synchronized (rippleList) {
checkNeedAddCicle(coast);
updateSize(current);
int size = rippleList.size();
for (int i = 0; i < size; i++) {
Ripple ripple = rippleList.get(i);
if (ripple.canDraw()) {
paint.setAlpha(ripple.alpha);
canvas.drawCircle(ripple.x, ripple.y, ripple.radius,
paint);
}
}
}
this.postInvalidateDelayed(5);
}
if (image != null) {
canvas.setDrawFilter(new PaintFlagsDrawFilter(0,
Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
canvas.drawBitmap(image, null, imageRect, imagePaint);
}
}
// 更新波纹半径
private void updateSize(long current) {
int size = rippleList.size();
for (int i = 0; i < size; i++) {
Ripple ripple = rippleList.get(i);
long coast = current - ripple.addTime;
ripple.y = height - height * IMGAE_SCALE / 2 - coast / SPEED;
ripple.radius = height * IMGAE_SCALE / 2 + coast / SPEED;
ripple.alpha=(int) (300 - ripple.radius * 2 / height
* 255);
}
}
// 检查是否需要增加新的波纹
private void checkNeedAddCicle(long coast) {
int count = (int) (coast / INTERVAL);
if (count > rippleList.size()) {
addRipple();
}
}
// 增加一个波纹
private void addRipple() {
Ripple ripple = new Ripple();
ripple.x = width / 2;
ripple.y = height - height * IMGAE_SCALE / 2;
ripple.radius = height * IMGAE_SCALE / 2;
ripple.addTime = System.currentTimeMillis();
rippleList.add(ripple);
}
//波纹对象
class Ripple {
public float x;//x坐标
public float y;//y坐标
public float radius;//半径
public long addTime;//开始时间
public int alpha;//透明像素
// 波纹是否需要显示
public boolean canDraw() {
if (radius > MAX_RADIUS) {
// 超过最大尺寸则不画出来
return false;
}
return true;
}
}
}
布局文件需要的 很简单
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
tools:context=".MainActivity" >
<com.example.ripplebackdemo.RippleView
android:id="@+id/centerImage"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerInParent="true" />
</RelativeLayout>
Activity 文件中调用
public class MainActivity extends Activity {
RippleView button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (RippleView) findViewById(R.id.centerImage);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
button.start();
//10秒后停止
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
button.stop();
}
}, 10000);
}
});
}
}