Unity中关于ScrollRect组件完整解决方案(ScrollRect中元素自动排版+ScrollRect中元素自动定位到Viewport可见范围内)

这个教程可以实现点击我这个视频中所示的效果

一、元素自动排版功能

1、首先要往我们的unity项目中导入两个脚本文件,脚本文件名称分别是UIScrollEventListener和CZScrollRect,这两个脚本文件代码如下所示。

1-1、介绍UIScrollEventListener脚本写法。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class UIScrollEventListener : MonoBehaviour, IBeginDragHandler, IEndDragHandler , IPointerUpHandler, IPointerDownHandler , IDragHandler
{
   
    public delegate void VoidDelegate(PointerEventData pdata);
    public VoidDelegate onBeginDrag;
    public VoidDelegate onEndDrag;
    public VoidDelegate onUp;
    public VoidDelegate onDown;
    public VoidDelegate onDrag;
    bool isDrag = false;
    List<Image> registers = new List<Image>();

    public static UIScrollEventListener Get(GameObject go)
    {
   
        UIScrollEventListener listener = go.GetComponent<UIScrollEventListener>();
        if (listener == null) listener = go.AddComponent<UIScrollEventListener>();
        return listener;
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
   
        isDrag = true;
        if (onBeginDrag != null) onBeginDrag(eventData);
    }

    public void OnEndDrag(PointerEventData eventData)
    {
   
        isDrag = false;
        if (onEndDrag != null) onEndDrag(eventData);
    }

    public void OnPointerUp(PointerEventData eventData)
    {
   
        if (!isDrag) {
   

            SetRegisterEvent(true);
            PraseObject(eventData);
            SetRegisterEvent(false);
        }
        if (onUp != null) onUp(eventData);
    }

    public void OnPointerDown(PointerEventData eventData)
    {
   
        if (onDown != null) onDown(eventData);
    }

    public void OnDrag(PointerEventData eventData) {
   

        if (onDrag != null) onDrag(eventData);
    }

    public void RegisterButton(GameObject go)
    {
   
        Image img = go.GetComponent<Image>();
        if (img != null)
        {
   
            img.raycastTarget = false;
            registers.Add(img);
        }
    }

    void SetRegisterEvent(bool b) {
   

        if (registers.Count > 0)
        {
   
            for (int i = 0; i < registers.Count; ++i)
            {
   
                registers[i].raycastTarget = b;
            }
        }
    }

    void PraseObject(PointerEventData eventData) {
   

        if (registers.Count > 0)
        {
   
            for (int i = 0; i < registers.Count; ++i)
            {
   
                if (EventSystem.current != null)
                {
   
                    List<RaycastResult> result = new List<RaycastResult>();
                    EventSystem.current.RaycastAll(eventData, result);
                    foreach (RaycastResult r in result)
                    {
   
                        //Debug.Log(r.gameObject.name);
                        foreach (Image img in registers)
                        {
   

                            if (img.gameObject.Equals(r.gameObject))
                            {
   

                                InputField inputfield = img.gameObject.GetComponent<InputField>();
                                if (inputfield != null) inputfield.ActivateInputField();
                            }

                        }
                    }
                }
            }
        }
    }

}
1-2、介绍CZScrollRect脚本写法。
using System;
using UnityEngine;
using UnityEngine.UI;

public class ScrollObj
{
   
    public GameObject obj;
    public int dex;
}

public class CZScrollRect
{
   

    public enum TipType
    {
   
        UNDO_REFRESH = 0,
        PULL_REFRESH = 1,
        UNDO_APPEND = 2,
        PULL_AAPEND = 3,
        NODATA = 4,
        NONE = 5
    }

    const int OPEAT_HEIGHT = 100;//高度差判断操作类型
    const int INIT_NUM_LIMIT = 8;//列表实例化个数

    public delegate void OperatDelegate();
    public delegate void OperatObjDelegate(GameObject obj , int index);
    public delegate void OperatTextObjDelegate(GameObject obj, TipType t);
    public OperatDelegate onRefresh;//下拉刷新时回调
    public OperatDelegate onAppend;//需要加载更多时回调
    public OperatObjDelegate onScrollObj;//需刷新时回调
    public OperatTextObjDelegate onUpdateTextObj;//需刷新文本状态时回调

    public ScrollRect scrollRect;//ScrollRect
    private RectTransform scrollRectContent;//RectTransform
    public GameObject prefab;//实例化的对象
    public GameObject text_up;//下拉刷新文本
    public GameObject text_down;//上拉加载更多文本

    TipType textup_status;

    int opeartLen = 0;//记录总长度
    public int layoutwidth = 1242;//填写item的长度
    public int limitNum = 8;//列表实例化个数
    public float interval = 200;//每个item的高度
    public float spacing = 5;//每个tiem的间隔

    ScrollObj[] list;//用于管理生成的对象
    int opeartType;
    int pageindex;//页码
    bool bHasMore;//是否能加载更多
    int halfWidth;

    //
    public GameObject batchContent;

    public CZScrollRect()
    {
   
        opeartType = -1;
        hasMore = false;
    }

    /// <summary>
    /// 用于控制scrollrect是否能够滑动
    /// (用于等待网络请求等业务)
    /// </summary>
    public bool vertical
    {
   
        get{
   
            return scrollRect.vertical;
        }set{
   
            scrollRect.vertical = value;
        }
    }

    /// <summary>
    /// 是否存在更多
    /// </summary>
    public bool hasMore
    {
   
        get{
   
            return bHasMore;
        }set{
   
            bHasMore = value;
        }
    }

    /// <summary>
    /// 获取对象所在的索引
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public int GetObjIndex(GameObject obj) {
   

        for(int i = 0; i < list.Length; ++i)
        {
   
            if (obj.Equals(list[i].obj))
            
  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要判断ScrollRect下Content里面的元素是否在可视范围内,可以使用RectTransform组件Viewport的位置信息来进行判断。可以按照以下步骤进行判断: 1. 获取ScrollRect组件和Content的RectTransform组件: ```csharp ScrollRect scrollRect = yourScrollRect.GetComponent<ScrollRect>(); RectTransform contentRectTransform = scrollRect.content.GetComponent<RectTransform>(); ``` 2. 获取Viewport的位置信息: ```csharp RectTransform viewportRectTransform = scrollRect.viewport.GetComponent<RectTransform>(); Vector3[] viewportCorners = new Vector3[4]; viewportRectTransform.GetWorldCorners(viewportCorners); Vector2 viewportMin = viewportCorners[0]; Vector2 viewportMax = viewportCorners[2]; ``` 3. 获取Content下每个元素的位置信息,并判断是否在可视范围内: ```csharp for (int i = 0; i < contentRectTransform.childCount; i++) { RectTransform childRectTransform = contentRectTransform.GetChild(i).GetComponent<RectTransform>(); Vector3[] childCorners = new Vector3[4]; childRectTransform.GetWorldCorners(childCorners); Vector2 childMin = childCorners[0]; Vector2 childMax = childCorners[2]; bool isElementVisible = childMax.x >= viewportMin.x && childMin.x <= viewportMax.x && childMax.y >= viewportMin.y && childMin.y <= viewportMax.y; // 根据需要使用isElementVisible进行进一步的操作 } ``` 通过遍历Content下的每个元素,获取其位置信息,并与Viewport的位置信息进行比较,可以判断元素是否在可视范围内。根据需要,可以在判断后对元素进行进一步的操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Defining the Future

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值