效果图
思想
1.绘制气泡
随机xy轴,r半径,速度,随机xy方向(方向就是x和y加减同一个随机偏移量),随机透明度
2.气泡移动和复用气泡
在原来的xy+=或者-=偏移量,每一次便宜判断xy是否超过屏幕宽度和高度,超过就重新随机生成
3.代码实现
制气泡效果
public class QiPao extends View {
public Paint paint;
public DisplayMetrics displayMetrics;
public QiPao(Context context) {
this(context,null);
}
public QiPao(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
displayMetrics = context.getResources().getDisplayMetrics();
init();
}
public QiPao(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
Timer timer;
@SuppressLint("ResourceAsColor")
public void init(){
paint = new Paint();
paint.setAntiAlias(true);
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
postInvalidate();//在子线程中执行 postInvalidate()会使onDrow()方法得到执行
}
}, 300, 10);
for (int i = 0; i <100 ; i++) {
QiPaoPoin qiPaoPoin = new QiPaoPoin();
//点的位置
qiPaoPoin.setX(random.nextFloat()*displayMetrics.widthPixels);
qiPaoPoin.setY(random.nextFloat()*displayMetrics.heightPixels);
int v = random.nextInt(2)+1;
qiPaoPoin.setxSke(random.nextFloat()*((v==1)?2:-2));
v = random.nextInt(2)+1;
qiPaoPoin.setySke(random.nextFloat()*((v==1)?2:-2));
qiPaoPoin.setDiaph(random.nextInt(100)+100);
qiPaoPoin.setSpeet(random.nextFloat());
//圆的半径
qiPaoPoin.setRadius(random.nextInt(170)+30);
list.add(qiPaoPoin);
}
}
@SuppressLint("NewApi")
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
aaa();
list.forEach((element)->{
paint.setARGB(element.getDiaph(),255,255,255);
canvas.drawCircle(element.getX(),element.getY(),element.getRadius(),paint);
});
}
List<QiPaoPoin> list =new ArrayList<>();
Random random = new Random();
float yske,xske;//xy轴偏移量
int radius;//半径
public void aaa(){
for (int i = 0; i <list.size() ; i++) {
yske = list.get(i).getySke();//y偏移
xske = list.get(i).getxSke();//x偏移
radius = list.get(i).getRadius();//半径
//如果不是按住就解锁
if(!isDown){
list.get(i).setLock(false);
}
if(list.get(i).isLock()){
if(isMove){//跟随鼠标移动
list.get(i).setY(lastY);
list.get(i).setX(lastX);
}
}else {
//点击不动
if(isDown&&(lastX<=list.get(i).getX()+list.get(i).getRadius()&&lastX>=list.get(i).getX()-list.get(i).getRadius())&&(lastY<=list.get(i).getY()+list.get(i).getRadius()&&lastY>=list.get(i).getY()-list.get(i).getRadius())){
if(isMove){//跟随鼠标移动
list.get(i).setY(lastY);
list.get(i).setX(lastX);
list.get(i).setLock(true);
}
}else {
//这里才是真正的复用 和实现移动气泡
if(list.get(i).getY()-(yske+radius)<displayMetrics.heightPixels&&list.get(i).getY()-(yske+radius)>-radius*2){
list.get(i).setY(list.get(i).getY()+yske);
}else {//结束完随机y轴出现 和任意方向飘动
list.get(i).setY(random.nextFloat()*displayMetrics.heightPixels);
// int v = random.nextInt(2)+1;
// list.get(i).setxSke(random.nextFloat()*((v==1)?3:-3));
// v = random.nextInt(2)+1;
// list.get(i).setySke(random.nextFloat()*((v==1)?3:-3));
}
if(list.get(i).getX()-(xske+radius)<displayMetrics.widthPixels&&list.get(i).getX()-(xske+radius)>-radius*2){
list.get(i).setX(list.get(i).getX()+xske);
}else{//结束完随机x轴出现 和任意方向飘动
list.get(i).setX(random.nextFloat()*displayMetrics.widthPixels);
int v = random.nextInt(2)+1;
list.get(i).setxSke(random.nextFloat()*((v==1)?2:-2));
v = random.nextInt(2)+1;
list.get(i).setySke(random.nextFloat()*((v==1)?2:-2));
}
}
}
}
}
public int lastX,lastY;
public boolean isDown,isMove;
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
// 记录触摸点坐标
lastX = x;
lastY = y;
isDown = true;
break;
case MotionEvent.ACTION_MOVE:
lastX = x;
lastY = y;
isMove = true;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
isDown = false;
isMove = false;
break;
}
return true;
}
public void dis(){
timer.cancel();
}