using UnityEngine; using UnityEngine.UI; using System.Collections; using System.Collections.Generic; using System; using XLua; public class UIContainerBase : UIBase { // 容器每个Item的内容和位置 public class ContentPos { public Vector2 Pos; // 位置 public object Obj; // 显示信息 public UIItemBase ShowItem; // 显示脚本 - 内包含和 Obj 一样的显示信息 } void OnDisable() { _ContainerObj.anchoredPosition = Vector2.zero; } void OnEnable() { // 仅当Conten内容被重新设置过才执行初始化。 if (!_HasInit) { StartInitContainer(); } } #region calculate rect protected float _ViewPortWidth = 0; protected float _ViewPortHeight = 0; protected float _ContentCanvasWidth = 0; protected float _ContentCanvasHeight = 0; protected int _ContentRow = 0; protected int _ContentColumn = 0; protected int _ShowRowCount = 0; protected int _ShowColumnCount = 0; public int _InitItemCount = 0; private int _InitItemCountPrivate = 0; private void CalculateRect(ICollection items) { int itemCount = items.Count; _ViewPortWidth = _ScrollTransform.sizeDelta.x; _ViewPortHeight = _ScrollTransform.sizeDelta.y; _ContentColumn = 1; _ContentRow = 1; if (_LayoutGroup.constraint == GridLayoutGroup.Constraint.FixedRowCount) { _ContentColumn = _LayoutGroup.constraintCount; _ContentRow = itemCount / _ContentColumn; if (itemCount % _ContentColumn > 0) { ++_ContentRow; } } else if (_LayoutGroup.constraint == GridLayoutGroup.Constraint.FixedColumnCount) { _ContentRow = _LayoutGroup.constraintCount; _ContentColumn = itemCount / _ContentRow; if (itemCount % _ContentRow > 0) { ++_ContentColumn; } } _ValueList.Clear(); int i = 0; var enumerator = items.GetEnumerator(); enumerator.Reset(); while (enumerator.MoveNext()) //for (int i = 0; i < itemCount; ++i) { int column = i / _ContentRow; int row = i % _ContentRow; var contentPos = new ContentPos(); contentPos.Pos = new Vector2( row * (_LayoutGroup.cellSize.x + _LayoutGroup.spacing.x) + _LayoutGroup.cellSize.x * 0.5f, -column * (_LayoutGroup.cellSize.y + _LayoutGroup.spacing.y) - _LayoutGroup.cellSize.y * 0.5f); contentPos.Obj = enumerator.Current; _ValueList.Add(contentPos); ++i; } _ContentCanvasWidth = _LayoutGroup.cellSize.x * _ContentRow + _LayoutGroup.spacing.x * (_ContentRow - 1); _ContentCanvasHeight = _LayoutGroup.cellSize.y * _ContentColumn + _LayoutGroup.spacing.y * (_ContentColumn - 1); if (_BG != null) { _BG.rectTransform.sizeDelta = new Vector2(_ContentCanvasWidth + 20, _ContentCanvasHeight + 20); } if (_ContainerBaseLarge) { _ContentCanvasWidth = Math.Max(_ScrollTransform.sizeDelta.x, _ContentCanvasWidth); _ContentCanvasHeight = Math.Max(_ScrollTransform.sizeDelta.y, _ContentCanvasHeight); } _ShowRowCount = (int)Math.Ceiling((_ViewPortWidth + _LayoutGroup.spacing.x) / (_LayoutGroup.cellSize.x + _LayoutGroup.spacing.x)); _ShowColumnCount = (int)Math.Ceiling((_ViewPortHeight + _LayoutGroup.spacing.y) / (_LayoutGroup.cellSize.y + _LayoutGroup.spacing.y)); //_InitItemCount = _ShowColumnCount * _ShowRowCount; //_InitItemCount = Math.Min(_InitItemCount, itemCount); _ContainerObj.sizeDelta = new Vector2(_ContentCanvasWidth, _ContentCanvasHeight); float containerPosX = 0; float containerPosY = 0; if (_ContainerObj.sizeDelta.x < _ScrollTransform.sizeDelta.x) { containerPosX = (_ScrollTransform.sizeDelta.x - _ContainerObj.sizeDelta.x) * 0.5f; } if (_ContainerObj.sizeDelta.y < _ScrollTransform.sizeDelta.y) { containerPosY = (_ContainerObj.sizeDelta.y - _ScrollTransform.sizeDelta.y) * 0.5f; } _ContainerObj.transform.localPosition = new Vector3(containerPosX, containerPosY, 0); //LogModule.DebugLog("CalculateRect viewPortWidth:" + _ShowRowCount + "," + _ShowColumnCount + "," + _ContentCanvasWidth + "," + _ContentCanvasHeight); } #endregion #region public Vector3 GetItemPosition(object item) { foreach (UIItemBase uiItem in _ItemPrefabList) { if (uiItem._InitInfo == item) { return uiItem.transform.position; } } return Vector3.zero; } public Vector3 GetItemLocalPosition(UIItemBase item) { foreach (UIItemBase uiItem in _ItemPrefabList) { if (uiItem._InitInfo.Equals(item._InitInfo)) { return uiItem.transform.localPosition; } } return Vector3.zero; } #endregion public ScrollRect _ScrollRect; // 滑动框组件 public RectTransform _ScrollTransform; // 滑动框组件Rt public GridLayoutGroup _LayoutGroup; // 自动布局组件 public GameObject _ContainItemPre; // Item预设体 public RectTransform _ContainerObj; // 自身容器Rt public Image _BG; public bool _ContainerBaseLarge = false; protected List _ItemPrefabList = new List(); protected List _ValueList = new List(); // 内容的数组 protected UIItemBase.ItemClick _OnClickItem; // 单个内容Item点击回调 protected UIItemBase.PanelClick _OnClickPanel; // ... public int GetValueCnt() { return _ValueList.Count; } public void SetValueObjByIndex(int index, object initInfo) { if(index < _ValueList.Count) { _ValueList[index].Obj = initInfo; _ItemPrefabList[index]._InitInfo = initInfo; Hashtable param = new Hashtable(); param.Add("InitObj", initInfo); _ValueList[index].ShowItem.Show(param); } } public delegate void ShowItemFinish(); protected ShowItemFinish m_ShowItemFinish = null; public void SetShowItemFinishCallFun(ShowItemFinish fun) { m_ShowItemFinish = fun; } public void SetLayoutPosotion(int index) { if(_LayoutGroup!=null) { _LayoutGroup.transform.localPosition = new Vector3(_LayoutGroup.transform.position.x, _LayoutGroup.cellSize.y * index, _LayoutGroup.transform.position.z); } } public int GetItemCount() { return _ValueList.Count; } protected Hashtable _ExHash; private bool _HasInit = false; //[CSharpCallLua] public virtual void InitContentItem(IEnumerable valueList, UIItemBase.ItemClick onClick = null, Hashtable exhash = null, UIItemBase.PanelClick onPanelClick = null) { _InitItemCountPrivate = _InitItemCount; //CalculateRect(valueList); _ValueList.Clear(); //ClearPrefab(); int i = 0; if (valueList == null) { ClearPrefab(); return; } var enumerator = valueList.GetEnumerator(); enumerator.Reset(); while (enumerator.MoveNext()) { var contentPos = new ContentPos(); contentPos.Obj = enumerator.Current; _ValueList.Add(contentPos); ++i; } if (_InitItemCountPrivate <= 0) { _InitItemCountPrivate = 30; } _InitItemCountPrivate = Math.Min(_InitItemCountPrivate, _ValueList.Count); _HasInit = false; _OnClickItem = onClick; _OnClickPanel = onPanelClick; _ExHash = exhash; if (isActiveAndEnabled) { StartInitContainer(); } //_LayoutGroup.enabled = false; } // For lua public void InitContentItemL2L(List valueList, UIItemBase.ItemClick onClick = null, Hashtable exhash = null, UIItemBase.PanelClick onPanelClick = null) { InitContentItem(valueList, onClick, exhash, onPanelClick); } public void StartInitContainer() { _HasInit = true; if (_ValueList.Count > 0) { StartCoroutine(InitItems(_ExHash)); } else { ClearPrefab(); } } public virtual void ShowItems() { } public virtual void ShowItemsFinish() { if (m_ShowItemFinish != null) m_ShowItemFinish.Invoke(); WindowSign wnd = gameObject.GetComponentInParent(); if (wnd != null) wnd.SetWndDirty(); } private bool IsPosInView(ContentPos pos) { return (_ContainerObj.localPosition.x + pos.Pos.x >= -_LayoutGroup.cellSize.x * 0.5f && _ContainerObj.localPosition.x + pos.Pos.x <= _ViewPortWidth + _LayoutGroup.cellSize.x * 0.5f && -_ContainerObj.localPosition.y - pos.Pos.y >= -_LayoutGroup.cellSize.y * 0.5f && -_ContainerObj.localPosition.y - pos.Pos.y <= _ViewPortHeight + _LayoutGroup.cellSize.y * 0.5f); } private void InitItem(ContentPos contentItem, UIItemBase preItem, Hashtable exhash) { preItem.gameObject.SetActive(true); //preItem.transform.localPosition = new Vector3(contentItem.Pos.x, contentItem.Pos.y, 0); //if (preItem._InitInfo != contentItem.Obj) { Hashtable hash; if (exhash == null) { hash = new Hashtable(); } else { hash = new Hashtable(exhash); } hash.Add("InitObj", contentItem.Obj); preItem.Show(hash); preItem._InitInfo = contentItem.Obj; preItem._ClickEvent = _OnClickItem; preItem._PanelClickEvent = _OnClickPanel; contentItem.ShowItem = preItem; } } public virtual void RefreshItems() { foreach (var item in _ItemPrefabList) { item.Refresh(); } } public virtual void RefreshItems(Hashtable hash) { foreach (var item in _ItemPrefabList) { item.Refresh(hash); } } public void PreLoadItem(int preLoadCount) { InitItems(null); } private void ClearPrefab() { foreach (var prefab in _ItemPrefabList) { //prefab.transform.localPosition = new Vector3(1000, 1000, 1); prefab.Hide(); prefab._InitInfo = null; } } private IEnumerator InitItems(Hashtable exhash) { //先初始化可见 //var itemPrefabList = _ContainerObj.GetComponentsInChildren(); //_ItemPrefabList = new List(itemPrefabList); //ClearPrefab(); if (_InitItemCountPrivate > _ItemPrefabList.Count) { for (int i = _ItemPrefabList.Count; i < _InitItemCountPrivate; ++i) { GameObject obj = GameObject.Instantiate(_ContainItemPre); obj.transform.SetParent(_ContainerObj.transform); obj.transform.localScale = Vector3.one; obj.transform.localPosition = Vector3.zero; obj.name = _ContainItemPre.name + _ItemPrefabList.Count; var itemScript = obj.GetComponent(); //itemScript.Hide(); _ItemPrefabList.Add(itemScript); //_EmpeyItemPrefab.Enqueue(itemScript); } } for (int i = 0; i < _InitItemCountPrivate; ++i) { InitItem(_ValueList[i], _ItemPrefabList[i], exhash); } if (_ItemPrefabList.Count > _ValueList.Count) { for (int i = _ValueList.Count; i < _ItemPrefabList.Count; ++i) { _ItemPrefabList[i].Hide(); } } if (_InitItemCountPrivate >= _ValueList.Count) { ShowItemsFinish(); yield break; } yield return new WaitForFixedUpdate(); int nextNeedCount = _ValueList.Count - _InitItemCountPrivate; if (nextNeedCount > 0) { int needCreateCount = nextNeedCount - (_ItemPrefabList.Count - _InitItemCountPrivate); for (int i = 0; i < needCreateCount; ++i) { GameObject obj = GameObject.Instantiate(_ContainItemPre); obj.transform.SetParent(_ContainerObj.transform); obj.transform.localScale = Vector3.one; obj.transform.localPosition = Vector3.zero; var itemScript = obj.GetComponent(); //itemScript.Hide(); _ItemPrefabList.Add(itemScript); //_EmpeyItemPrefab.Enqueue(itemScript); } for (int i = _InitItemCountPrivate; i < _ValueList.Count; ++i) { InitItem(_ValueList[i], _ItemPrefabList[i], exhash); } } if (_ItemPrefabList.Count > _ValueList.Count) { for (int i = _ValueList.Count; i < _ItemPrefabList.Count; ++i) { _ItemPrefabList[i].Hide(); } } ShowItemsFinish(); } public T GetContainItem(int idx) { return _ItemPrefabList[idx].GetComponent(); } public void ForeachActiveItem(Action action) { for (int i = 0; i < _ItemPrefabList.Count; ++i) { if (_ItemPrefabList[i].gameObject.activeSelf) { var component = _ItemPrefabList[i].gameObject.GetComponent(); if (component == null) continue; action(component); } } } public virtual void ForeachActiveBaseItemL2L(Action action) { ForeachActiveItem(action); } public Vector3 GetObjItemPos(object obj) { foreach (var item in _ItemPrefabList) { if (item._InitInfo == obj) { return item.transform.position; } } return Vector3.zero; } }