Unity滚动列表

 之前我还在用克隆,主程把我一顿怼。说用缓存实现。只好认真学习

 关于缓存真的没啥,多练习,多使用就好,毕竟这么好的功能,减少内存消耗真的挺棒的。

 

    UIScrollView RightView;
    UIMyWrapContent myWrap;
    UIPanel RightPanel;
    SpringPanel RightSpringP;
    bool isfirst = true;
    const int MaxItemNum = 3;

    /// <summary>
    /// 缓存
    /// </summary>
    Item_RideSkillList[] item_RideSkillList = new Item_RideSkillList[MaxItemNum];

void Init()
    {
        RightView = transform.FindChild("Right").GetComponent<UIScrollView>();
        myWrap = RightView.GetComponent<UIMyWrapContent>();
        RightPanel = RightView.GetComponent<UIPanel>();
        RightSpringP = RightView.GetComponent<SpringPanel>();
        myWrap.InitThis();
        myWrap.onInitializeItem = OnInitializeItem;
  }


//缓存最重要的方法,在滑动时候就是这个函数起作用
  void OnInitializeItem(GameObject go, int wrapIndex, int realIndex)
    {
        if (MaxItemLine < MaxItemNum + 1 || !Isinit)
            return;
        if (go.name.StartsWith("Item_RideSkillList_"))
        {
            int itemP = 0;
            int.TryParse(go.name.Replace("Item_RideSkillList_", string.Empty), out itemP);
            if (realIndex > 0)
            {
                item_RideSkillList[itemP - 1].gameObject.SetActive(false);
                return;
            }
            //itemP: 1  2  3 
            int reI = Mathf.Abs(realIndex);
            if (MaxItemLine > reI)
                SetItemData(itemP - 1, reI);
        }
    }
//这就是对缓存的子物体进行赋值
void SetItemData(int itemPos, int LinePos)
    {
        List<RideSkill> rs = new List<RideSkill>();
        for (int i = 0; i < OneLineCount; ++i)
        {
            if (OneLineCount * LinePos + i < ridelists.Count)
                rs.Add(ridelists[(OneLineCount * LinePos + i)]);
        }
        item_RideSkillList[itemPos].Setdata(rs);
    }

//设置缓存的个数,MaxItemLine就是一共有的东西
void SetData()
    {
        myWrap.maxIndex = 0;
        myWrap.minIndex = 1 - MaxItemLine;
   if (MaxItemLine > MaxItemNum)
        {
            myWrap.enabled = true;
            for (int i = 0; i < MaxItemNum; ++i)
            {
                item_RideSkillList[i].gameObject.SetActive(true);
                SetItemData(i, i);
                if (isfirst)
                    item_RideSkillList[i].transform.localPosition = new Vector3(0, -myWrap.itemSize * i, 0);
            }
        }
        else
        {
            for (int i = 0; i < MaxItemNum; ++i)
            {
                if (isfirst)
                    item_RideSkillList[i].transform.localPosition = new Vector3(0, -myWrap.itemSize * i, 0);
                if (i >= MaxItemLine)
                    item_RideSkillList[i].Hide();
                else
                    SetItemData(i, i);
            }
        }
        if (isfirst)
        {
            RightSpringP.enabled = false;
            RightPanel.transform.localPosition = new Vector3(180, 8, 0);
            RightPanel.clipOffset = Vector2.zero;
            RightView.ResetPosition();
        }
        isfirst = false;

}

关于 UIMyWrapContent类,继承于UIWrapContent,也是对NGUI进行扩展

using UnityEngine;
using System.Collections;

public class UIMyWrapContent : UIWrapContent
{
    protected override void Start()
    {
        SortBasedOnScrollMovement();
        if (mScroll != null) mScroll.GetComponent<UIPanel>().onClipMove = OnMove;
        mFirstTime = false;
    }
    public void WrapContentForce()
    {
        mFirstTime = true;
        base.WrapContent();
        mFirstTime = false;
    }

    public void InitThis()
    {
        base.Start();
    }
    public  void MyUpdate()
    {
        for (int i = 0, imax = mChildren.Count; i < imax; ++i)
        {
            Transform t = mChildren[i];
            UpdateItem(t, i);
        }
    }
}

也是多练习就好了,主要还是对

 void OnInitializeItem(GameObject go, int wrapIndex, int realIndex)

{   }

方法的使用

### Unity 中实现可滚动列表的功能 在 Unity 的 UGUI 系统中,`ScrollRect` 是核心组件之一,用于创建滚动列表功能。以下是关于如何利用 `ScrollRect` 组件以及对象池技术来构建高效、流畅的滚动列表。 #### 1. ScrollRect 基础配置 `ScrollRect` 可以绑定到一个容器(Content),并通过拖动视口(Viewport)展示不同的内容区域。为了实现滚动列表,需完成以下基础设置: - 创建一个 Canvas 并在其下添加一个 Panel 或 Image 作为背景。 - 添加一个子物体并将其转换为 ScrollView,该物体应包含两个主要部分:Viewport 和 Content[^1]。 - 设置 Viewport 的大小和位置,并将 Content 物体放置于其内部。 ```csharp using UnityEngine; using UnityEngine.UI; public class SetupScrollView : MonoBehaviour { public GameObject scrollViewPrefab; // 预制件路径 void Start() { GameObject scrollObject = Instantiate(scrollViewPrefab, transform); RectTransform contentRectTransform = scrollObject.transform.Find("Viewport/Content").GetComponent<RectTransform>(); // 初始化滚动内容尺寸 contentRectTransform.sizeDelta = new Vector2(0f, itemHeight * itemCount); // 动态计算高度 } } ``` #### 2. 使用对象池优化性能 当滚动列表中的项数量较多时,频繁实例化和销毁会带来较大的开销。因此推荐使用 **对象池** 技术缓存未使用的 UI 元素。 ```csharp using System.Collections.Generic; using UnityEngine; public class ObjectPooler : MonoBehaviour { private Queue<GameObject> poolQueue = new Queue<GameObject>(); public GameObject prefab; // 单个列表项预制件 public int initialSize = 5; void Awake() { for (int i = 0; i < initialSize; ++i) { var obj = Instantiate(prefab); obj.SetActive(false); poolQueue.Enqueue(obj); } } public GameObject GetPooledObject() { if (poolQueue.Count > 0) { var pooledObj = poolQueue.Dequeue(); pooledObj.SetActive(true); return pooledObj; } else { var newObj = Instantiate(prefab); return newObj; } } public void ReturnToPool(GameObject go) { go.SetActive(false); poolQueue.Enqueue(go); } } ``` #### 3. 自定义滚动逻辑 对于更复杂的场景,可能需要自定义滚动行为。例如,在用户停止滑动后触发回调函数或者动态加载数据[^4]。 ```csharp using UnityEngine; using UnityEngine.EventSystems; public class CustomScrollLogic : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler { private bool isDragging = false; public void OnBeginDrag(PointerEventData eventData) { isDragging = true; } public void OnDrag(PointerEventData eventData) { if (!isDragging) return; // 更新滚动偏移量... } public void OnEndDrag(PointerEventData eventData) { isDragging = false; StartCoroutine(LoadMoreDataIfNecessary()); } IEnumerator LoadMoreDataIfNecessary() { yield return null; // 等待一帧确认结束状态 Debug.Log("尝试加载更多数据..."); } } ``` #### 4. 数字滚动动画增强用户体验 如果滚动列表涉及数值变化,则可以通过平滑过渡的方式改善视觉效果[^3]。 ```csharp using UnityEngine; using UnityEngine.UI; public class SmoothNumberAnimator : MonoBehaviour { [SerializeField] private Text numberText; private float targetValue = 0f; private float currentValue = 0f; public void SetTarget(float newValue) { targetValue = newValue; } void Update() { currentValue = Mathf.Lerp(currentValue, targetValue, Time.deltaTime * 8f); numberText.text = ((int)Mathf.Round(currentValue)).ToString(); } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值