正在忙别的东东,突然公司来了个需求,要加个什么无限滚动列表需求,再三确认,没错他就要这个(心想这玩意都烂大街,分分钟给你复制粘贴一个),然后就找啊找,找了一堆,没有找到正好对应需求的,然后找了个靠近需求的源码,改啊改,改啊改..... 我吐了!!!
思路:
1.无限滚动,Object肯定得重复利用 (位置循环)
2.保证循序正确,如果当前界面显示3个image,那我就生成9个image,canvas左边三个,右边三个,一摸一样的(因为我就三个数据,如果要是做成游戏那种无限滚动用来显示不用数据的,需要加个数据索引的集合,实时更新)
3.UGUI自带的scroll view 层级太多了,层级之间的引用看的头大(哈哈哈,底子不扎实)
制作:
1.ScrollDrog :继承拖拽接口,点击接口 (位置更新)
2.ChildLayout:只是为了子物体的布局,都是自己计算,现在只是定义了Item的大小和间距,还有其他的一些可以拓展
要点:初始化的时候记录所有子物体的位置,然后移动的时候检测有没有物体的位置大于最右边或者小于最左边的位置,然后更新位置
我是为了debug方便,给每个Item下面的text记录目标位置的索引,(这个是位置的索引,不是数据的索引,如果有需要的话自己加)
,Ondrag接口:这个只有在鼠标点下之后,有PointerEventData.delta(偏移)的时候调用
下面是代码:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using DG.Tweening;
public class ScrollDrog : UIBehaviour, IPointerUpHandler, IPointerDownHandler, IBeginDragHandler, IEndDragHandler, IDragHandler,IInitializePotentialDragHandler
{
public enum DropDirection {
Horizatal,
Verticle,
}
Vector2 delta;
public DropDirection dropDirection;
ChildLayout childLayout;
public void OnInitializePotentialDrag(PointerEventData eventData)
{
eventData.useDragThreshold = true;
}
public Action OnCustomStartDrop;
public Action OnCustomEndDrop;
public void OnBeginDrag(PointerEventData eventData)
{
}
public float speed;
public void OnDrag(PointerEventData eventData)
{
if (dropDirection== DropDirection.Horizatal)
{
//查找所有子物体移动
delta = eventData.delta;
delta.y = 0;
for (int i = 0; i < transform.childCount; i++)
{
transform.GetChild(i).GetComponent<RectTransform>().anchoredPosition += delta.normalized*Time.deltaTime*speed;
}
}
//跟新位置
Vector2 posMin = primitivePostion[0];
Vector2 posMax = primitivePostion[primitivePostion.Count - 1];
for (int i = 0; i < transform.childCount; i++)
{
RectTransform rectTrans = transform.GetChild(i).GetComponent<RectTransform>();
Vector2 pos = rectTrans.anchoredPosition;
if (pos.x< posMin.x &&Mathf.Abs(pos.x - posMin.x) > childLayout.cellSize.x)
{
transform.GetChild(i).GetComponent<RectTransform>().anchoredPosition = transform.GetChild(i).GetComponent<RectTransform>().anchoredPosition + new Vector2(transform.childCount * (childLayout.cellSize.x + childLayout.cellPadding.x), 0);
}
if (pos.x > posMax.x && Mathf.Abs(pos.x - posMax.x) > childLayout.cellSize.x)
{
transform.GetChild(i).GetComponent<RectTransform>().anchoredPosition = transform.GetChild(i).GetComponent<RectTransform>().anchoredPosition - new Vector2(transform.childCount * (childLayout.cellSize.x + childLayout.cellPadding.x), 0);
}
}
}
public void OnEndDrag(PointerEventData eventData)
{
for (int i = 0; i < transform.childCount; i++)
{
RectTransform rectTrans = transform.GetChild(i).GetComponent<RectTransform>();
string index = transform.GetChild(i).Find("Text").GetComponent<Text>().text;
//rectTrans.anchoredPosition = primitivePostion[int.Parse(index)];
//rectTrans.anchoredPosition =Vector2.SmoothDamp() primitivePostion[int.Parse(index)];
rectTrans.DOAnchorPos(primitivePostion[int.Parse(index)], 0.3f).SetEase(Ease.OutBounce).onComplete += () =>
{
rectTrans.anchoredPosition = primitivePostion[int.Parse(index)];
Debug.Log("isDoTweenAll.isDoTweenAll: " + i);
};
}
}
List<Vector2> primitivePostion;
protected override void Start()
{
base.Start();
childLayout = GetComponent<ChildLayout>();
childLayout.enabled = false;
primitivePostion = new List<Vector2>();
for (int i = 0; i < transform.childCount; i++)
{
primitivePostion.Add(transform.GetChild(i).GetComponent<RectTransform>().anchoredPosition);
transform.GetChild(i).Find("Text").GetComponent<Text>().text = i+"";
transform.GetChild(i).gameObject.name = i + "";
}
}
private void Update()
{
for (int i = 0; i < transform.childCount; i++)
{
RectTransform rectTrans = transform.GetChild(i).GetComponent<RectTransform>();
Vector2 pos = rectTrans.anchoredPosition;
int index = GetNearPos(pos);
transform.GetChild(i).Find("Text").GetComponent<Text>().text = index + "";
}
for (int i = 0; i < transform.childCount; i++)
{
RectTransform rectTrans = transform.GetChild(i).GetComponent<RectTransform>();
if (Mathf.Abs(rectTrans.anchoredPosition.x)<(childLayout.cellSize.x+childLayout.cellPadding.x))
{
float currentOffset= Mathf.Abs(rectTrans.anchoredPosition.x) - (childLayout.cellSize.x + childLayout.cellPadding.x);
float sFoctor= currentOffset / (childLayout.cellSize.x + childLayout.cellPadding.x);
float offset= (1- sFoctor);
rectTrans.localScale = Vector3.one* (offset);
}
else
{
rectTrans.localScale = Vector3.one;
}
Vector2 pos = rectTrans.anchoredPosition;
int index = GetNearPos(pos);
transform.GetChild(i).Find("Text").GetComponent<Text>().text = index + "";
}
}
float scale = 2;
/// <summary>
/// targetPos
/// </summary>
/// <param name="currentPos"></param>
/// <returns></returns>
int GetNearPos(Vector2 currentPos) {
int index = 0;
float xOffset= Mathf.Abs(primitivePostion[0].x - currentPos.x);
for (int i = 0; i < primitivePostion.Count; i++)
{
if (Mathf.Abs(primitivePostion[i].x-currentPos.x)<xOffset)
{
index = i;
xOffset = Mathf.Abs(primitivePostion[i].x - currentPos.x);
}
}
return index;
}
public void OnPointerDown(PointerEventData eventData)
{
if (OnCustomStartDrop != null)
{
OnCustomStartDrop();
}
}
public void OnPointerUp(PointerEventData eventData)
{
if (OnCustomEndDrop != null)
{
OnCustomEndDrop();
}
}
}
//=======================================================================================
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class ChildLayout : MonoBehaviour
{
// Start is called before the first frame update
public enum StartPosition {
Middle,
Left,
Right,
}
public StartPosition startPosition;
[Header("格子的大小")]
public Vector2 cellSize;
[Header("格子的间距")]
public Vector2 cellPadding;
public List<Vector2> p;
// Update is called once per frame
void Update()
{
if (Application.isPlaying)
{
return;
}
switch (startPosition)
{
case StartPosition.Middle:
List<Vector2> p = LayoutPositon();
for (int i = 0; i < transform.childCount; i++)
{
transform.GetChild(i).GetComponent<RectTransform>().sizeDelta = cellSize; //delta;
transform.GetChild(i).GetComponent<RectTransform>().anchoredPosition = p[i];
}
break;
case StartPosition.Left:
break;
case StartPosition.Right:
break;
default:
break;
}
}
List<Vector2> LayoutPositon() {
List<Vector2> pos = new List<Vector2>();
for (int i = 0; i < transform.childCount; i++)
{
pos.Add(new Vector2(i * (cellSize.x + cellPadding.x), transform.GetChild(i).GetComponent<RectTransform>().anchoredPosition.y));
}
//计算整体偏移
int offset = transform.childCount / 2;
for (int i = 0; i < pos.Count; i++)
{
Vector2 v2 = pos[i];
v2.x -= offset * (cellSize.x + cellPadding.x);
pos[i] = v2;
}
return pos;
}
}
ScrollViewDemo.rar-Unity3D文档类资源-CSDN下载
不多说了,研究shader去了