Unity3D通过拖拽UI的四个角伸缩UI

从今天开始写博客啦,把自己觉得有用的记录下来,供自己以后使用。

最近做项目遇到的一个需求,简单的实现了一下,大佬们有更好的方法恳请留言告诉我。

下图为UI的层级结构,Anchors下的四个物体为UI的四个角,注意物体的锚点要设置成对应的位置,而Communication的锚点要设置为stretch、stretch

Unity3D通过拖拽UI的四个角伸缩UI_第1张图片

Unity3D通过拖拽UI的四个角伸缩UI_第2张图片

具体代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class LeftTop : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    private RectTransform rectTransform; //当前预制体的坐标信息
    public RectTransform rootRectTransform; //UI窗口
    public Transform content; //消息显示对话框

    // Start is called before the first frame update
    void Start()
    {
        rectTransform = this.GetComponent();
        rootRectTransform = transform.parent.parent.GetComponent();
    }

    // Update is called once per frame
    void Update()
    {

    }
    #region 拖拽逻辑
    public void OnBeginDrag(PointerEventData eventData)
    {
        Debug.Log("开始拖拽左上角锚点");
    }
    public void OnDrag(PointerEventData eventData)
    {
        Vector3 pos;
        Vector2 mousePos = eventData.position;
        if (eventData.position.x < 0)
            mousePos.x = 0;
        else if (eventData.position.x > Screen.width)
            mousePos.x = Screen.width;
        if (eventData.position.y < 0)
            mousePos.y = 0;
        else if (eventData.position.y > Screen.height)
            mousePos.y = Screen.height;
        RectTransformUtility.ScreenPointToWorldPointInRectangle(rectTransform, mousePos, eventData.enterEventCamera, out pos);

        //Debug.Log(rootRectTransform.offsetMin + "  " + rootRectTransform.offsetMax + "  " + rootRectTransform.sizeDelta + "  " + Screen.width + "  " + Screen.height);
        //防止缩的太小把UI缩没了
        if (Mathf.Abs(pos.x - rootRectTransform.offsetMax.x) < Screen.width - 100 && Mathf.Abs(pos.y - Screen.height - rootRectTransform.offsetMin.y) < Screen.height - 100)
        {
            rectTransform.position = pos; //当前鼠标坐标赋给锚点
            rootRectTransform.offsetMin = new Vector2(pos.x, rootRectTransform.offsetMin.y); //设置UI的rectTransform组件的left  bottom参数
            rootRectTransform.offsetMax = new Vector2(rootRectTransform.offsetMax.x, pos.y - Screen.height); //设置rectTransform的right  top
            int children = content.childCount;
            for (int i = 0; i < children; i++)
            {
                content.GetChild(i).GetComponent().sizeDelta = new Vector2(Screen.width - Mathf.Abs(rootRectTransform.sizeDelta.x) - 40, 20);//消息显示对话框里的文本跟随窗口伸缩保持原有的相对位置不变
            }
        }
    }
    public void OnEndDrag(PointerEventData eventData)
    {
        Debug.Log("结束拖拽左上角锚点");
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class LeftBottom : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    private RectTransform rectTransform; //当前预制体的坐标信息
    public RectTransform rootRectTransform; //UI窗口
    public Transform content; //消息显示对话框

    // Start is called before the first frame update
    void Start()
    {
        rectTransform = this.GetComponent();
        rootRectTransform = transform.parent.parent.GetComponent();
    }

    // Update is called once per frame
    void Update()
    {

    }
    #region 拖拽逻辑
    public void OnBeginDrag(PointerEventData eventData)
    {
        Debug.Log("开始拖拽左下角锚点");
    }
    public void OnDrag(PointerEventData eventData)
    {
        Vector3 pos;
        Vector2 mousePos = eventData.position;
        if (eventData.position.x < 0)
            mousePos.x = 0;
        else if (eventData.position.x > Screen.width)
            mousePos.x = Screen.width;
        if (eventData.position.y < 0)
            mousePos.y = 0;
        else if (eventData.position.y > Screen.height)
            mousePos.y = Screen.height;
        RectTransformUtility.ScreenPointToWorldPointInRectangle(rectTransform, mousePos, eventData.enterEventCamera, out pos);

        //Debug.Log(rootRectTransform.offsetMin + "  " + rootRectTransform.offsetMax + "  " + rootRectTransform.sizeDelta + "  " + Screen.width + "  " + Screen.height);
        if (Mathf.Abs(pos.x - rootRectTransform.offsetMax.x) < Screen.width - 100 && Mathf.Abs(pos.y - rootRectTransform.offsetMax.y) < Screen.height - 100)
        {
            rectTransform.position = pos; //当前鼠标坐标赋给锚点
            rootRectTransform.offsetMin = new Vector2(pos.x, pos.y); //设置rectTransform的left  bottom
            rootRectTransform.offsetMax = new Vector2(rootRectTransform.offsetMax.x, rootRectTransform.offsetMax.y); //设置rectTransform的right  top
            int children = content.childCount;
            for (int i = 0; i < children; i++)
            {
                content.GetChild(i).GetComponent().sizeDelta = new Vector2(Screen.width - Mathf.Abs(rootRectTransform.sizeDelta.x)-40, 20);//消息显示对话框里的文本跟随窗口伸缩保持原有的相对位置不变
            }
        }
    }
    public void OnEndDrag(PointerEventData eventData)
    {
        Debug.Log("结束拖拽左下角锚点");
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class RightTop : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    private RectTransform rectTransform; //当前预制体的坐标信息
    public RectTransform rootRectTransform; //UI窗口
    public Transform content; //消息显示对话框

    // Start is called before the first frame update
    void Start()
    {
        rectTransform = this.GetComponent();
        rootRectTransform = transform.parent.parent.GetComponent();
    }

    // Update is called once per frame
    void Update()
    {

    }
    #region 拖拽逻辑
    public void OnBeginDrag(PointerEventData eventData)
    {
        Debug.Log("开始拖拽右上角锚点");
    }
    public void OnDrag(PointerEventData eventData)
    {
        Vector3 pos;
        Vector2 mousePos = eventData.position;
        if (eventData.position.x < 0)
            mousePos.x = 0;
        else if (eventData.position.x > Screen.width)
            mousePos.x = Screen.width;
        if (eventData.position.y < 0)
            mousePos.y = 0;
        else if (eventData.position.y > Screen.height)
            mousePos.y = Screen.height;
        RectTransformUtility.ScreenPointToWorldPointInRectangle(rectTransform, mousePos, eventData.enterEventCamera, out pos);

        //Debug.Log(rootRectTransform.offsetMin + "  " + rootRectTransform.offsetMax + "  " + rootRectTransform.sizeDelta + "  " + Screen.width + "  " + Screen.height);
        if (Mathf.Abs(pos.x - Screen.width - rootRectTransform.offsetMin.x) < Screen.width - 100 && Mathf.Abs(pos.y - Screen.height - rootRectTransform.offsetMin.y) < Screen.height - 100)
        {
            rectTransform.position = pos; //当前鼠标坐标赋给锚点
            rootRectTransform.offsetMin = new Vector2(rootRectTransform.offsetMin.x, rootRectTransform.offsetMin.y); //设置rectTransform的left  bottom
            rootRectTransform.offsetMax = new Vector2(pos.x - Screen.width, pos.y - Screen.height); //设置rectTransform的right  top
            int children = content.childCount;
            for (int i = 0; i < children; i++)
            {
                content.GetChild(i).GetComponent().sizeDelta = new Vector2(Screen.width - Mathf.Abs(rootRectTransform.sizeDelta.x) - 40, 20); //消息显示对话框里的文本跟随窗口伸缩保持原有的相对位置不变
            }
        }
    }
    public void OnEndDrag(PointerEventData eventData)
    {
        Debug.Log("结束拖拽右上角锚点");
    }
    #endregion
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class RightBottom : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    private RectTransform rectTransform; //当前预制体的坐标信息
    public RectTransform rootRectTransform; //UI窗口
    public Transform content; //消息显示对话框

    // Start is called before the first frame update
    void Start()
    {
        rectTransform = this.GetComponent();
        rootRectTransform = transform.parent.parent.GetComponent();
    }

    // Update is called once per frame
    void Update()
    {

    }
    #region 拖拽逻辑
    public void OnBeginDrag(PointerEventData eventData)
    {
        Debug.Log("开始拖拽右下角锚点");
    }
    public void OnDrag(PointerEventData eventData)
    {
        Vector3 pos;
        Vector2 mousePos = eventData.position;
        if (eventData.position.x < 0)
            mousePos.x = 0;
        else if (eventData.position.x > Screen.width)
            mousePos.x = Screen.width;
        if (eventData.position.y < 0)
            mousePos.y = 0;
        else if (eventData.position.y > Screen.height)
            mousePos.y = Screen.height;
        RectTransformUtility.ScreenPointToWorldPointInRectangle(rectTransform, mousePos, eventData.enterEventCamera, out pos);

        //Debug.Log(rootRectTransform.offsetMin + "  " + rootRectTransform.offsetMax + "  " + rootRectTransform.sizeDelta + "  " + Screen.width + "  " + Screen.height);
        if (Mathf.Abs(pos.x - Screen.width - rootRectTransform.offsetMin.x) < Screen.width - 100 && Mathf.Abs(pos.y - rootRectTransform.offsetMax.y) < Screen.height - 100)
        {
            rectTransform.position = pos; //当前鼠标坐标赋给锚点
            rootRectTransform.offsetMin = new Vector2(rootRectTransform.offsetMin.x, pos.y); //设置rectTransform的left  bottom
            rootRectTransform.offsetMax = new Vector2(pos.x - Screen.width, rootRectTransform.offsetMax.y); //设置rectTransform的right  top
            int children = content.childCount;
            for (int i = 0; i < children; i++)
            {
                content.GetChild(i).GetComponent().sizeDelta = new Vector2(Screen.width - Mathf.Abs(rootRectTransform.sizeDelta.x) - 40, 20);//消息显示对话框里的文本跟随窗口伸缩保持原有的相对位置不变
            }
        }
    }
    public void OnEndDrag(PointerEventData eventData)
    {
        Debug.Log("结束拖拽右下角锚点");
    }
    #endregion
}

Communication下的子物体根据需要设置锚点,横向或者纵向需要跟随根节点变化的就将锚点设置为stretch。

需要注意的是,当子物体为Scroll View时,content下的物体无法设置锚点,我的content下是text组件,不管怎么拉伸UI文字始终维持到左上角的距离不变,所以我只好在每次拖拽时都设置text的位置,来控制text在UI中的相对位置,不要问为什么设置为那个值,我试出来的。

我的第一篇博客新鲜出炉啦,请各路大神不吝赐教!

你可能感兴趣的:(Unity3D,Unity,UI伸缩)