BasePanel.cs 5.82 KB
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;

public abstract class BasePanel<T> : MonoBehaviour where T : struct
{
    /// <summary>
    /// 实例化的预设体
    /// </summary>
    [SerializeField] private GameObject itemPrefab;

    /// <summary>
    /// item面板的父物体
    /// </summary>
    [SerializeField] private Transform itemContainer;

    /// <summary>
    /// 存放实例化的Item列表
    /// </summary>
    [SerializeField] protected List<BaseItem<T>> objItemList = new List<BaseItem<T>>();

    /// <summary>
    ///  行列数
    /// </summary>
    [SerializeField] private int itemsPerRow = 1;

    [SerializeField] protected Vector2 itemSize;
    [SerializeField] protected Vector2 itemSpacing = new Vector2(10, 10);

    /// <summary>
    /// 选中得Item
    /// </summary>
    private BaseItem<T> selectItem = null;

    /// <summary>
    /// 初始化面板
    /// </summary>
    /// <param name="dataList">列表数据</param>
    protected void InitPanel(List<T> dataList)
    {
        if (dataList.Count == 0)
        {
            Debug.LogError("面板数据为空");
            return;
        }

        ClearPanel();
        CreatItem(dataList);
    }

    /// <summary>
    /// 清空面板
    /// </summary>
    private void ClearPanel()
    {
        if (objItemList.Count != 0)
        {
            for (int i = 0; i < objItemList.Count; i++)
            {
                if (objItemList[i] != null)
                {
                    // 取消委托
                    objItemList[i].OnItemClick -= ItemClickCallBack;
                    Destroy(objItemList[i]);
                }
            }

            objItemList.Clear();
        }
    }

    /// <summary>
    /// 创建Item
    /// </summary>
    private void CreatItem(List<T> dataList)
    {
        for (int i = 0; i < dataList.Count; i++)
        {
            var obj = Instantiate(itemPrefab, itemContainer);
            var item = obj.GetComponent<BaseItem<T>>();
            if (item != null)
            {
                itemSize = item.gameObject.GetComponent<RectTransform>().sizeDelta;
                item.SetupData(dataList[i]);
                item.SetSelected(i == 0);
                item.OnItemClick += ItemClickCallBack;
                objItemList.Add(item);
            }
            else
            {
                Debug.LogError("面板Item实例化找不到对应组件");
                Destroy(obj);
            }
        }

        UpdateLayout();
    }

    /// <summary>
    /// 更新一下Item布局
    /// </summary>
    private void UpdateLayout()
    {
        if (objItemList.Count <= 0)
        {
            Debug.LogError("面板内Item列表内数据为空");
            return;
        }

        for (int i = 0; i < objItemList.Count; i++)
        {
            // 计算行列
            int row = i / itemsPerRow;
            int col = i % itemsPerRow;

            if (itemSize.x <= 0 || itemSize.y <= 0)
            {
                Debug.LogError("当前面板布局内的Item未获得实际大小");
                break;
            }

            // 计算位置
            float xPos = col * (itemSize.x + itemSpacing.x);
            float yPos = -row * (itemSize.y + itemSpacing.y); // 负号表示向下排列

            // 设置项位置和大小
            objItemList[i].SetPosition(new Vector3(xPos, yPos, 0));
        }
    }

    /// <summary>
    /// 刷新面板数据
    /// </summary>
    /// <param name="datas">新数据列表</param>
    public virtual void RefreshPanel(List<T> data)
    {
        // 数据保持不表
        if (data.Count == objItemList.Count)
        {
            // 直接循环更新
            for (int i = 0; i < objItemList.Count; i++)
            {
                objItemList[i].SetupData(data[i]);
                objItemList[i].SetSelected(i == 0);
            }
        }

        if (data.Count < objItemList.Count)
        {
            // 多余得直接隐藏
            for (int i = 0; i < objItemList.Count; i++)
            {
                if (i < data.Count)
                {
                    objItemList[i].SetupData(data[i]);
                    objItemList[i].SetSelected(i == 0);
                }
                else
                {
                    objItemList[i].gameObject.SetActive(false);
                }
            }
        }

        if (data.Count > objItemList.Count)
        {
            for (int i = 0; i < data.Count; i++)
            {
                if (i < objItemList.Count)
                {
                    objItemList[i].gameObject.SetActive(true);
                    objItemList[i].SetupData(data[i]);
                }
                else
                {
                    // 多出来得直接重新从创建
                    var obj = Instantiate(itemPrefab, itemContainer);
                    var item = obj.GetComponent<BaseItem<T>>();
                    if (item != null)
                    {
                        itemSize = item.gameObject.GetComponent<RectTransform>().sizeDelta;
                        item.SetupData(data[i]);
                        item.SetSelected(i == 0);
                        item.OnItemClick += ItemClickCallBack;
                        objItemList.Add(item);
                    }
                }
            }
        }

        UpdateLayout();
    }

    /// <summary>
    /// item得点击事件得 委托方法
    /// </summary>
    /// <param name="clickItem"></param>
    private void ItemClickCallBack(BaseItem<T> clickItem)
    {
        if (selectItem == null)
        {
            objItemList[0].SetSelected(false);
        }

        if (selectItem != null && selectItem != clickItem)
        {
            selectItem.SetSelected(false);
        }

        selectItem = clickItem;
        selectItem.SetSelected(true);
    }
}