U3D 实现UGUI循环列表

本文介绍如何在Unity3D中使用UGUI创建一个支持正反方向、垂直和水平循环滚动的列表,适用于展示排名、聊天信息等场景。通过移除ScrollRect Content内的布局组件并添加特定代码,可以实现不等高Item的循环滚动效果。
摘要由CSDN通过智能技术生成

在项目开发中,列表滚动是很常用的功能,比如展示玩家排名,聊天信息等。

这里我们实现一个循环列表功能。

首先我们创建个ScrollRect,移除掉Content里面的布局组件。如下

 然后在List_View上放上如下代码

LoopListViewer.cs

/*
 * Created By Zhaotao On 2019-3-22
 * Desc:循环列表
 */

using System;
using System.Collections;
using System.Collections.Generic;
using DigiskyUnity;
using LuaInterface;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SocialPlatforms;
using UnityEngine.UI;


public class LoopListViewer : MonoBehaviour
{
    private enum LayoutDir
    {
        NEGATIVE = -1,
        POSITIVE = 1,
    }

    //滚动区域组件
    [SerializeField] private ScrollRect ScrollView;

    //Item父对象
    [SerializeField] private GameObject Content;

    //list的Item 控件
    [SerializeField] private GameObject ItemBase;

    //上下的缓冲
    [SerializeField] private float BufferDis = 20;

    //排列器
    [SerializeField] private LoopItemArranger Arranger;
    
    //默认Item的个数
    [SerializeField] private int DefaultCount = 10;

    //是否是垂直滚动
    [SerializeField] private bool IsVertical = true;

    //滚动方向 1 为正滚动,-1为反方向滚动
    [SerializeField] private LayoutDir Direction = LayoutDir.POSITIVE;

    //Item 列表
    private List<ILoopItem> _ItemList = new List<ILoopItem>();

    private int _TopIndex = -1;
    private int _EndIndex = -1;

    //Item的个数
    private int _TotalCount = 0;

    //Content 的尺寸
    private Vector2 _ContentSize = Vector2.zero;

    //ViewPort的尺寸
    private Vector2 _ViewPortSize = Vector2.zero;

    private LoopListUpdateCallBack _ChangeCallBack = null;

    private Vector2 _LastPos = Vector2.zero;

    //滚动到的索引
    private int _ScrollToIndex = 0;
    
    //滚动速度
    private float _ScrollSpeed = 0;

    private void Awake()
    {
        if (Content != null)
        {
            _ContentSize = Content.GetComponent<RectTransform>().sizeDelta;
        }

        if (ScrollView != null)
        {
            _ViewPortSize = ScrollView.GetComponent<RectTransform>().sizeDelta;

            ScrollView.onValueChanged.AddListener(ScrollCallBack);
        }

        Arranger.SetIsVertical(IsVertical);
        Arranger.SetDir((int)Direction);
        AdjustPovit();
    }

    private void Start()
    {
        AddCount(DefaultCount);
        Content.GetComponent<RectTransform>().anchoredPosition = Vector2.zero;
    }

    private void Update()
    {
        if (_ScrollToIndex > 0 && _ScrollSpeed > 0)
        {
            var head = Arranger.GetHeadItem();
            var tail = Arranger.GetTailItem();
            if (_ScrollToIndex < head.GetIndex())
            {
                //项下滚动
                if (IsVertical)
                {
                    SpeedScroll(-_ScrollSpeed * (int)Direction);
                }
                else
                {
                    SpeedScroll(_ScrollSpeed * (int)Direction); 
                }
            }else if (_ScrollToIndex > tail.GetIndex())
            {
                //项上滚动
                if (IsVertical)
                {
                    SpeedScroll(_ScrollSpeed * (int)Direction);
                }
                else
                {
                    SpeedScroll(-_ScrollSpeed * (int)Direction); 
                }
            }
            else
            {
                //在可见项之间
                ILoopItemArrange itemArrange = Arranger.GetItemArrangeByIndex(_ScrollToIndex);
                if (itemArrange != null)
                {
                    if (IsVertical)
                    {
                        float conY = Content.GetComponent<RectTransform>().anchoredPosition.y;
                        float iY = itemArrange.GetCurrentItem().GetPosition().y * (int) Direction;
                        float offY = conY * (int) Direction + iY + Arranger.GetSpaceOff();

                        if (Math.Abs(offY) < _ScrollSpeed)
                        {
                            SpeedScroll(-offY * (int)Direction); 
                            _ScrollToIndex = 0;
                            _ScrollSpeed = 0;
                            ScrollView.enabled = true;
                        }
                        else if(Math.Abs(offY) > _ScrollSpeed)
                        {
                            SpeedScroll(-offY/Math.Abs(offY) * _ScrollSpeed * (int)Direction);
                        }
                        else
                        {
                            _ScrollToIndex = 0;
                            _ScrollSpeed = 0;
                            ScrollView.enabled = true;
                        }
                    }
                    else
                    {
                        float conX = Content.GetComponent<RectTransform>().anchoredPosition.x;
                        float iX = itemArrange.GetCurrentItem().GetPosition().x * (int) Direction;
                        float offX = conX * (int) Direction + iX - Arranger.GetSpaceOff();
                        
                        if (Math.Abs(offX) < _ScrollSpeed)
                        {
                            SpeedScroll(-offX * (int)Direction); 
                            _ScrollToIndex = 0;
                            _ScrollSpeed = 0;
                            ScrollView.enabled = true;
                        }
                        else if(Math.Abs(offX) > _ScrollSpeed)
                        {
                            SpeedScroll(-offX/Math.Abs(offX) * _ScrollSpeed * (int)Direction); 
                        }
                        else
                        {
                            _ScrollToIndex = 0;
                            _ScrollSpeed = 0;
                            ScrollView.enabled = true;
                        }
                    }
                }
                else
                {
                    LogHelper.Warning("dont find "+_ScrollToIndex +" Item");
                }
            }
        }
    }

    /// <summary>
    /// 调整锚点方向
    /// </summary>
    private void AdjustPovit()
    {
        var Rt = Content.GetComponent<RectTransform>();
        var Rtb = ItemBase.GetComponent<RectTransform>();
        if (Direction == LayoutDir.POSITIVE && IsVertical)
        {
            Rt.anchorMin = new Vector2(0,1);
            Rt.anchorMax = new Vector2(1,1);
            Rt.pivot = new Vector2(0.5f,1);
            Rt.anchoredPosition = Vector2.zero;
            
            Rtb.pivot = new Vector2(0.5f,1);
            Rtb.anchoredPosition = Vector2.zero;
        }else if (Direction == LayoutDir.NEGATIVE && IsVertical)
        {
            Rt.anchorMin = new Vector2(0,0);
            Rt.anchorMax = new Vector2(1,0);
            Rt.pivot = new Vector2(0.5f,0);
            Rt.anchoredPosition = Vector2.zero;
            
            Rtb.pivot = new Vector2(0.5f,0);
            Rtb.anchoredPosition = Vector2.zero;
        }else if(Direction == LayoutDir.POSITIVE && !IsVertical)
        {
            Rt.anchorMin = new Vector2(0,0);
            Rt.anchorMax = new Vector2(0,1);
            Rt.pivot = new Vector2(0,0.5f);
            Rt.anchoredPosition = Vector2.zero;
            
            Rtb.pivot = new Vector2(0,0.5f);
            Rtb.anchoredPosition = Vector2.zero;
        }else if(Direction == LayoutDir.NEGATIVE && !IsVertical)
        {
            Rt.anchorMin = new Vector2(1,0);
            Rt.anchorMax = new Vector2(1,1);
            Rt.pivot = new Vector2(1,0.5f);
            Rt.anchoredPosition = Vector2.zero;
            
            Rtb.pivot = new Vector
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值