美文网首页
简单的自定义ViewGroup

简单的自定义ViewGroup

作者: 笔墨Android | 来源:发表于2017-07-23 15:51 被阅读0次

    不怕跌倒,所以飞翔

    今天有了一个感慨:静下心来去学习_总会有收获的!
    其实开始的时候总觉得自己写不出来,但是静下心来了之后,还是写不出来,觉得自己都要放弃了,但是工作就是工作,没有你想不想,一定要去实现,没有别的只有实现,所以必须去弄,希望以后慢慢积累更多知识,不必在这么累。不墨迹了。。。

    其实说实话自定义View没有想象的那么简单,今天就先记录一下吧,如果有时间自己在写一个专题来记录下这些内容吧!

    先上张图片说明一下 效果图

    效果就是点击的时候文字改变颜色,开始播放音乐,转盘开始旋转,再次点击取消旋转!

    首先简单说下自己了解的自定义ViewGroup,其实就是重写onLayout()onMeasure()
    还有就是重写一个返回LayoutParams的方法,以为每个ViewGroup都会返回一个LayoutParams,所以这个方法要重写的!但是看了几篇文章都是返回了一个 MarginLayoutParams(getContext(), attrs);或许是因为MarginLayoutParams可以设置边距的问题吧!

    其实自定义ViewGroup分以下几个步骤:

    • 重写generateLayoutParams()
    • 重写onMeasure()
    • 重写onLayout()

    generateLayoutParams()

    重写这个方法基本上是返回一个对应的LayoutParams,因为每一个ViewGroup都会对应一个LayoutParams,所以必须重写这个方法,我看了很多都是返回一个MarginLayoutParams,至于为什么我也不太清楚,希望有知道的大神不吝赐教;

    onMeasure()

    说到这个方法的话,主要的作用就是当你定义xml时,你只要写了wrap_content的时候才会使用onMeasure();进行测量,绘制真是的尺寸,若你只想用match_parent那么大可以不用去操心这个方法;按照下面的写就可以了。

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            // 计算出所有的childView的宽和高
            measureChildren(widthMeasureSpec, heightMeasureSpec);
            //测量并保存layout的宽高(使用getDefaultSize时,wrap_content和match_perent都是填充屏幕)
            //稍后会重新写这个方法,能达到wrap_content的效果
            setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
                    getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
        }
    

    onLayout()

    这个方法要说的就会多点了,其实这个方法简单讲的话就是测量每一个子View的,然后对位置进行配置;但是这里基本上都涉及到一些算法问题,所以关于方法的问题基本上都是考验你算法功底的时候;

    先说说我这个自定义的是什么吧!中间有一个圆形,其他的就是定义了一些随机数,用来摆放相应的TextView,但是要保证这些TextView不重叠,而且还不能和中间的圆形重叠,其实也算是很简单的呢。。。

    其他的方法都在上面可以找到的就不写了。。其实这个ViewGroup最难点就在于怎么把确定它们之间不重叠的问题,其实刚开始在网上找了很多的办法,但是都不怎么好使,后来无意之间看到了Rect其实有一个静态方法就能判断两个Rect是否重复,所以问题就变得很简单了;不多逼逼了,还是看代码吧!

     int cCount = getChildCount();
            int screenWidth = getWidth();
            int screenHeight = getHeight();
    
            int cl = 0, ct = 0, cr = 0, cb = 0;
            for (int i = 0; i < cCount; i++) {
                View childAt = getChildAt(i);
                int cWidth = childAt.getMeasuredWidth();
                int cHeight = childAt.getMeasuredHeight();
                if (i == 0) {
                    cl = screenWidth / 2 - cWidth / 2;
                    ct = screenHeight / 2 - cHeight / 2;
                    cr = screenWidth / 2 + cWidth / 2;
                    cb = screenHeight / 2 + cHeight / 2;
                    mRects.add(new Rect(cl,ct,cr,cb));
                    childAt.layout(cl, ct, cr, cb);
                } else {/*这个是第一个View的时候,展示在中间的*/
                    setLocationView(screenWidth, screenHeight, childAt, cWidth, cHeight);
                }
            }
    
        }
    
        private void setLocationView(int screenWidth, int screenHeight, View childAt, int cWidth, int cHeight) {
            int cl;
            int ct;
            int cr;
            int cb;
            /*这里随机的是结束点*/
            int randomWidth = mRandom.nextInt(screenWidth);
            int randomHeight = mRandom.nextInt(screenHeight);
    
            cl = randomWidth - cWidth;
            ct = randomHeight - cHeight;
            cr = randomWidth;
            cb = randomHeight;
    
            if (cl < 0 || ct < 0) {
                /*这里应该重新获取点重新计算*/
                setLocationView(screenWidth,screenHeight,childAt,cWidth,cHeight);
                return;
            }
    
            /*这里判断的是是否重合*/
            Rect currentRect = new Rect(cl, ct, cr, cb);
            for (int i = 0; i < mRects.size(); i++) {
                Rect rect = mRects.get(i);
                if(Rect.intersects(rect,currentRect)){
                    setLocationView(screenWidth,screenHeight,childAt,cWidth,cHeight);
                    return;
                }
            }
            childAt.layout(cl, ct, cr, cb);
            mRects.add(new Rect(cl,ct,cr,cb));
        }
    

    其实最主要的一个方法就是Rect.intersects(rect,currentRect)这个方法,开始的时候不知道这个方法是静态的方法,还傻了吧唧的拿Rect的对象去调用呢,一直oom后来才看到这是一个静态的方法,改成Rect之后就没有在oom了!所以这一定要注意一下!

    Demo地址

    今天就先记录到这里吧!如果以后时间充裕的话一定要写一个关于自定义View的专题……

    相关文章

      网友评论

          本文标题:简单的自定义ViewGroup

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