类似window7的气泡屏保的自定义view
2017-12-13 本文已影响104人
不识水的鱼
这个只能做来玩玩儿,没有太多的使用价值,看着好玩,有密集恐惧症的就不要玩儿了
在实现上主要使用了两个自定义view
,
一个画圆(使用图片也是可以的)
一个写位置逻辑
上图
不重叠气泡重叠气泡
其中有两种状态,一种可以重叠,一种不能重叠。类似Window 7 气泡的屏保。
一个使用两个自定义view,一个就是一个圆圈,一个实现动画,边界计算
在实现上画圆的view
简单到其实就一个方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setStyle(painStyle);
mPaint.setColor(color);
mPaint.setStrokeWidth(width);
canvas.drawCircle(mWidth/2,mHeight/2,mWidth/2-width*2,mPaint);
}
就是一个圆圈,这里其实使用图片简单粗暴,啥也不用写,只是为了获取一个圆而已
下一个view
多一点逻辑
如下:
/**
* add view 获取到view
* @param view
*/
public void addBallsView(RainBallView view){
Balls balls=new Balls();
balls.setRainBallView(view);
balls.setXtag(movePos);
balls.setYtag(movePos);
// balls.getRainBallView().setX(200/((int)(Math.random()*9)+1));
// balls.getRainBallView().setY(200/((int)(Math.random()*9)+1));
mViewList.add(balls);
addView(view);
}
当然了有对象最好。有一个Ball的对象实现
逻辑代码如下
public void startMove(){
for (int i = 0; i < mViewList.size(); i++) {
//保证每一个小球的唯一性,使用对象
Balls rainBallView= mViewList.get(i);
//宽度判断
// Log.i("x-->",rainBallView.getRainBallView().getX()+"");
// Log.i("y-->",rainBallView.getRainBallView().getY()+"");
// Log.i("w-->",screenWidth-rainBallView.getRainBallView().getWidth()+"");
if(rainBallView.getRainBallView().getX()<0||rainBallView.getRainBallView().getX()>=screenWidth-rainBallView.getRainBallView().getWidth()){
rainBallView.setXtag(-rainBallView.getXtag());
//随机数出现不能一次将值的正负改变,所以取最大值,否则会在边界上抖
//×2为了避免是在边界碰撞,位置移动没办法移出来
randomX=rainBallView.getXtag()*2;
}else {
randomX=(int)(Math.random()*rainBallView.getXtag());
}
//高度判断
if(rainBallView.getRainBallView().getY()<0||rainBallView.getRainBallView().getY()>=screenHeight-rainBallView.getRainBallView().getHeight()){
rainBallView.setYtag(-rainBallView.getYtag());
//随机数出现不能一次将值的正负改变,所以取最大值
//×2为了避免是在边界碰撞,位置移动没办法移出来
randomY=rainBallView.getYtag()*2;
}else {
randomY=(int)(Math.random()*rainBallView.getYtag());
}
//判断两个小球之间的距离,如果相聚小于两个的半径值的两倍,则接触了,就反弹
for (int j = 0; j < mViewList.size(); j++) {
//排除自己
if(j!=i&&isReward){
//x方向的距离的绝对值
int xTox=(int) Math.abs(rainBallView.getRainBallView().getX()-mViewList.get(j).getRainBallView().getX());
//y方向的距离的绝对值
int yToy= (int) Math.abs(rainBallView.getRainBallView().getY()-mViewList.get(j).getRainBallView().getY());
//两个球的距离
int ballToball=rainBallView.getRainBallView().getWidth();
// Log.i("xDis",xTox+"-"+ballToball+"-"+yToy);
//x和y方向的距离的绝对值
if(xTox<ballToball&&yToy<ballToball){
//当前的小球x方向取反
rainBallView.setXtag(-rainBallView.getXtag());
//随机数出现不能一次将值的正负改变,所以取最大值
//×2两个小球一起移动,位移是两倍
if(rainBallView.getXtag()>0){
randomX=(ballToball-xTox);
}else {
randomX=-(ballToball-xTox);
}
randomX= rainBallView.getXtag()*2;
//当前的小球y方向取反
rainBallView.setYtag(-rainBallView.getYtag());
//随机数出现不能一次将值的正负改变,所以取最大值
//×2为了避免是在边界碰撞,位置移动没办法移出来
if(rainBallView.getYtag()>0){
randomY=(ballToball-yToy);
}else {
randomY=-(ballToball-yToy);
}
//×2两个小球一起移动,位移是两倍
randomY=rainBallView.getYtag()*2;
mViewList.get(j).setXtag(-mViewList.get(j).getXtag());
mViewList.get(j).setYtag(-mViewList.get(j).getYtag());
}
}
}
rainBallView.getRainBallView().setX(rainBallView.getRainBallView().getX()+randomX);
rainBallView.getRainBallView().setY(rainBallView.getRainBallView().getY()+randomY);
}
}
注释尽量写的多一点,修改过部分,有一两注释句可能位置不对,没啥大的影响
对于多次的绘制view,使用了handler
实现的延迟操作,实现运动的效果
private Handler mHandler=new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what==1){
mHandler.sendEmptyMessageDelayed(1,5);
startMove();
}
}
};
这也是比肩常用的方式。很多时候延迟都会用到handler
实现。
使用,考入两个自定义view,直接使用
只要是计算边界的位置,保证小球不能出界,出界就让它往回走,分别判断了宽高的位置
if(rainBallView.getRainBallView().getX()<0||rainBallView.getRainBallView().getX()>=screenWidth-rainBallView.getRainBallView().getWidth()){
rainBallView.setXtag(-rainBallView.getXtag());
//随机数出现不能一次将值的正负改变,所以取最大值,否则会在边界上抖
//×2为了避免是在边界碰撞,位置移动没办法移出来
randomX=rainBallView.getXtag()*2;
}else {
randomX=(int)(Math.random()*rainBallView.getXtag());
}
//高度判断
if(rainBallView.getRainBallView().getY()<0||rainBallView.getRainBallView().getY()>=screenHeight-rainBallView.getRainBallView().getHeight()){
rainBallView.setYtag(-rainBallView.getYtag());
//随机数出现不能一次将值的正负改变,所以取最大值
//×2为了避免是在边界碰撞,位置移动没办法移出来
randomY=rainBallView.getYtag()*2;
}else {
randomY=(int)(Math.random()*rainBallView.getYtag());
}
还有就是判断当前绘制的小球不能和其他的小球的距离小于两个小球的半径和,也就是直径的距离,由x和y两个方向,分别判断,实现位置的判断
//x方向的距离的绝对值
int xTox=(int) Math.abs(rainBallView.getRainBallView().getX()-mViewList.get(j).getRainBallView().getX());
//y方向的距离的绝对值
int yToy= (int) Math.abs(rainBallView.getRainBallView().getY()-mViewList.get(j).getRainBallView().getY());
//两个球的距离
int ballToball=rainBallView.getRainBallView().getWidth();
// Log.i("xDis",xTox+"-"+ballToball+"-"+yToy);
//x和y方向的距离的绝对值
if(xTox<ballToball&&yToy<ballToball){
// .......
}
实现了判断,只剩下位置的后移。和方向的反转,这样就是反弹效果,
其余的样式参数也就只是简单的设置一下就可以了
xml布局中
<com.yk.myselfview.views.RainBallLayout android:layout_width="match_parent"
android:id="@+id/rain_ball_layout"
android:layout_height="match_parent">
</com.yk.myselfview.views.RainBallLayout>
页面
public class BallsViewActivity extends AppCompatActivity {
private RainBallLayout mRainBallLayout;
private List<Integer> mListColor=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_balls_view);
mListColor.add(Color.BLUE);
mListColor.add(Color.BLACK);
mListColor.add(Color.GREEN);
mListColor.add(Color.RED);
mListColor.add(Color.CYAN);
mRainBallLayout = (RainBallLayout) findViewById(R.id.rain_ball_layout);
for (int i = 0; i < 1; i++) {
RainBallView rainBallView=getRainBallView();
mRainBallLayout.addBallsView(rainBallView);
//s是否可以相交
mRainBallLayout.isReward(true);
mRainBallLayout.startAmimation();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mRainBallLayout.stopAmimation();
}
public void addBall(View view) {
RainBallView rainBallView = getRainBallView();
mRainBallLayout.addBallsView(rainBallView);
}
@NonNull
private RainBallView getRainBallView() {
Random random=new Random();
int color = random.nextInt(4);
RainBallView rainBallView=new RainBallView(this);
rainBallView.setColors(mListColor.get(color));
rainBallView.setPainStyle(Paint.Style.STROKE);
rainBallView.setWidth(4);
return rainBallView;
}
}