UGUI循环滚动排行榜

步骤:

1.创建一个UGUI自带的Scroll View组件
2.在Scroll view的Content下创建一个模板命名为RankCellPrefab

注意:

设置模板RankCellPrefab的锚点设置,以及Pivot要设置为(0.5,1),目的是为了方便改变位置。
在这里插入图片描述

//子物体属性设置
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 模拟玩家数据
/// </summary>
public class UserData
{
    public string name;
    public float score;
    //public Sprite icon;//其他属性自行扩展
    public UserData(string name, float score)
    {
        this.name = name;
        this.score = score;
    }
}

public class RankCell : MonoBehaviour
{

    public Text m_indexText;
    public Text m_nameText;
    public Text m_scoreText;

    /// <summary>
    /// 设置属性内容
    /// </summary>
    /// <param name="index"></param>
    /// <param name="name"></param>
    /// <param name="score"></param>
    public void UpdateCellData(int index, string name, float score)
    {
        m_indexText.text = index.ToString();
        m_nameText.text = name;
        m_scoreText.text = score.ToString();
    }
}
//核心类  
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class LoopScrollView : UIBehaviour
{
    /// <summary>
    /// 偏移值
    /// </summary>
    public float m_cellOffSetY;
    /// <summary>
    /// item的大小
    /// </summary>
    private Vector2 m_cellSize;
    private RankCell m_rankCellprefab;
    private ScrollRect m_scrollRect;
    private bool m_finishInit = false;
    private int m_visibleCellsRowCount;
    /// <summary>
    /// 总共显示生成的数量
    /// </summary>
    private int m_visibleCellsTotalCount;
    private int m_visiblePreFirstIndex;
    private int m_visibleFirstIndex;
    //private IList allData;
    private List<UserData> allData;
    private LinkedList<GameObject> m_Cells;

    protected override void Awake()
    {
        //设置个实例化的模板
        GameObject prefab = transform.Find("Viewport/Content/RankCellPrefab").gameObject;
        prefab.SetActive(false);
        m_rankCellprefab = prefab.GetComponent<RankCell>();

        RectTransform rt = m_rankCellprefab.GetComponent<RectTransform>();
        m_cellSize = rt.sizeDelta;

        m_scrollRect = GetComponent<ScrollRect>();
    }

    public void InitWithData(IList cellDataList)
    {
        allData = cellDataList as List<UserData>;
        Init();
    }

    public void Init()
    {
        if (!m_finishInit)
        {
            //实际显示(m_visibleCellsRowCount-1)个,剩下的两个作为上下滑动时的替换
            m_visibleCellsRowCount = (int)(m_scrollRect.viewport.rect.height / (m_cellSize.y + m_cellOffSetY)) + 1;
            m_visibleCellsTotalCount = (m_visibleCellsRowCount + 1);
            Debug.Log(m_visibleCellsRowCount + "---" + m_visibleCellsTotalCount);
            m_Cells = new LinkedList<GameObject>();

            for (int i = 0; i < m_visibleCellsTotalCount; i++)
            {
                GameObject go = Instantiate(m_rankCellprefab.gameObject, m_scrollRect.content.transform) as GameObject;
                go.name = i + "";
                go.SetActive(true);
                m_Cells.AddLast(go);
                SetCellPosition(go, i);
            }
        }
        UpdateContentSize();

        m_finishInit = true;
    }

    /// <summary>
    /// 设置item的位置
    /// </summary>
    /// <param name="go"></param>
    /// <param name="index"></param>
    void SetCellPosition(GameObject go, int index)
    {
        go.GetComponent<RectTransform>().anchoredPosition = new Vector2(0, -index * (m_cellSize.y + m_cellOffSetY));
        if (index >= 0 && index < allData.Count)
        {
            go.GetComponent<RankCell>().UpdateCellData(index + 1, allData[index].name, allData[index].score);
        }
    }

    /// <summary>
    /// 设置content大小
    /// </summary>
    void UpdateContentSize()
    {
        int cellOneWayCount = allData.Count;
        m_scrollRect.content.sizeDelta = new Vector2(m_scrollRect.content.sizeDelta.x,
            cellOneWayCount * m_cellSize.y + (cellOneWayCount - 1) * m_cellOffSetY);
    }

    private void Update()
    {
        if (m_finishInit)
        {
            CalculateIndex();
            UpdateCells();
        }
    }

    void CalculateIndex()
    {
        m_visibleFirstIndex = (int)(m_scrollRect.content.anchoredPosition.y / (m_cellSize.y + m_cellOffSetY));
        m_visibleFirstIndex = Mathf.Clamp(m_visibleFirstIndex, 0, m_visibleFirstIndex - 1);
    }

    void UpdateCells()
    {
        if (m_visiblePreFirstIndex != m_visibleFirstIndex)
        {
            bool scrollingDown = m_visiblePreFirstIndex < m_visibleFirstIndex;
            int indexDelta = Mathf.Abs(m_visiblePreFirstIndex - m_visibleFirstIndex);
            int deltaSign = scrollingDown ? +1 : -1;

            for (int i = 1; i <= indexDelta; i++)
                UpdateContent(m_visiblePreFirstIndex + i * deltaSign, scrollingDown);

            m_visiblePreFirstIndex = m_visibleFirstIndex;
        }
    }

    void UpdateContent(int index, bool scrollingPositive)
    {
        //Debug.Log(" index " + index + " scrollingPositive " + scrollingPositive);
        if (scrollingPositive)
        {
            LinkedListNode<GameObject> cell = m_Cells.First;
            cell.Value.gameObject.SetActive(false);
            m_Cells.RemoveFirst();
            SetCellPosition(cell.Value, index + m_visibleCellsRowCount);
            m_Cells.AddLast(cell);
            if (index + m_visibleCellsRowCount <= allData.Count - 1)
                cell.Value.gameObject.SetActive(true);
        }
        else
        {
            LinkedListNode<GameObject> cell = m_Cells.Last;
            cell.Value.gameObject.SetActive(false);
            m_Cells.RemoveLast();
            SetCellPosition(cell.Value, index);
            m_Cells.AddFirst(cell);
            if (index >= 0)
                cell.Value.gameObject.SetActive(true);
        }
    }
}

//启动类--模拟数据
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

public class GameMain : MonoBehaviour
{
    public LoopScrollView m_RankView;
    public int dataCount = 50;
    private List<UserData> userDatas = new List<UserData>();
    void Start()
    {
        SetData();
        m_RankView.InitWithData(userDatas);
    }

    /// <summary>
    /// 模拟一些已经排好顺序的数据
    /// </summary>
    void SetData()
    {
        userDatas.Clear();
        float score = 10000;
        UserData userData = null;
        string name;
        for (int i = 0; i < dataCount; i++)
        {
            name = GenerateChineseWord(Random.Range(1, 5));
            userData = new UserData(name, score);
            userDatas.Add(userData);
            score -= Random.Range(50, 200);
        }
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            dataCount = 50;
            SetData();
            m_RankView.InitWithData(userDatas);
            Debug.Log("设置50条数据");
        }
        else if (Input.GetKeyDown(KeyCode.D))
        {
            dataCount = 80;
            SetData();
            m_RankView.InitWithData(userDatas);
            Debug.Log("设置80条数据");
        }
    }
	//随机玩家名称
    public  string GenerateChineseWord(int count)
    {
        string chineseWords = "";
        Encoding gb = Encoding.GetEncoding("gb2312");
        for (int i = 0; i < count; i++)
        {
            // 获取区码(常用汉字的区码范围为16-55)
            int regionCode = Random.Range(16, 56);

            // 获取位码(位码范围为1-94 由于55区的90,91,92,93,94为空,故将其排除)
            int positionCode;
            if (regionCode == 55)
            {
                // 55区排除90,91,92,93,94
                positionCode = Random.Range(1, 90);
            }
            else
            {
                positionCode = Random.Range(1, 95);
            }

            // 转换区位码为机内码
            int regionCode_Machine = regionCode + 160;// 160即为十六进制的20H+80H=A0H
            int positionCode_Machine = positionCode + 160;// 160即为十六进制的20H+80H=A0H

            // 转换为汉字
            byte[] bytes = new byte[] { (byte)regionCode_Machine, (byte)positionCode_Machine };
            chineseWords += gb.GetString(bytes);
        }
        return chineseWords;
    }
}


效果图
在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值