也论UIGrid

之前网上有篇文章,是讲创建高效的超大Scroll view,其思路就是将没在clip范围内的item进行setactive(false),反之则setactive(true),这样item很多也可以流畅的滑动。

他是改造的UIWarpContent.cs。也就是循环列表那个例子里的脚本,不过它参数没有UIGrid多,想了一想,还是改UIGrid更快。现在就讲讲怎么改动UIGrid以达到同样的效果。

UIScrollView mScroll;//增加这一行,用来保存UIScrollView组件 (114行)
protected virtual void Start ()
{
if (!mInitDone) Init();
bool smooth = animateSmoothly;
animateSmoothly = false;
Reposition();
animateSmoothly = smooth;
enabled = false;

//增加部分,就是给UIPanel的onClipMove注册这边的处理事件,这个事件在列表被拖动时会触发
        mScroll = mPanel.GetComponent<UIScrollView>();
        if (mScroll != null) {
            //Debug.Log(transform.parent +"`s grid reg OnMove");
            mScroll.GetComponent<UIPanel>().onClipMove += OnMove;
        }
}

然后就是具体操作,这两个函数写在UIGrid类里的最后面就行了

protected virtual void OnMove(UIPanel panel) { WrapContent(); }
        public void WrapContent() {
        //EX(为支持多个item,禁用不显示item)
        //Debug.Log("call "+transform.parent.name+"`s WrapContent");
        Transform myTrans = transform;
        Vector3[] corners = mPanel.worldCorners;
        for (int i = 0; i < 4; ++i) {
            Vector3 v = corners[i];
            v = myTrans.InverseTransformPoint(v);//把clip rect的四个角变换到grid的坐标系
            corners[i] = v;
        }
        Vector3 center = Vector3.Lerp(corners[0], corners[2], 0.5f);//左下和右上角的取半,就是clip rect的中心
        //Debug.Log(myTrans.parent.name+" child count:" + myTrans.childCount);
        if (arrangement == Arrangement.Horizontal) {
            float min = corners[0].x - cellWidth;//最小值:左下角x减去一个item的宽度
            float max = corners[2].x + cellWidth;//最大值:右上角x加上一个item的宽度


            for (int i = 0; i < myTrans.childCount; ++i) {
                Transform t = myTrans.GetChild(i);
                Vector3 tmpPos = t.position;
                tmpPos = myTrans.InverseTransformPoint(tmpPos);
                float distance = tmpPos.x;// -center.x;


                if (true) {
                    //distance += mPanel.clipOffset.x - myTrans.localPosition.x;
                    //Debug.Log("H name:" + t.name + " min:" + min + " dis:" + distance + " max:" + max);
                    if (!UICamera.IsPressed(t.gameObject)) {
                        Transform g = t.FindChild("children");//这后面的代码要结合自身情况改
                        if (g != null && g.childCount == 0)
                            NGUITools.SetActive(t.gameObject, (distance > min && distance < max), false);
                    }
                }
            }
        } else {
            float min = corners[0].y - cellHeight;
            float max = corners[2].y + cellHeight;
            for (int i = 0; i < myTrans.childCount; ++i) {
                Transform t = myTrans.GetChild(i);
                Vector3 tmpPos = t.position;
                tmpPos = myTrans.InverseTransformPoint(tmpPos);
                float distance = tmpPos.y;// -center.y;


                if (true) {
                    //distance += mPanel.clipOffset.y - myTrans.localPosition.y;
                    //Debug.Log("V name:" + t.name + " min:" + min + " dis:" + distance + " max:" + max);
                    if (!UICamera.IsPressed(t.gameObject)) {
                        Transform g = t.FindChild("children");//这后面的代码要结合自身情况改
                        if(g!=null && g.childCount == 0)
                            NGUITools.SetActive(t.gameObject, (distance > min && distance < max), false);
                    }
                }
            }
        }
        //
    }

我这个不具有通用性,因为我这个是多级列表,它判断了一下UIGrid所在的对象是否是列表的叶节点,因为只有叶节点才能这样处理,有子物体的节点不能被隐藏,否则子物体全看不到了,就是你拖着拖着,列表一下全没了。。。

总之就是把UIPanel的clip的范围和每一个item的坐标都变换到同一个坐标系下,然后比较item是不是在clip的范围里,以决定隐藏还是显示。

不过这样最好不要在item的脚本里执行协程,不然一setactive(false)协程就断了

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值