Unity NGUI之ScrollView扩展-1

大伙在用到Unity NGUI插件时有木有遇到过这样的问题 - ScrollView 里面的图片,或者 label之类的如果超出列表的区域的话,scrollview 边缘的地方总是显示到不是理想的位置。或者 列表里面有一个旋转动画,如果sprite在旋转过成功如果超出列表区域的话,就可能在没有填充整个ScrollView 裁剪区域的情况下,可以拖拽里面的列表。

这是什么原因呢?通过研究代码,我们发现,UIScrollView是通过计算里面涵盖所有子物体的UIWidget区域的边界,如果超出这个边界的话,ScrollView就判定可以拖动,显示的时候边缘的部分间隙过大。

这显然不是我们想要的效果:怎样解决呢?一个有效的办法就是过滤UIWidget,考虑到动态生成UIScrollView下的子物体,来计算bounds,即重写bounds,可以按照gameobject的名字进行过滤,下面是具体代码:本人亲自测过,并用到实际项目中得到了很好的效果,因此给小伙伴分享一下

using UnityEngine;
using System.Collections;
using System.Collections.Generic;


public class UIScrollViewForSpecialBounds : UIScrollView
{
    /// <summary>
    /// 针对改名字获取相应的bounds 即只计算子物体下所有名字是这个UIWidget的覆盖区域
    /// </summary>
    public string TargetWidgetBoundsName;

    public override Bounds bounds
    {
        get
        {
            mCalculatedBounds = true;
            mTrans = transform;
            return GetSpecialBounds(transform);
        }
    }

    /// <summary>
    /// 获取特定的Bounds 按照gameobject的名字进行过滤
    /// </summary>
    private Bounds GetSpecialBounds(Transform scrollView)
    {
        Matrix4x4 toLocal = scrollView.worldToLocalMatrix;
        bool isSet = false;
        Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
        Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue);
        if (!(scrollView == null || (!NGUITools.GetActive(scrollView.gameObject))))
        {
            Vector3[] corners = null;// p.worldCorners;


            List<UIWidget> widigetList = new List<UIWidget>();
            GetSpecialBoundsWidget(transform, TargetWidgetBoundsName, ref widigetList);


            for (int i = 0; i < widigetList.Count; i++)
            {
                UIWidget w = widigetList[i];
                corners = w.worldCorners;


                for (int j = 0; j < 4; ++j)
                {
                    Vector3 v = toLocal.MultiplyPoint3x4(corners[j]);


                    if (v.x > max.x) max.x = v.x;
                    if (v.y > max.y) max.y = v.y;
                    if (v.z > max.z) max.z = v.z;


                    if (v.x < min.x) min.x = v.x;
                    if (v.y < min.y) min.y = v.y;
                    if (v.z < min.z) min.z = v.z;


                    isSet = true;
                }
            }
        }
        if (isSet)
        {
            Bounds b = new Bounds(min, Vector3.zero);
            b.Encapsulate(max);
            return b;
        }
        return new Bounds(Vector3.zero,Vector3.zero);
    }
    private void GetSpecialBoundsWidget(Transform parent,string speciBoundsName,ref List<UIWidget> list)
    {
        if (parent == null)
            return;
        foreach(Transform child in parent)
        {
            GetSpecialBoundsWidget(child,speciBoundsName,ref list);
        }


        if(parent.name==speciBoundsName)
        {
            list.Add(parent.GetComponent<UIWidget>());
        }
    }
}

猜你喜欢

转载自blog.csdn.net/liulei199079/article/details/50750093