制作流程
1.制作一个滑动预制体,打上标签UICompent
2.挂载AntVerticalScroll或者AntHorizontalScroll滑动组件
3.设置一行或一列滑动的item
4.创建Lua逻辑脚本和View视图脚本
5.在Lua逻辑脚本中require一个列表渲染组件XXXRender.lua
6.在列表渲染组件里在Require一个子项渲染组件XXXItemRender.lua
AntScroll抽象类
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
using XLua;
//抽象类
public abstract class AntScroll : ScrollRect
{
protected RectTransform rtf;
protected RectTransform _prefabItem;
#region abstracts
protected abstract float GetDimension(Vector2 vector); //获取维度
protected abstract float GetPos(Vector2 vector); //获取位置
protected abstract Vector2 GetVector(float value); //获取向量
#endregion
[HideInInspector]
public int dataCount;
private int _startIndex;
private int _endIndex;
//对象池~~
private List<RectTransform> _items;
private List<RectTransform> _pool;
private Queue<RectTransform> _poolFree;
private float _itemSize;
//private Vector2 _org;
[CSharpCallLua]
public delegate void RenderDelegate(int index, RectTransform tf,int tfIndex); //C#调用Lua,渲染委托,映射,三个形参
public RenderDelegate renderHandler; //渲染事件
[SerializeField]
public bool useObjectPool;
//private float _fixDirect;
protected override void Awake()
{
base.Awake();
if (Application.isPlaying == false)
return;
rtf = GetComponent<RectTransform>();
//_fixDirect = horizontal ? 1 : -1;
Init();
}
protected void Init()
{
List<RectTransform> listChild = new List<RectTransform>();
foreach (RectTransform child in content) //子节点content下的内容~
{
listChild.Add(child);
}
// Debug.Log("AntScroll listChild.Count ============================= " + listChild.Count);
for (int i = 0; i < listChild.Count; i++)
{
if (_prefabItem == null)
{
_prefabItem = listChild[i]; //content 对象 ~
_prefabItem.gameObject.SetActive(false); //content 对象 ~先设置不可见
}
else
{
Destroy(listChild[i].gameObject); //仙小灰
}
}
_itemSize = GetDimension(_prefabItem.sizeDelta); //此 RectTransform 相对于锚点之间距离的大小。实现类获取维度Vertor.y或.x
_startIndex = 0;
_endIndex = 0;
_items = new List<RectTransform>();
_pool = new List<RectTransform>();
_poolFree = new Queue<RectTransform>();
}
public GameObject GetPrefab()
{
return _prefabItem.gameObject;
}
protected override void Start()
{
base.Start();
if (Application.isPlaying == false)
return;
Refresh();
}
protected RectTransform GetPrefabItem(int index)
{
return _prefabItem;
}
public void SetCount(int value)
{
dataCount = value;
Debug.Log("SetCount C# " +dataCount);
if (horizontal)
content.sizeDelta = new Vector2(_prefabItem.sizeDelta.x * dataCount, content.sizeDelta.y);
else
{
// Debug.Log("_prefabItem " + _prefabItem);
content.sizeDelta = new Vector2(content.sizeDelta.x, _prefabItem.sizeDelta.y * dataCount);
}
Refresh();
}
/// <summary>
/// 刷新
/// </summary>
public void Refresh()
{
for (int i = 0; i < _pool.Count; i++)
_pool[i].gameObject.SetActive(false);
float py = 0;
if (_items.Count > 0)
py = GetPos(_items[0].anchoredPosition);
for (int i = _items.Count - 1; i > -1; i--)
RemoveFromItems(i);
float viewSize = GetDimension(rtf.sizeDelta);
if (_startIndex > dataCount)
{
_startIndex = 0;
py = 0f;
}
for (int i = _startIndex; i < dataCount; i++)
{
RectTransform newItem = CreateItem(i);
_items.Add(newItem);
newItem.anchoredPosition = GetVector(py);
_endIndex = i;
py = GetPos(newItem.anchoredPosition) + _itemSize;
if (GetPos(content.anchoredPosition) + py > viewSize)
{
break;
}
}
}
private Vector2 _contentLastAnchoredPosition;
/// <summary>
/// 设置Content的位置
/// </summary>
/// <param name="position"></param>
protected override void SetContentAnchoredPosition(Vector2 position)
{
base.SetContentAnchoredPosition(position);
if (_contentLastAnchoredPosition == content.anchoredPosition)
{
content.anchoredPosition = new Vector2((float)System.Math.Round(_contentLastAnchoredPosition.x, 2), (float)System.Math.Round(_contentLastAnchoredPosition.y, 2));
}
_contentLastAnchoredPosition = content.anchoredPosition;
if (_items == null || _items.Count == 0)
{
return;
}
RectTransform topItem = _items[0];
RectTransform bottomItem = _items[_items.Count - 1];
if (GetPos(content.anchoredPosition) + GetPos(topItem.anchoredPosition) > 0)
{
if (_startIndex > 0)
{
RectTransform newItem = CreateItem(_startIndex - 1);
newItem.anchoredPosition = GetVector(GetPos(topItem.anchoredPosition) - _itemSize);
newItem.SetSiblingIndex(0);
_startIndex--;
_items.Insert(0, newItem);
}
}
else if (GetPos(content.anchoredPosition) + GetPos(topItem.anchoredPosition) + _itemSize < 0)
{
if(_items.Count != 1)
{
_startIndex++;
RemoveFromItems(0);
}
}
topItem = _items[0];
bottomItem = _items[_items.Count - 1];
//Debug.Log((GetDimension(content.anchoredPosition) + GetPos(bottomItem.anchoredPosition) + _itemSize) + " " + GetDimension(rtf.sizeDelta));
if (GetPos(content.anchoredPosition) + GetPos(bottomItem.anchoredPosition) + _itemSize < GetDimension(rtf.sizeDelta))
{
if (_endIndex < dataCount - 1)
{
//float py = GetDimension(bottomItem.anchoredPosition + _fixDirect * bottomItem.sizeDelta / 2);
RectTransform newItem = CreateItem(_endIndex + 1);
newItem.anchoredPosition = GetVector(GetPos(bottomItem.anchoredPosition) + _itemSize);
_items.Add(newItem);
_endIndex++;
}
}
else if (GetPos(content.anchoredPosition) + GetPos(bottomItem.anchoredPosition) > GetDimension(rtf.sizeDelta))
{
if (_items.Count != 1)
{
RemoveFromItems(_items.Count - 1);
_endIndex--;
}
}
}
/// <summary>
/// 移除Item
/// </summary>
/// <param name="index"></param>
protected void RemoveFromItems(int index)
{
_items[index].gameObject.SetActive(false);
_poolFree.Enqueue(_items[index]); //队列入栈
_items.RemoveAt(index);
}
/// <summary>
/// 创建Item,加入对象池,并触发渲染事件
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
protected RectTransform CreateItem(int index)
{
RectTransform newItem = null;
if (_poolFree.Count > 0)
{
newItem = _poolFree.Dequeue(); //队列出栈
}
else
{
newItem = Instantiate(GetPrefabItem(index)) as RectTransform;
newItem.transform.SetParent(content.transform, false);
_pool.Add(newItem);
}
newItem.SetSiblingIndex(index);
newItem.gameObject.name = "item" + index;
newItem.gameObject.SetActive(true);
RenderHandler(index, newItem);
return newItem;
}
private void RenderHandler(int index, RectTransform tf)
{
Debug.Log("RenderHandler ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "+renderHandler);
if(renderHandler != null)
renderHandler(index, tf, _pool.IndexOf(tf));
}
}
EquipDemo.Lua逻辑脚本
equipDemo = {}
local UITable = require("UI/equip2/Base/equipDemoView")
local UIEquipScrollRender = require("UI/equip2/UIEquipScrollDemoRender")
UIEquipScrollRender.__index = UIEquipScrollRender
function equipDemo.Create()
local ui = {}
setmetatable(ui, {__index=UITable})
ui:Create()
ui.layer = 3
UI.LoadUI(ui)
return ui
end
function UITable:Awake()
self:StartInit()
self.oneLineNum = 3
self.CrewList1 = {}
self.CrewItemList1 = {}
self.EquipScroll.renderHandler = function (nIndex,tempTransRect,nIndexTrans)
self:CrewItemRenderHandel1(nIndex,tempTransRect,nIndexTrans)
end
self.equipId = ""
self:Init()
self:AddListener("chooseEquip",self.chooseEquip)
self:AddListener("reFreshEquipL",self.reFreshEquipL)
end
function UITable:Init()
self:RefEquip()
if GameMainData.nowequipId == "" then
self.nowequipName.gameObject:SetActive(false);
self.nowEquipPic.gameObject:SetActive(false);
self.nowAtk.gameObject:SetActive(false);
else
self.nowequipName.text = GameMainData.getWuqiByID(GameMainData.nowequipId).Name;
self.nowequipName.gameObject:SetActive(true);
self.nowEquipPic.gameObject:SetActive(true);
self.nowAtk.gameObject:SetActive(true);
self.nowAtk.text = "攻击力+" .. GameMainData.getWuqiByID(GameMainData.nowequipId).atk;
end
end
function UITable:RefEquip()
self.CrewList1 = GameMainData.EquipData
local nTotal = #self.CrewList1
local nLine = nTotal/self.oneLineNum
self.EquipScroll:SetCount(math.ceil(nLine))
end
function UITable:CrewItemRenderHandel1(nIndex,tempTransRect,nIndexTrans)
local nDataTotal = 0
local nNum = 0
if self.CrewItemList1[nIndexTrans] == nil then
self.CrewItemList1[nIndexTrans] = {}
setmetatable(self.CrewItemList1[nIndexTrans] ,UIEquipScrollRender)
self.CrewItemList1[nIndexTrans]:Init(tempTransRect)
end
nDataTotal = #self.CrewList1
for i=1,self.oneLineNum do
nNum = nIndex * self.oneLineNum + i
if nNum <= nDataTotal then
self.CrewItemList1[nIndexTrans].lineList[i]:SetData(self.CrewList1[nNum])
self.CrewItemList1[nIndexTrans].lineList[i].transform.gameObject:SetActive(true)
else
self.CrewItemList1[nIndexTrans].lineList[i].transform.gameObject:SetActive(false)
end
end
end
function UITable:SetData(v)
self.data=v
end
function UITable:Start()
self:StartInit()
end
function UITable:ButtonClickHandler(btn)
--LuaTools.PlaySound("btnsound")
if btn == self.equipTrue then --
self.equipMsg:SetActive(false)
GameMainData.nowequipId = self.nowSeeId
self:Init()
elseif btn == self.equipFalse then --
self.equipMsg:SetActive(false)
elseif btn == self.BtnClose then --
self:Close()
end
end
function UITable:chooseEquip(evtName,equipid) -- 选择装备 打开面板
self.equipMsg:SetActive(true)
self.nowSeeId = equipid;
self.equipMsg_name.text = GameMainData.getWuqiByID(equipid).Name;
self.equipMsg_Info.text = GameMainData.getWuqiByID(equipid).jieshao;
-- self:Init()
end
function UITable:reFreshEquipL(evtName,equipid)
self:RefEquip()
end
UIEquipScrollDemoRender.lua逻辑脚本 XXXScrollRender滑动逻辑脚本
local Render = UI.CreateRenderTable()
local UIEquipInfoRender = require("UI/equip2/UIEquipDemoItemRender")
UIEquipInfoRender.__index = UIEquipInfoRender
function Render:Awake()
self.lineList = {}
end
function Render:SetUICompent(child)
if child.name == "Item1" then
self:CreateItemRender(child)
elseif child.name == "Item2" then
self:CreateItemRender(child)
elseif child.name == "Item3" then
self:CreateItemRender(child)
end
end
function Render:CreateItemRender(tempTrans)
local tempRender = {}
setmetatable(tempRender,UIEquipInfoRender)
tempRender:Init(tempTrans)
table.insert(self.lineList, tempRender)
end
return Render
UIEquipDemoItemRender.lua逻辑脚本 XXXItemRender子项目渲染
local Render = UI.CreateRenderTable()
Render.chooseBeC = nil
function Render:SetUICompent(child)
if child.name == "beChoose" then -- 点某一个装备按钮
self.choose = child:GetComponent("Button")
self.choose.onClick:RemoveAllListeners()
self.choose.onClick:AddListener(function()
self:chooseB() -- 发消息通知装备模块打开装备详情
end)
elseif child.name == "zhuangbei" then -- 已经装备中的显示游戏体
self.zhuangbei = child.gameObject
end
end
function Render:SetData(v)
self.EquipData = v
self:RefreshEquipItem()
end
function Render:RefreshEquipItem()
if self.EquipData.ID == GameMainData.nowequipId then
self.zhuangbei:SetActive(true)
else
self.zhuangbei:SetActive(false)
end
end
function Render:chooseB() -- 发消息通知装备模块打开装备详情
Event.Call("chooseEquip",self.EquipData.ID)
end
return Render