美文网首页Android开发程序员Android知识
类似window7的气泡屏保的自定义view

类似window7的气泡屏保的自定义view

作者: 不识水的鱼 | 来源:发表于2017-12-13 16:43 被阅读104次

    这个只能做来玩玩儿,没有太多的使用价值,看着好玩,有密集恐惧症的就不要玩儿了

    在实现上主要使用了两个自定义view

    一个画圆(使用图片也是可以的)

    一个写位置逻辑

    github链接

    上图

    不重叠气泡
    重叠气泡

    其中有两种状态,一种可以重叠,一种不能重叠。类似Window 7 气泡的屏保。

    一个使用两个自定义view,一个就是一个圆圈,一个实现动画,边界计算

    圆圈的view
    计算距离的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;
            }
        }

    相关文章

      网友评论

        本文标题:类似window7的气泡屏保的自定义view

        本文链接:https://www.haomeiwen.com/subject/vkkzixtx.html