/// <summary> /// 当Item未填满ScrollView时,限制在Top/Left /// </summary> /// <param name="pDragInfo"></param> /// <returns></returns> protected bool RestrictIfFits(ref RecycleTableDragInfo <T> pDragInfo) { if (!ScrollViewHasSpace()) { return(false); } var tConstraint = Vector3.zero; var b = itemsBounds; b.center += itemTrans.localPosition + scrollViewTrans.localPosition; switch (movement) { case UIScrollView.Movement.Horizontal: var tMin = panelBounds.min.x - b.min.x; tConstraint = new Vector3(tMin + panel.clipSoftness.x, 0, 0); pDragInfo.dragDirection = tConstraint.x < 0 ? Direction.Left : tConstraint.x > 0 ? Direction.Right : Direction.None; break; case UIScrollView.Movement.Vertical: var tMax = panelBounds.max.y - b.max.y; tConstraint = new Vector3(0, tMax - panel.clipSoftness.y, 0); pDragInfo.dragDirection = tConstraint.y > 0 ? Direction.Top : tConstraint.y < 0 ? Direction.Bottom : Direction.None; break; } if (tConstraint.sqrMagnitude > 0.1F) { if (!pDragInfo.instant && scrollView.dragEffect == UIScrollView.DragEffect.MomentumAndSpring) { var tPos = scrollViewTrans.localPosition + tConstraint; tPos.x = Mathf.Round(tPos.x); tPos.y = Mathf.Round(tPos.y); SpringPanel.Begin(scrollViewTrans.gameObject, tPos, 8F); } else { scrollView.MoveRelative(tConstraint); var tMomentum = scrollView.currentMomentum; if (Mathf.Abs(tConstraint.x) > 0.01F) { tMomentum.x = 0; } if (Mathf.Abs(tConstraint.y) > 0.01F) { tMomentum.y = 0; } if (Mathf.Abs(tConstraint.z) > 0.01F) { tMomentum.z = 0; } scrollView.currentMomentum = tMomentum; } } return(true); }
/// <summary> /// ScrollView归位 /// </summary> /// <param name="pInstant"></param> protected void RestrictWithinBounds(RecycleTableDragInfo <T> pDragInfo) { if (!pDragInfo.restrictScrollView) { return; } if (!RestrictIfFits(ref pDragInfo)) { scrollView.RestrictWithinBounds(pDragInfo.instant); } if (pDragInfo.isTopOrLeft && onStartTarget != null) { onStartTarget(pDragInfo.offset); } if (pDragInfo.isBottomOrRight && onEndTarget != null) { onEndTarget(pDragInfo.offset); } }
/// <summary> /// 初始化 /// </summary> protected void Init() { if (isNoneScrollView) { return; } NGUITools.DestroyChildren(scrollViewTrans); scrollView.restrictWithinPanel = false; scrollView.disableDragIfFits = false; var tClipRegion = panel.finalClipRegion; var tCenter = new Vector3(tClipRegion.x, tClipRegion.y, 0); tCenter += scrollViewTrans.localPosition; panelBounds = new Bounds(new Vector3(tCenter.x, tCenter.y, 0), new Vector3(tClipRegion.z, tClipRegion.w, 0)); scrollViewTrans.localPosition = Vector3.zero; panel.clipOffset = Vector2.zero; panel.baseClipRegion = new Vector4(panelBounds.center.x, panelBounds.center.y, panelBounds.size.x, panelBounds.size.y); if (!itemTrans) { itemTrans = NGUITools.AddChild(scrollView.gameObject).transform; itemTrans.name = "Items"; switch (movement) { case UIScrollView.Movement.Horizontal: itemTrans.SetLocalPos(0, panel.finalClipRegion.y); break; case UIScrollView.Movement.Vertical: itemTrans.SetLocalPos(panel.finalClipRegion.x, 0); break; } } if (!cacheTrans) { var tCacheTrans = scrollViewTrans.parent.Find("UIRecycleTableCache"); if (tCacheTrans != null) { cacheTrans = tCacheTrans; } else { cacheTrans = NGUITools.AddChild(scrollViewTrans.parent.gameObject).transform; cacheTrans.name = "UIRecycleTableCache"; } cacheTrans.gameObject.SetActive(false); } if (!springPanel) { springPanel = scrollViewTrans.gameObject.AddMissingComponent <SpringPanel>(); springPanel.enabled = false; } if (itemControllers == null) { itemControllers = new HashSet <T>(); } dragInfo = new RecycleTableDragInfo <T>() { restrictScrollView = true, instant = false, dragDirection = Direction.None, movement = movement, panelOffset = Vector2.zero, }; RegisterEvent(); MoveToItemByIndex(0); }
/// <summary> /// Panel裁剪时触发 /// </summary> /// <param name="pPanel"></param> protected void OnClipMove(UIPanel pPanel) { if (isNoneScrollView || itemCount == 0) { return; } var tPanelOffset = Vector3.zero; var tAddItemDirection = CalculateAddItemDirection(out tPanelOffset); var tIsLeft = tAddItemDirection == Direction.Left; var tIsBottom = tAddItemDirection == Direction.Bottom; var tIsRight = tAddItemDirection == Direction.Right; var tIsTop = tAddItemDirection == Direction.Top; if (tIsLeft || tIsTop) { AddItem(tIsLeft ? Direction.Left : tIsTop?Direction.Top: Direction.None); var tIsTopOrLeft = false; var tFirstItemCtrl = UIRecycleTableExtension.Find(itemControllers, x => x.recycleTablInfo.dataIndex == 0); var tFirstBounds = new Bounds(); if (tFirstItemCtrl != null) { tFirstBounds = tFirstItemCtrl.recycleTablInfo.bounds; tFirstBounds.center += tFirstItemCtrl.itemTransform.localPosition + scrollViewTrans.localPosition; tIsTopOrLeft = tIsLeft ? tFirstBounds.min.x > panelBounds.min.x : tIsTop ? tFirstBounds.max.y < panelBounds.max.y : tIsTopOrLeft; } var tInfo = new RecycleTableDragInfo <T>() { restrictScrollView = tIsTopOrLeft, panelOffset = tPanelOffset, dragDirection = Direction.Top | Direction.Left, instant = false, movement = movement, }; if (scrollView.isDragging) { dragInfo = tInfo; if (!tIsTopOrLeft) { MoveOverBoundsItemToCache(); } } else if (tIsTopOrLeft) { RestrictWithinBounds(tInfo); } else { MoveOverBoundsItemToCache(false); } } else if (tIsRight || tIsBottom) { AddItem(tIsRight ? Direction.Right : tIsBottom?Direction.Bottom: Direction.None); var tIsBottomOrRight = false; var tLastItemCtrl = UIRecycleTableExtension.Find(itemControllers, x => x.recycleTablInfo.dataIndex == itemCount - 1); var tLastBounds = new Bounds(); if (tLastItemCtrl != null) { tLastBounds = tLastItemCtrl.recycleTablInfo.bounds; tLastBounds.center += tLastItemCtrl.itemTransform.localPosition + scrollViewTrans.localPosition; tIsBottomOrRight = tIsRight ? tLastBounds.max.x <panelBounds.max.x : tIsBottom?tLastBounds.min.y> panelBounds.min.y : tIsBottomOrRight; } var tInfo = new RecycleTableDragInfo <T>() { restrictScrollView = tIsBottomOrRight, panelOffset = tPanelOffset, dragDirection = Direction.Bottom | Direction.Right, instant = false, movement = movement, }; if (scrollView.isDragging) { dragInfo = tInfo; if (!tIsBottomOrRight) { MoveOverBoundsItemToCache(); } } else if (tIsBottomOrRight) { RestrictWithinBounds(tInfo); } else { MoveOverBoundsItemToCache(false); } } }
/// <summary> /// Panel裁剪时触发 /// </summary> /// <param name="pPanel"></param> protected void OnClipMove(UIPanel pPanel) { if (isNoneScrollView || itemCount == 0) { return; } var tPanelOffset = panel.CalculateConstrainOffset(itemsBounds.min, itemsBounds.max); var tIsLeft = tPanelOffset.x < -1 && movement == UIScrollView.Movement.Horizontal; var tIsBottom = tPanelOffset.y < -1 && movement == UIScrollView.Movement.Vertical; var tIsRight = tPanelOffset.x > 1 && movement == UIScrollView.Movement.Horizontal; var tIsTop = tPanelOffset.y > 1 && movement == UIScrollView.Movement.Vertical; if (tIsLeft || tIsTop) { AddItem(tIsLeft ? Direction.Left : tIsTop?Direction.Top: Direction.None); var tIsTopOrLeft = false; var tFirstItemCtrls = itemControllers == null || itemControllers.Count == 0 ? null : itemControllers.Where(x => x.recycleTablInfo.dataIndex == 0); var tFirstBounds = new Bounds(); if (tFirstItemCtrls != null && tFirstItemCtrls.Count() == 1) { var tItemCtrl = tFirstItemCtrls.First(); tFirstBounds = tItemCtrl.recycleTablInfo.bounds; tFirstBounds.center += tItemCtrl.itemTransform.localPosition + scrollViewTrans.localPosition; tIsTopOrLeft = tIsLeft ? tFirstBounds.min.x > panelBounds.min.x : tIsTop ? tFirstBounds.max.y < panelBounds.max.y : tIsTopOrLeft; } var tInfo = new RecycleTableDragInfo <T>() { restrictScrollView = tIsTopOrLeft, panelOffset = tPanelOffset, dragDirection = Direction.Top | Direction.Left, instant = false, movement = movement, }; if (scrollView.isDragging) { dragInfo = tInfo; if (!tIsTopOrLeft) { MoveOverBoundsItemToCache(); } } else if (tIsTopOrLeft) { RestrictWithinBounds(tInfo); } else { MoveOverBoundsItemToCache(false); } } else if (tIsRight || tIsBottom) { AddItem(tIsRight ? Direction.Right : tIsBottom?Direction.Bottom: Direction.None); var tIsBottomOrRight = false; var tLastItemCtrls = itemControllers == null || itemControllers.Count == 0 ? null : itemControllers.Where(x => x.recycleTablInfo.dataIndex == itemCount - 1); var tLastBounds = new Bounds(); if (tLastItemCtrls != null && tLastItemCtrls.Count() == 1) { var tItemCtrl = tLastItemCtrls.First(); tLastBounds = tItemCtrl.recycleTablInfo.bounds; tLastBounds.center += tItemCtrl.itemTransform.localPosition + scrollViewTrans.localPosition; tIsBottomOrRight = tIsRight ? tLastBounds.max.x <panelBounds.max.x : tIsBottom?tLastBounds.min.y> panelBounds.min.y : tIsBottomOrRight; } var tInfo = new RecycleTableDragInfo <T>() { restrictScrollView = tIsBottomOrRight, panelOffset = tPanelOffset, dragDirection = Direction.Bottom | Direction.Right, instant = false, movement = movement, }; if (scrollView.isDragging) { dragInfo = tInfo; if (!tIsBottomOrRight) { MoveOverBoundsItemToCache(); } } else if (tIsBottomOrRight) { RestrictWithinBounds(tInfo); } else { MoveOverBoundsItemToCache(false); } } }