using UnityEngine; using System.Collections; using System.Collections.Generic; using System.Text; using System; namespace Thousandto.Plugins.Common { /// /// ListView,单列排版的滑动列表,支持不等高度的自动排版 /// 示例可以参考UIServerListFormScript /// public class UIListView : MonoBehaviour { const float DURATION = 0.5f; #region 公共成员 public UIScrollView ScrollView = null; public float LerpDuration = DURATION; public bool Initialized = false; public float Offset = 50f; //默认缩放动画 public bool EnableEffect = true; #endregion #region 私有成员 private UIPanel _panel = null; //最初的偏移 private Vector4 _originalClipOffset = Vector4.zero; //最初的位置 private Vector3 _originalPos = Vector3.zero; //下方最终位置,向上滑动时,如果下方需要补新的item, 坐标从_bottomPos开始算 private Vector3 _bottomPos = Vector3.zero; //上方最终位置,向下滑动时,如果上方需要补新的item,坐标从_topPos开始算 private Vector2 _topPos = Vector2.zero; //需要移动的距离 //private Vector2 _moveAmount = Vector2.zero; //跟节点的上一次变换后的位置 private Vector3 _lastRootPos = Vector3.zero; private Vector2 _lastClipOffset = Vector2.zero; //滑动窗口尺寸 private Vector2 _scrollViewSize = Vector2.zero; private Vector2 _autoMoveDistance = Vector2.zero; //添加新的item后,transform需要移动到的目标位置 private Vector3 _rootMoveToPos = Vector3.zero; //添加新的item后,裁剪区域偏移量需要改变到的目标值 private Vector2 _rootEndClipOffset = Vector2.zero; //边界模糊区域 private Vector2 _softClipOffset = Vector2.zero; //ScrollView的边界 private Bounds _bounds; private Transform _transform = null; //在添加了新的item或者滑动区域后需要重新计算边界 private bool _calclateBounds = false; //添加新item后,自动滑动 private bool _enableSmoothMove = false; //插值时长 private float _lerpTimer = 0; //保存临时Item的节点 private Transform _cacheRootTrans = null; //--------------下面几个变量用于调用Show方法刷新面板所用 //是否调用show方法显示列表 private bool _isCallShowFunc = false; private bool _endShow = false; //调用show时,记录下沿Y坐标 private float _bottomClipPosOnShow = 0; //显示的索引 private int _showIndex = 0; //------------------------------------------------------ #endregion #region 数据 private List _showingList = new List(); private ItemHolder _itemHolder = null; private ListItemAdapter _adapter; //顶部的item private ItemHolder _topItemHolder; //底部的item private ItemHolder _bottomItemHolder; private int _lastIndex = 0; //新需要展示消息 private int _newItemCount = 0; //item间距 private float _spaceY = 10; private int _curChannel = -1; #endregion #region 属性 //当前窗口的边界 private Bounds mBounds { get { if (!_calclateBounds) { _calclateBounds = true; _bounds = GetBounds(transform); } return _bounds; } } public bool EnableSmoothMove { get { return _enableSmoothMove; } } #endregion #region Mono生命周期 void Awake() { _transform = transform; ScrollView = GetComponent(); _panel = ScrollView.panel; _scrollViewSize = ScrollView.panel.GetViewSize(); _originalClipOffset = _panel.clipOffset; _originalPos = transform.localPosition; if (ScrollView.panel.clipping == UIDrawCall.Clipping.SoftClip) { _softClipOffset.y = _panel.clipSoftness.y; _softClipOffset.x = _panel.clipSoftness.x; } InitTopAndBottomPos(); //事件注册 ScrollView.onDragStarted = onDragStarted; ScrollView.onDragFinished = onDragFinished; ScrollView.onStoppedMoving = onStoppedMoving; ScrollView.panel.onClipMove = onDragMove; //自动创建保存Item的节点 GameObject cacheTempGo = new GameObject("[CacheScrollItem]"); _cacheRootTrans = cacheTempGo.transform; _cacheRootTrans.parent = transform.parent; Clear(); } //void Update() //{ //} private void LateUpdate() { RefreshWhileNewItem(); if (_dragging) { //UnityEngine.Debug.LogError("点击了拖动直接返回不移动滑动列表!!!!!"); return; } //onDragMove(null); if (!_enableSmoothMove) { //UnityEngine.Debug.LogError("滑动列表的SmoothMove状态是关闭的!!!!!"); return; } _lerpTimer += Time.deltaTime / LerpDuration; SmoothMove(_lerpTimer); if (_lerpTimer > 1) { _lerpTimer = 0; _enableSmoothMove = false; } } #if UNITY_EDITOR void OnDrawGizmos() { Vector4 clip = ScrollView.panel.finalClipRegion; if (Input.mousePosition.y - _lastMousePos.y >= 0) _dragMoveDown = false; else _dragMoveDown = true; Bounds b = GetBounds(transform); float hx = clip.z * 0.5f; float hy = clip.w * 0.5f; //裁剪区域的上沿Y坐标 var topClipPos = clip.y + hy; //下沿Y坐标 var bottomClipPos = clip.y - hy; var TopItemOutOfRegion = GetTopItemOutOfClipRegion(topClipPos); var TopItemInView = GetTopItemInClipRegion(); var BottomItemOutOfRegion = GetBottomItemOutOfClipRegion(bottomClipPos); var BottomItemInView = GetBottomItemInClipRegion(); Gizmos.color = Color.red; if (TopItemOutOfRegion != null) { Gizmos.DrawLine(ScrollView.transform.TransformPoint(new Vector2(0, TopItemOutOfRegion.TopAndBottom.y)), ScrollView.transform.TransformPoint((new Vector2(50 * 5, TopItemOutOfRegion.TopAndBottom.y)))); UnityEditor.Handles.Label(ScrollView.transform.TransformPoint((new Vector2(50 * 5 + 10, TopItemOutOfRegion.TopAndBottom.y))), "TopItemOutOfRegion-" + TopItemOutOfRegion.Object.name); } Gizmos.color = Color.green; if (TopItemInView != null) { Gizmos.DrawLine(ScrollView.transform.TransformPoint(new Vector2(0, TopItemInView.TopAndBottom.x)), ScrollView.transform.TransformPoint((new Vector2(50 * 5, TopItemInView.TopAndBottom.x)))); UnityEditor.Handles.Label(ScrollView.transform.TransformPoint((new Vector2(50 * 5 + 10, TopItemInView.TopAndBottom.x))), "TopItemInView-" + TopItemInView.Object.name); } Gizmos.color = Color.blue; if (BottomItemInView != null) { Gizmos.DrawLine(ScrollView.transform.TransformPoint(new Vector2(0, BottomItemInView.TopAndBottom.y)), ScrollView.transform.TransformPoint((new Vector2(50 * 5, BottomItemInView.TopAndBottom.y)))); UnityEditor.Handles.Label(ScrollView.transform.TransformPoint((new Vector2(50 * 5 + 10, BottomItemInView.TopAndBottom.y))), "BottomItemInView-" + BottomItemInView.Object.name); } Gizmos.color = Color.black; if (BottomItemOutOfRegion != null) { Gizmos.DrawLine(ScrollView.transform.TransformPoint(new Vector2(0, BottomItemOutOfRegion.TopAndBottom.x)), ScrollView.transform.TransformPoint((new Vector2(50 * 5, BottomItemOutOfRegion.TopAndBottom.x)))); UnityEditor.Handles.Label(ScrollView.transform.TransformPoint((new Vector2(50 * 5 + 10, BottomItemOutOfRegion.TopAndBottom.x))), "BottomItemOutOfRegion-" + BottomItemOutOfRegion.Object.name); } } #endif #endregion #region 公共功能函数 public List GetShowList() { return _showingList; } public void SetAdapter(ListItemAdapter adapter) { _adapter = adapter; Initialized = true; } public void SetSpaceY(float space) { _spaceY = space; } public void SetChannel(int channel) { _curChannel = channel; } /// /// 显示若干item,直到超出可视窗 /// /// 采用倒序获取数据 /// public void Show(bool moveDown = false) { _isCallShowFunc = true; _showIndex = 0; var clip = ScrollView.panel.finalClipRegion; float hy = clip.w * 0.5f; //下沿Y坐标 _bottomClipPosOnShow = clip.y - hy; //_panel.onClipMove = null; //int dataCount = _adapter.GetCount(); //for(int i = 0; i < dataCount; ++i) //{ // var view = _adapter.GetView(i, null); // view.Index = i; // if(i == 0) // { // _topItemHolder = view; // } // AddItem(view, false); // _showingList.Add(view); // if (_bottomClipPosOnShow - _bottomPos.y > view.Bounds.size.y + Offset) // { // _lastIndex = i; // _bottomItemHolder = view; // break; // } //} if (!moveDown) _enableSmoothMove = false; } public void ShowReverse(int channel = -1) { //这里要设置为0,避免切换频道有滑动操作 ScrollView.currentMomentum = Vector2.zero; _dragging = false; var clipRegion = ScrollView.panel.finalClipRegion; InitTopAndBottomPos(false); if (channel == -1) { int dataCount = _adapter.GetCount(); for (int i = dataCount - 1; i >= 0; --i) { var view = _adapter.GetView(i, null); view.Index = i; if (i == dataCount - 1) { _bottomItemHolder = view; } AddItem(view, true); _showingList.Insert(0, view); _topItemHolder = view; if (_topPos.y - _bottomPos.y > clipRegion.w + Offset) { _lastIndex = i; break; } } } else { List indexList = _adapter.GetIndexs(channel); for (int i = indexList.Count -1; i >= 0; i--) { var view = _adapter.GetView(indexList[i], null); view.Index = indexList[i]; if (i == indexList.Count - 1) { _bottomItemHolder = view; } AddItem(view, true); _showingList.Insert(0, view); _topItemHolder = view; if (_topPos.y - _bottomPos.y > clipRegion.w + Offset) { _lastIndex = i; break; } } } SmoothMove(1); //这个脚本导致切换聊天时,如果有滑动操作,新频道内容位置显示异常 var sp = transform.GetComponent(); if (sp != null) { sp.target = Vector3.zero; sp.enabled = false; } } private float _addItemDeltaTime = 0; //当有新item添加到数据源后触发,需要手动调用 public bool OnAddItem() { if (_dragging) return false; //上下方如果有超出框的item存在,则不添加新的item if ((GetBottomItemOutOfClipRegion() != null/* && GetTopItemOutOfClipRegion() != null*/)) { var topItem = GetTopItemInClipRegion(); if(topItem != null && topItem.Index != 0) return false; } if(GetTopItemInClipRegion() == null) { ScrollView.ResetPosition(); } //_newItemCount++; ShowNewItem(); if (_addItemDeltaTime == 0) _addItemDeltaTime = Time.realtimeSinceStartup; else { var deltaTime = Time.realtimeSinceStartup - _addItemDeltaTime; if (deltaTime < DURATION) { LerpDuration = deltaTime; } else { LerpDuration = DURATION; } _addItemDeltaTime = Time.realtimeSinceStartup; } return true; } public void ShowNewItem() { var holder = AddItemFromCacheParent(GetTopItemOutOfClipRegion(), false, GetBottomItemInClipRegion()); if (holder == null) return; //对新加入的item,播放缩放动画 PlayScaleEffect(holder); } public bool RefreshWhileNewItem() { //每5帧刷新界面 //if (Time.frameCount % 5 != 0) // return; if(_isCallShowFunc) { if (Time.frameCount % 5 != 0) { return true; } if (_endShow) { _isCallShowFunc = false; _endShow = false; //_panel.onClipMove = onDragMove; return true; } var view = _adapter.GetView(_showIndex, null); if (view != null) { view.Index = _showIndex; if (_showIndex == 0) { _topItemHolder = view; } AddItem(view, false); _showingList.Add(view); if (_bottomClipPosOnShow - _bottomPos.y > view.Bounds.size.y + Offset) { _lastIndex = _showIndex; _bottomItemHolder = view; _showIndex = 0; _endShow = true; } else _showIndex++; //对新加入的item,播放缩放动画 PlayScaleEffect(view); } else _endShow = true; } else { if (_newItemCount > 0) { _newItemCount--; ShowNewItem(); return true; } } return false; } public ItemHolder RemoveAtIndex(int index, bool fromFirst = true, bool forceRemove = false) { if (_showingList.Count == 0) return null; ItemHolder ret = null; if (forceRemove) { ret = fromFirst ? _showingList[0] : _showingList[_showingList.Count - 1]; _showingList.RemoveAt(fromFirst ? 0 : _showingList.Count - 1); return ret; } if (fromFirst) { //从上到下、从前往后查找 for(int i = 0; i < _showingList.Count; ++i) { //找到指定item,删除,其后的item的index需要递减 if (_showingList[i].Index == index) { ret = _showingList[i]; _showingList.RemoveAt(i); i--; _topPos.y = ret.TopAndBottom.y; } else if (_showingList[i].Index > index) { _showingList[i].Index--; } } if(ret != null) { //删除顶部item,需要重新对齐 if (GetTopItemOutOfClipRegion() == null) { SetClipRegionMoveOffset(ret.TopAndBottom.y); //AddItemFromCacheParent(ret, false, _showingList[_showingList.Count - 1]); } } } else { ret = _showingList[_showingList.Count - 1]; _showingList.RemoveAt(_showingList.Count - 1); for(int i = _showingList.Count - 1; i >= 0; --i) { if(_showingList[i].Index == index) { ret = _showingList[i]; _showingList.RemoveAt(i); _bottomPos.y = ret.TopAndBottom.x; break; } else _showingList[i].Index--; } } return ret; } public void SetAfterItemPos(ItemHolder holder) { bool isAfter = false; List tempList = new List(); for (int i = 0; i < _showingList.Count; i++) { var item = _showingList[i]; if (!isAfter) { if (_showingList[i] == holder) { isAfter = true; } } else { tempList.Add(item); } } float curSizeY = GetBounds(holder.Object).size.y; float offsetY = curSizeY - holder.Param; holder.Param = curSizeY; for (int i = 0; i < tempList.Count; i++) { var item = tempList[i]; if (item != null) { item.Object.localPosition = new Vector3(item.Object.localPosition.x, item.Object.localPosition.y - offsetY, item.Object.localPosition.z); var bounds = GetBounds(ScrollView.transform, item.Object); item.TopAndBottom.x = bounds.max.y; item.TopAndBottom.y = bounds.min.y; item.Size = bounds.size; } } //同步bottomPos的坐标 //_bottomPos.y var bottomItem = _showingList[_showingList.Count - 1]; _bottomPos.y = bottomItem.TopAndBottom.y; _bottomPos.y -= _spaceY; } public void Clear() { if (ScrollView == null) return; _showingList.Clear(); InitTopAndBottomPos(); _enableSmoothMove = false; _panel.clipOffset = _originalClipOffset; transform.localPosition = _originalPos; } #endregion #region 回调函数 private Vector3 _lastMousePos = Vector3.zero; private bool _dragMoveDown = true; private bool _dragging = false; private void onDragStarted() { _lastMousePos = Input.mousePosition; _dragging = true; //手动滑动,就关掉自动滑动 _enableSmoothMove = false; } private void onDragFinished() { } private void onStoppedMoving() { _dragging = false; } private void onDragMove(UIPanel panel) { //if (!_dragging) // return; if (_isCallShowFunc) return; var mPanel = ScrollView.panel; bool moveDown = true; Vector4 clip = mPanel.finalClipRegion; if (Input.mousePosition.y - _lastMousePos.y >= 0) _dragMoveDown = false; else _dragMoveDown = true; moveDown = _dragMoveDown; Bounds b = GetBounds(transform); float hx = clip.z * 0.5f; float hy = clip.w * 0.5f; //裁剪区域的上沿Y坐标 var topClipPos = clip.y + hy; //下沿Y坐标 var bottomClipPos = clip.y - hy; //上方在裁剪窗口内的item var topDisplayItem = GetTopItemInClipRegion(); //下方在裁剪窗口内的item var bottomDisplayItem = GetBottomItemInClipRegion(); //上方在裁剪窗口外的item var topDisappearItem = GetTopItemOutOfClipRegion(topClipPos); //下方在裁剪窗口外的item var bottomDisappearItem = GetBottomItemOutOfClipRegion(bottomClipPos); if(moveDown) { //往下滑,需要补充上方的item。如果上方有滑出屏幕的item,则不补充 if(topDisappearItem == null && topDisplayItem != null) { AddItemFromCacheParent(bottomDisappearItem, true, topDisplayItem); } } else { //往上滑,需要补充下方的item。如果下方有滑出屏幕的item,则不补充 if(bottomDisappearItem == null && bottomDisplayItem != null) { AddItemFromCacheParent(topDisappearItem, false, bottomDisplayItem); } } _lastMousePos = Input.mousePosition; } #endregion #region 私有功能函数 private void InitTopAndBottomPos(bool topLeft = true) { var clipRegion = ScrollView.panel.finalClipRegion; if (topLeft) { //左上角 _bottomPos = new Vector2(-clipRegion.z * 0.5f, clipRegion.w * 0.5f); } else { //左下角 _bottomPos = new Vector2(-clipRegion.z * 0.5f, -clipRegion.w * 0.5f); } _topPos = _bottomPos; _topPos.y += _softClipOffset.y + clipRegion.y; //clipRegion.y = 0 的情况加上偏移7.7592f _bottomPos.y -= _softClipOffset.y + clipRegion.y - 7.7592f; } private void AddItem(ItemHolder holder, bool addToTop = true) { //在这里设置holder非New holder.UseNew = false; Transform templateTrans = holder.Object; if (templateTrans.parent != ScrollView.transform) { if(!templateTrans.gameObject.activeSelf) templateTrans.gameObject.SetActive(true); templateTrans.parent = ScrollView.transform; Core.Base.UnityUtils.ResetTransform(templateTrans.gameObject); } templateTrans.name = "" + holder.Index; //var itemTrans = templateTrans; Bounds bounds = GetBounds(templateTrans); //设置item的坐标 SetPosition(templateTrans, bounds, addToTop); bounds = GetBounds(ScrollView.transform, templateTrans); holder.TopAndBottom.x = bounds.max.y; holder.TopAndBottom.y = bounds.min.y; holder.Size = bounds.size; //可重新计算ScrollView的bounds _calclateBounds = false; if(!_dragging && !_isCallShowFunc) SetMoveAmount(); //if (_newItemCount > 5) //{ // SmoothMove(1); // RecordLastPosition(); //} //if (!_dragging) // SmoothMove(1); TriggeOnItemShow(holder); } private Bounds GetBounds(Transform trans) { return NGUIMath.CalculateRelativeWidgetBounds(trans, trans); } private Bounds GetBounds(Transform parent, Transform trans) { return NGUIMath.CalculateRelativeWidgetBounds(parent, trans); } /// /// 计算添加item后,UIPanel的clipOffset的偏移 /// /// 对齐到底部 private void SetMoveAmount(bool toBottom = true) { RecordLastPosition(); var mPanel = ScrollView.panel; Bounds b = mBounds; if (b.min.x == b.max.x || b.min.y == b.max.y) return; Vector4 clip = mPanel.finalClipRegion; float hx = clip.z * 0.5f; float hy = clip.w * 0.5f; float left = b.min.x + hx; float right = b.max.x - hx; float bottom = b.min.y + hy; float top = b.max.y - hy; if (mPanel.clipping == UIDrawCall.Clipping.SoftClip) { left -= mPanel.clipSoftness.x; right += mPanel.clipSoftness.x; bottom -= mPanel.clipSoftness.y; top += mPanel.clipSoftness.y; } Vector4 cr = mPanel.baseClipRegion; float oy = bottom; if (b.size.y < cr.w) { oy = top; _lerpTimer = 1; } //对齐顶部,主要是用在起始位置的item被删除后,裁剪区域顶部需要和最上面的item对齐 if (!toBottom) oy = top; var pos = transform.localPosition; if (ScrollView.canMoveHorizontally) { _rootMoveToPos.x = pos.x + clip.x - right; _rootMoveToPos.y = pos.y; _rootEndClipOffset.x = right - cr.x; _rootEndClipOffset.y = clip.y - cr.y; } if (ScrollView.canMoveVertically) { _rootMoveToPos.x = pos.x; _rootMoveToPos.y = pos.y + clip.y - oy; _rootEndClipOffset.x = clip.x - cr.x; _rootEndClipOffset.y = oy - cr.y; } } /// /// 手动设置裁剪区域需要移动的偏移 /// /// private void SetClipRegionMoveOffset(float offsetY) { //RecordLastPosition(); var pos = transform.localPosition; Vector4 clip = ScrollView.panel.finalClipRegion; Vector4 cr = ScrollView.panel.baseClipRegion; var topPos = offsetY - cr.w * 0.5f; //需要矫正边界坐标,中心点总是跟边界有其一半高度的偏移 //topPos = topPos - clip.w * 0.5f; Vector3 _rootMoveToPos = pos; Vector4 _rootEndClipOffset = clip; _rootMoveToPos.x = pos.x; _rootMoveToPos.y = pos.y + clip.y - topPos; _rootEndClipOffset.x = clip.x; _rootEndClipOffset.y = topPos - cr.y; transform.localPosition = _rootMoveToPos; ScrollView.panel.clipOffset = _rootEndClipOffset; RecordLastPosition(); } private void SmoothMove(float time) { _calclateBounds = false; if (transform.localPosition == _rootMoveToPos) return; //transform.localPosition = Vector3.Lerp(_lastRootPos, _rootMoveToPos, time); //ScrollView.panel.clipOffset = Vector2.Lerp(_lastClipOffset, _rootEndClipOffset, time); transform.localPosition = _rootMoveToPos; ScrollView.panel.clipOffset = _rootEndClipOffset; //可重新计算ScrollView的bounds } private void TriggeOnItemShow(ItemHolder item) { if (item.OnItemShow != null) item.OnItemShow(item); } //记录上次变换后的位置 private void RecordLastPosition() { _lastRootPos = transform.localPosition; _lastClipOffset = ScrollView.panel.clipOffset; _lerpTimer = 0; if (!_dragging) _enableSmoothMove = true; } private void SetPosition(Transform item, Bounds itemBounds, bool addToTop) { int offsetX = 10; var pivot = GetPivot(item); if (addToTop) { var pos = new Vector3(0, _topPos.y - itemBounds.size.y * 0.5f); if (pivot == UIWidget.Pivot.TopLeft) { //pos.x = -itemBounds.size.x * 0.5f; pos.x = -_scrollViewSize.x * 0.5f + offsetX; pos.y = _topPos.y + itemBounds.size.y; } else if (pivot == UIWidget.Pivot.Left) { //pos.x = -itemBounds.size.x ; pos.x = -_scrollViewSize.x * 0.5f + offsetX; pos.y = _topPos.y + itemBounds.size.y * 0.5f; } else if (pivot == UIWidget.Pivot.TopRight) { //pos.x = itemBounds.size.x * 0.5f; pos.x = _scrollViewSize.x * 0.5f - offsetX; pos.y = _topPos.y + itemBounds.size.y; } else if (pivot == UIWidget.Pivot.Right) { //pos.x = itemBounds.size.x * 0.5f; pos.x = _scrollViewSize.x * 0.5f - offsetX; pos.y = _topPos.y + itemBounds.size.y * 0.5f; } //垂直方向,x值是center的值 item.localPosition = pos; //矫正坐标, 需要在设置偏移前调用 CorrectPosition(item, addToTop); //仅在Y方向做偏移保存 _topPos.y = _topPos.y + itemBounds.size.y; _topPos.y += _spaceY; _topPos.x = pos.x; } else { var pos = new Vector3(0, _bottomPos.y - itemBounds.size.y * 0.5f); if (pivot == UIWidget.Pivot.TopLeft) { pos.x = -_scrollViewSize.x * 0.5f + offsetX; pos.y = _bottomPos.y - itemBounds.size.y; } else if (pivot == UIWidget.Pivot.Left) { pos.x = -_scrollViewSize.x + offsetX; pos.y = _bottomPos.y - itemBounds.size.y * 0.5f; } else if (pivot == UIWidget.Pivot.TopRight) { pos.x = _scrollViewSize.x * 0.5f - offsetX; pos.y = _bottomPos.y - itemBounds.size.y; } else if (pivot == UIWidget.Pivot.Right) { pos.x = _scrollViewSize.x * 0.5f - offsetX; pos.y = _bottomPos.y - itemBounds.size.y * 0.5f; } //垂直方向,x值是center的值 item.localPosition = pos; //仅在Y方向做偏移保存 _bottomPos.y = _bottomPos.y - itemBounds.size.y; _bottomPos.y -= _spaceY; _bottomPos.x = pos.x; //矫正坐标,需要在设置了偏移后调用 CorrectPosition(item, addToTop); } } //矫正位置,因Item设置坐标,其中心点是最上层组件的中心点,而不是整个Transform和子控件构成的大的 //控件的中心点,导致设置坐标时会有偏移,在这里对偏移做矫正 private void CorrectPosition(Transform trans, bool addToTop) { //重新计算设置了坐标后的bounds,主要是得到中心点 var bounds = NGUIMath.CalculateRelativeWidgetBounds(_transform, trans); if (addToTop) trans.localPosition += (new Vector3(0, _topPos.y - bounds.min.y)); else trans.localPosition += (new Vector3(0, _bottomPos.y - bounds.min.y)); } private UIWidget.Pivot GetPivot(Transform trans) { var widget = trans.GetComponent(); if (widget != null) return widget.pivot; return UIWidget.Pivot.Center; } private void MoveItemToCacheParent(ItemHolder item, bool disappearTop) { item.Object.gameObject.SetActive(false); if(disappearTop) { _topPos.y -= item.Bounds.size.y; } else { _bottomPos.y += item.Bounds.size.y; } } /// /// 添加新的Item,补充到上或者下方即将呈现的位置 /// /// 上方或者下方在裁剪区域外的item /// /// 上方或者下方在裁剪区域内的item private ItemHolder AddItemFromCacheParent(ItemHolder disappearItem, bool addToTop, ItemHolder displayItem) { ItemHolder newItem = null; if(addToTop) { var newIndex = displayItem == null ? 0 : _adapter.GetReverseNextIndex(displayItem.Index); if (_curChannel != _adapter.GetChannelId(newIndex)) return null; newItem = CreateHolder(newIndex, disappearItem); if (newItem == null) return newItem; //有裁剪区域外的item才移除末尾的item if (disappearItem != null && !newItem.UseNew) { _showingList.RemoveAt(_showingList.Count - 1); if(_showingList.Count > 0) { var bottomItem = _showingList[_showingList.Count - 1]; _bottomPos.y = bottomItem.TopAndBottom.y; _bottomPos.y -= _spaceY; } } _showingList.Insert(0, newItem); } else { var newIndex = displayItem == null ? 0 : _adapter.GetNextIndex(displayItem.Index); if (_curChannel != _adapter.GetChannelId(newIndex)) return null; newItem = CreateHolder(newIndex, disappearItem); if (newItem == null) return newItem; //有裁剪区域外的item才移除开头的item if (disappearItem != null && !newItem.UseNew) { _showingList.RemoveAt(0); if(_showingList.Count > 0) { _topPos.y = _showingList[0].TopAndBottom.x; _topPos.y += _spaceY; } } _showingList.Add(newItem); } AddItem(newItem, addToTop); return newItem; } private ItemHolder CreateHolder(int index, ItemHolder temp) { if (index < 0 || index >= _adapter.GetCount()) return null; var newItem = _adapter.GetView(index, temp); if (newItem == null) return null; newItem.Index = index; //newItem.Object.parent = _transform; return newItem; } private void PlayScaleEffect(ItemHolder holder) { if (holder == null || !EnableEffect) return; //if (holder.AnimEffect == null) //{ // holder.AnimEffect = holder.Object.gameObject.RequireComponent(); // holder.AnimEffect.From = Vector3.one * 0.5f; // holder.AnimEffect.To = Vector3.one; // holder.AnimEffect.Duration = 0.5f; //} //holder.Object.localScale = holder.AnimEffect.From; //holder.AnimEffect.Start(); } //上方第一个在裁剪区域内的item private ItemHolder GetTopItemInClipRegion() { if (_showingList.Count > 0) return _showingList[0]; return null; } //下方最后一个在裁剪区域内的item private ItemHolder GetBottomItemInClipRegion() { if (_showingList.Count > 0) return _showingList[_showingList.Count - 1]; return null; } //上方第一个在裁剪区域外的Item private ItemHolder GetTopItemOutOfClipRegion(float topClipPos) { if(_showingList.Count > 0) { var topItem = _showingList[0]; if (topItem.TopAndBottom.y > topClipPos + Offset) return topItem; } return null; } private ItemHolder GetTopItemOutOfClipRegion() { Vector4 clip = ScrollView.panel.finalClipRegion; float hy = clip.w * 0.5f; //裁剪区域的上沿Y坐标 var topClipPos = clip.y + hy; return GetTopItemOutOfClipRegion(topClipPos); } //下方最后一个在裁剪区域外的item private ItemHolder GetBottomItemOutOfClipRegion(float bottomClipPos) { if(_showingList.Count > 0) { var bottomItem = _showingList[_showingList.Count - 1]; if (bottomItem.TopAndBottom.x < bottomClipPos - Offset) return bottomItem; } return null; } //下方最后一个在裁剪区域外的item private ItemHolder GetBottomItemOutOfClipRegion() { Vector4 clip = ScrollView.panel.finalClipRegion; float hy = clip.w * 0.5f; //下沿Y坐标 var bottomClipPos = clip.y - hy; return GetBottomItemOutOfClipRegion(bottomClipPos); } #endregion } }