首页 >Unity3D频道 >【Unity杂文】 > Unity3D研究院之ContentSizeFitter同步立即响应回调
2016
08-17

Unity3D研究院之ContentSizeFitter同步立即响应回调

ContentSizeFitter使用Preferred Size来设置RectTransform不能立即生效,必须要等一帧,也可以利用OnRectTransformDimensionsChange的回调方法。

但是这么做还是很恶心,最好还是能同步的计算出它的区域,一般我们可能会横向纵向的嵌套Layout。

主要就是 LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform); 这一句。 如果不想用下面的脚本。 也可以在取RectTransofrm的size之前加上这一句

unity版本:5.3.5

不废话了直接上代码啦。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using FitMode = UnityEngine.UI.ContentSizeFitter.FitMode;
using UnityEngine.EventSystems;
using System;


[RequireComponent(typeof(ContentSizeFitter))]
public class ContentImmediate :MonoBehaviour
{
    private RectTransform m_RectTransform;
    private RectTransform rectTransform
    {
        get
        {
            if (m_RectTransform == null)
                m_RectTransform = GetComponent<RectTransform>();
            return m_RectTransform;
        }
    }

    private ContentSizeFitter m_ContentSizeFitter;
    private ContentSizeFitter contentSizeFitter
    {
        get
        {
            if (m_ContentSizeFitter == null)
                m_ContentSizeFitter = GetComponent<ContentSizeFitter>();
            return m_ContentSizeFitter;
        }
    }
    //立即获取ContentSizeFitter的区域
    public Vector2 GetPreferredSize () 
    {
        LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform);
        return  new Vector2(HandleSelfFittingAlongAxis(0),HandleSelfFittingAlongAxis(1));
    }

    private float HandleSelfFittingAlongAxis(int axis)
    {
        FitMode fitting = (axis == 0 ? contentSizeFitter.horizontalFit : contentSizeFitter.verticalFit);
        if (fitting == FitMode.MinSize){
            return LayoutUtility.GetMinSize(rectTransform, axis);
        }else{
            return LayoutUtility.GetPreferredSize(rectTransform, axis);
        }
    }

}

然后是测试的代码, 同步把gameobject挂在Layout下,同步计算出它的size。

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class Test : MonoBehaviour {

    public GameObject momo;
    public GameObject ruoruo;
	void Start () 
    {
        //同步的把两个gameobject挂在layout下面
        GameObject go1 =  GameObject.Instantiate<GameObject>(momo);
        go1.transform.SetParent(transform,false);

        GameObject go2 =  GameObject.Instantiate<GameObject>(ruoruo);
        go2.transform.SetParent(transform,false);

        ContentImmediate  content = GetComponent<ContentImmediate>() ?? gameObject.AddComponent<ContentImmediate>();
        //同步获取ContentSizeFitter的size
        Debug.Log("ContentSizeFitter size  = " +" " + content.GetPreferredSize());
	}
}

如下图所示,同步加载的gameobject已经可以立刻获取它的区域了
snip20161009_3
最后欢迎大家提出意见。

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

Unity3D研究院之ContentSizeFitter同步立即响应回调》有 13 条评论

  1. 可以自己去计算
    text.rectTransform.sizeDelta = new Vector2 (text.preferredWidth,text.preferredHeight);
    backGround.sizeDelta = new Vector2 (text.preferredWidth+20.0f,text.preferredHeight+20.0f);

  2. Disuo.Ke说:

    可以用这个 Canvas.ForceUpdateCanvases();

  3. 任凯说:

    给个demo吧 雨松老师

  4. 任凯说:

    你好
    我是unity 5.6.4p1 版本 测试上述代码不好用 log是 (0,0) 还请雨松老师 给与解答

  5. 任凯说:

    你好
    我是unity 5.6.4p1 版本 测试上述代码不好用 log是 (0,0)

  6. 感谢雨松大神 帮了大忙

  7. 说:

    这能直接导入到LuaFramework_UGUI中用吗?ContentSizeFitter fitter = GetComponent(); fitter.CallBack(delegate(Vector2 size) { Debug.Log(“size =” size); });这个直接在lua中调用,不知要不要wrap出来

  8. 说:

    这能直接导入到LuaFramework_UGUI中用吗?ContentSizeFitter fitter = GetComponent(); fitter.CallBack(delegate(Vector2 size) { Debug.Log(“size =” + size); });这个直接在lua中调用,不知要不要wrap出来

  9. MaCh说:

    等一帧是因为要刷新canvas renderer的原因?

留下一个回复

你的email不会被公开。 必填项已用 * 标注。