Unity笔记之下拉刷新列表
这样的效果;
代码:
using System;
using System.Collections;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ScrollRectUpdateViewBase<T> : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
{
private ScrollRect scrollRect;
[SerializeField] private RectTransform contentTransform;
[SerializeField] private ScrollRefreshInfo upRefreshInfo;
[SerializeField] private ScrollRefreshInfo downRefreshInfo;
[SerializeField] private GameObject item;
[SerializeField] private int onceRefreshCount = 10;
private Dictionary<GameObject, T> openDic = new Dictionary<GameObject, T>();
private List<T> remainList = new List<T>();
private List<T> allData = new List<T>();
private bool isUpRefresh;
private bool isDownRefresh;
private bool isRefreshing;
[SerializeField] [ReadOnly] float refreshNumber = 100;
[SerializeField] [ReadOnly] float canRefreshNumber = 50;
[SerializeField] [ReadOnly] float canShowRefreshNumber = 20;
private Action upAction;
private Action downAction;
public Action<GameObject, T> createItemFinish;
public Action<ScrollRectUpdateViewBase<T>> resetAction;
private void Awake()
{
this.scrollRect = this.GetComponent<ScrollRect>();
if (scrollRect == null) throw new NullReferenceException();
upRefreshInfo.ShowAndHideSelf(false);
downRefreshInfo.ShowAndHideSelf(false);
this.isUpRefresh = false;
this.isDownRefresh = false;
isRefreshing = false;
}
public void OnBeginDrag(PointerEventData eventData)
{
if (this.isRefreshing) return;
}
public void OnDrag(PointerEventData eventData)
{
if (this.isRefreshing) return;
var rectTransform = this.transform.GetComponent<RectTransform>();
float height = 0f;
var childCount = this.contentTransform.childCount;
var child = this.contentTransform.GetChild(1).GetComponent<RectTransform>();
if (this.contentTransform.TryGetComponent(out VerticalLayoutGroup group))
{
height = child.rect.height * (childCount - 2) + group.spacing * (childCount - 3) - rectTransform.rect.height;
}
else
height = child.rect.height * (childCount - 2) - rectTransform.rect.height;
var he = 0f;
if (this.allData.Count > this.onceRefreshCount)
he = this.contentTransform.anchoredPosition.y - height;
// Up
if (this.contentTransform.anchoredPosition.y < -0.5f && this.contentTransform.anchoredPosition.y < -canShowRefreshNumber)
{
this.upRefreshInfo.ShowAndHideSelf(true);
if (contentTransform.anchoredPosition.y >= -this.canRefreshNumber)
{
this.upRefreshInfo.SetContent("下拉可刷新");
this.isUpRefresh = false;
}
else if (contentTransform.anchoredPosition.y <= -this.refreshNumber)
{
this.upRefreshInfo.SetContent("释放后刷新");
this.isUpRefresh = true;
}
}
else
{
this.isUpRefresh = false;
this.upRefreshInfo.ShowAndHideSelf(false);
}
// down
if (he > 0.5f && he > canShowRefreshNumber)
{
this.downRefreshInfo.ShowAndHideSelf(true);
if (he <= this.canRefreshNumber)
{
this.downRefreshInfo.SetContent("上拉可刷新");
this.isDownRefresh = false;
}
else if (he >= this.refreshNumber)
{
this.downRefreshInfo.SetContent("释放后刷新");
this.isDownRefresh = true;
}
}
else
{
this.isDownRefresh = false;
this.downRefreshInfo.ShowAndHideSelf(false);
}
}
public void OnEndDrag(PointerEventData eventData)
{
if (this.isRefreshing) return;
if (this.isUpRefresh)
{
Debug.Log("开始刷新 Up");
StartCoroutine(RefreshUpData());
}
else if (this.isDownRefresh)
{
Debug.Log("开始刷新 Down");
StartCoroutine(RefreshDownData());
}
else
{
this.upRefreshInfo.ShowAndHideSelf(false);
this.downRefreshInfo.ShowAndHideSelf(false);
}
}
private IEnumerator RefreshUpData()
{
isRefreshing = true;
this.upRefreshInfo.SetContent("Up刷新中");
yield return new WaitForSeconds(2);
this.upRefreshInfo.SetContent("Up刷新成功");
yield return new WaitForSeconds(1);
this.upRefreshInfo.SetContent("Up释放后刷新");
// CheckIsNeedTran();
this.upRefreshInfo.ShowAndHideSelf(false);
this.isUpRefresh = false;
this.isDownRefresh = false;
isRefreshing = false;
}
private IEnumerator RefreshDownData()
{
isRefreshing = true;
this.downRefreshInfo.SetContent("Down刷新中");
yield return new WaitForSeconds(1);
var result = this.RefreshData();
if (result)
this.downRefreshInfo.SetContent("Down刷新成功");
else
this.downRefreshInfo.SetContent("没有更多数据了");
yield return new WaitForSeconds(1);
this.downRefreshInfo.SetContent("Down释放后刷新");
this.downRefreshInfo.ShowAndHideSelf(false);
this.isUpRefresh = false;
this.isDownRefresh = false;
isRefreshing = false;
}
void CheckIsNeedTran()
{
var tmp1 = this.downRefreshInfo.transform;
int siblingIndex = tmp1.GetSiblingIndex();
var count = (this.contentTransform.childCount) - siblingIndex;
if (count <= 0) return;
for (var i = 1; i < count; i++)
{
int ii = i + siblingIndex;
var child = this.contentTransform.GetChild(ii);
var index = child.GetSiblingIndex();
int index1 = tmp1.GetSiblingIndex();
child.SetSiblingIndex(index1);
tmp1.SetSiblingIndex(index);
}
}
public void RefreshInitData(List<T> list)
{
foreach (var openDicKey in this.openDic.Keys)
{
GameObject.Destroy(openDicKey);
}
allData = list;
remainList = new List<T>(list);
this.openDic = new Dictionary<GameObject, T>();
this.RefreshData();
}
private bool RefreshData()
{
int tmp = this.onceRefreshCount;
if (remainList.Count < 10)
{
tmp = remainList.Count;
}
if (this.remainList.Count == 0)
{
Debug.Log("已经全部刷新了");
return false;
}
for (int i = 0; i < tmp; i++)
{
var o = GameObject.Instantiate(this.item, this.item.transform.parent);
var remain = this.remainList[0];
o.SetActive(true);
this.openDic.Add(o, remain);
createItemFinish?.Invoke(o, remain);
this.remainList.RemoveAt(0);
}
CheckIsNeedTran();
return true;
}
// TODO: 充值好恶心啊啊啊啊啊啊啊啊啊啊啊
public void ResetData()
{
foreach (var openDicKey in this.openDic.Keys)
{
GameObject.Destroy(openDicKey);
}
resetAction?.Invoke(this);
}
}
ScrollRefreshInfo.cs
using TMPro;
using UnityEngine;
public class ScrollRefreshInfo : MonoBehaviour
{
private string oldStr;
[SerializeField] private GameObject imgRefresh;
[SerializeField] private TMP_Text txtContent;
public void SetContent(string str)
{
if (this.oldStr == str) return;
this.txtContent.text = str;
this.oldStr = str;
Debug.Log(str);
}
public void ShowAndHideSelf(bool isShow)
{
if (this.gameObject.activeSelf != isShow)
this.gameObject.SetActive(isShow);
}
}
场景:
就这些了。
哦对了,这个最好还是套一层,弄成泛型的,这样会好点
省事多了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!