步骤:
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; } }
效果图
发表评论 取消回复