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;
///
/// 模拟玩家数据
///
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;
///
/// 设置属性内容
///
///
///
///
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
{
///
/// 偏移值
///
public float m_cellOffSetY;
///
/// item的大小
///
private Vector2 m_cellSize;
private RankCell m_rankCellprefab;
private ScrollRect m_scrollRect;
private bool m_finishInit = false;
private int m_visibleCellsRowCount;
///
/// 总共显示生成的数量
///
private int m_visibleCellsTotalCount;
private int m_visiblePreFirstIndex;
private int m_visibleFirstIndex;
//private IList allData;
private List allData;
private LinkedList m_Cells;
protected override void Awake()
{
//设置个实例化的模板
GameObject prefab = transform.Find("Viewport/Content/RankCellPrefab").gameObject;
prefab.SetActive(false);
m_rankCellprefab = prefab.GetComponent();
RectTransform rt = m_rankCellprefab.GetComponent();
m_cellSize = rt.sizeDelta;
m_scrollRect = GetComponent();
}
public void InitWithData(IList cellDataList)
{
allData = cellDataList as List;
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();
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;
}
///
/// 设置item的位置
///
///
///
void SetCellPosition(GameObject go, int index)
{
go.GetComponent().anchoredPosition = new Vector2(0, -index * (m_cellSize.y + m_cellOffSetY));
if (index >= 0 && index < allData.Count)
{
go.GetComponent().UpdateCellData(index + 1, allData[index].name, allData[index].score);
}
}
///
/// 设置content大小
///
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 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 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 userDatas = new List();
void Start()
{
SetData();
m_RankView.InitWithData(userDatas);
}
///
/// 模拟一些已经排好顺序的数据
///
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;
}
}