大伙在用到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>());
}
}
}