【Unity UGUI】各种优化效果

发表于2017-05-20
评论2 2k浏览

UGUI在项目开发中的使用就不多做介绍了,本篇文章给大家介绍的是UGUI各种优化效果。

所实现的UGUI效果需求如下:

  • 支持动态缩放循环加载
  • 支持不用Mask遮罩无限循环加载
  • 支持ObjectPool动态加载
  • 支持无限不规则子物体动态加载
  • 支持拖动并点击和拖拽
  • 支持拖动并拖拽
  • 支持ScrollRect拖动自动吸附功能(拖动是否超过一半自动进退)

前言

要实现以上效果,我从网上搜索得到部分解决方案链接,但不是完全满足想要的效果,就自己继续改造优化和添加想要的效果,本文最后会附带上完整Demo下载链接。

效果图

  • 缩放循环展示卡牌效果

  • 大量数据无卡顿动态加载,并且支持拖拽、点击和吸附功能

  • 无限无遮罩动态加载

  • 不规则子物体动态循环加载

部分核心代码

  • 有遮罩无卡顿加载 
    思路:并没有使用UGUI的ScrollRect组件,摆放几张卡片,通过移动和缩放来实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
 
public class EnhancelScrollView : MonoBehaviour
{
    // 缩放曲线
    public AnimationCurve scaleCurve;
    // 位移曲线
    public AnimationCurve positionCurve;
    // 位移系数
    public float posCurveFactor = 500.0f;
    // y轴坐标固定值(所有的item的y坐标一致)
    public float yPositionValue = 46.0f;
 
    // 添加到EnhanceScrollView的目标对象
    public List scrollViewItems;
    // 目标对象Widget脚本,用于depth排序
    private List imageTargets;
 
    // 当前处于中间的item
    private EnhanceItem centerItem;
    private EnhanceItem preCenterItem;
 
    // 当前出移动中,不能进行点击切换
    private bool canChangeItem = true;
 
    // 计算差值系数
    public float dFactor = 0.2f;
 
    // 点击目标移动的横向目标值
    private float[] moveHorizontalValues;
    // 对象之间的差值数组(根据差值系数算出)
    private float[] dHorizontalValues;
 
    // 横向变量值
    public float horizontalValue = 0.0f;
    // 目标值
    public float horizontalTargetValue = 0.1f;
 
    // 移动动画参数
    private float originHorizontalValue = 0.1f;
    public float duration = 0.2f;
    private float currentDuration = 0.0f;
 
    private static EnhancelScrollView instance;
    public static EnhancelScrollView GetInstance()
    {
        return instance;
    }
 
    void Awake()
    {
        instance = this;
    }
 
    void Start()
    {
        if((scrollViewItems.Count % 2) == 0)   
        {
            Debug.LogError("item count is invaild,please set odd count! just support odd count.");
        }
 
        if(moveHorizontalValues == null)
            moveHorizontalValues = new float[scrollViewItems.Count];
 
        if(dHorizontalValues == null)
            dHorizontalValues = new float[scrollViewItems.Count];
 
        if (imageTargets == null)
            imageTargets = new List();
 
        int centerIndex = scrollViewItems.Count / 2;
        for (int i = 0; i < scrollViewItems.Count;i++ )
        {
            scrollViewItems[i].scrollViewItemIndex = i;
            Image tempImage = scrollViewItems[i].gameObject.GetComponent();
            imageTargets.Add(tempImage);
 
            dHorizontalValues[i] = dFactor * (centerIndex - i);
 
            dHorizontalValues[centerIndex] = 0.0f;
            moveHorizontalValues[i] = 0.5f - dHorizontalValues[i];
            scrollViewItems[i].SetSelectColor(false);
        }
 
        centerItem = scrollViewItems[centerIndex];
        canChangeItem = true;
    }
 
    public void UpdateEnhanceScrollView(float fValue)
    {
        for (int i = 0; i < scrollViewItems.Count; i++)
        {
            EnhanceItem itemScript = scrollViewItems[i];
            float xValue = GetXPosValue(fValue, dHorizontalValues[itemScript.scrollViewItemIndex]);
            float scaleValue = GetScaleValue(fValue, dHorizontalValues[itemScript.scrollViewItemIndex]);
            itemScript.UpdateScrollViewItems(xValue, yPositionValue, scaleValue);
        }
    }
 
    void Update()
    {
        currentDuration += Time.deltaTime;
        if (currentDuration > duration)
        {
            // 更新完毕设置选中item的对象即可
            currentDuration = duration;
            if (centerItem != null)
                centerItem.SetSelectColor(true);
            if (preCenterItem != null)
                preCenterItem.SetSelectColor(false);
            canChangeItem = true;
        }
 
        SortDepth();
        float percent = currentDuration / duration;
        horizontalValue = Mathf.Lerp(originHorizontalValue, horizontalTargetValue, percent);
        UpdateEnhanceScrollView(horizontalValue);
    }
 
    ///
    /// 缩放曲线模拟当前缩放值
    ///
    private float GetScaleValue(float sliderValue, float added)
    {
        float scaleValue = scaleCurve.Evaluate(sliderValue + added);
        return scaleValue;
    }
 
    ///
    /// 位置曲线模拟当前x轴位置
    ///
    private float GetXPosValue(float sliderValue, float added)
    {
        float evaluateValue = positionCurve.Evaluate(sliderValue + added) * posCurveFactor;
        return evaluateValue;
    }
 
    public void SortDepth()
    {
        imageTargets.Sort(new CompareDepthMethod());
        for (int i = 0; i < imageTargets.Count; i++)
            imageTargets[i].transform.SetSiblingIndex(i);
    }
 
    ///
    /// 用于层级对比接口
    ///
    public class CompareDepthMethod : IComparer
    {
        public int Compare(Image left, Image right)
        {
            if (left.transform.localScale.x > right.transform.localScale.x)
                return 1;
            else if (left.transform.localScale.x < right.transform.localScale.x)
                return -1;
            else
                return 0;
        }
    }
 
    ///
    /// 获得当前要移动到中心的Item需要移动的factor间隔数
    ///
    private int GetMoveCurveFactorCount(float targetXPos)
    {
        int centerIndex = scrollViewItems.Count / 2;
        for (int i = 0; i < scrollViewItems.Count;i++ )
        {
            float factor = (0.5f - dFactor * (centerIndex - i));
 
            float tempPosX = positionCurve.Evaluate(factor) * posCurveFactor;
            if (Mathf.Abs(targetXPos - tempPosX) < 0.01f)
                return Mathf.Abs(i - centerIndex);
        }
        return -1;
    }
 
    ///
    /// 设置横向轴参数,根据缩放曲线和位移曲线更新缩放和位置
    ///
    public void SetHorizontalTargetItemIndex(int itemIndex)
    {
        if (!canChangeItem)
            return;
 
        EnhanceItem item = scrollViewItems[itemIndex];
        if (centerItem == item)
            return;
 
        canChangeItem = false;
        preCenterItem = centerItem;
        centerItem = item;
 
        // 判断点击的是左侧还是右侧计算ScrollView中心需要移动的value
        float centerXValue = positionCurve.Evaluate(0.5f) * posCurveFactor;
        bool isRight = false;
        if (item.transform.localPosition.x > centerXValue)
            isRight = true;
 
        // 差值,计算横向值
        int moveIndexCount = GetMoveCurveFactorCount(item.transform.localPosition.x);
        if (moveIndexCount == -1)
        {
            moveIndexCount = 1;
        }
 
        float dvalue = 0.0f;
        if (isRight)
            dvalue = -dFactor * moveIndexCount;
        else
            dvalue = dFactor * moveIndexCount;
 
        // 更改target数值,平滑移动
        horizontalTargetValue += dvalue;
        currentDuration = 0.0f;
        originHorizontalValue = horizontalValue;
    }
 
    ///
    /// 向右选择角色按钮
    ///
    public void OnBtnRightClick()
    {
        if (!canChangeItem)
            return;
        int targetIndex = centerItem.scrollViewItemIndex + 1;
        if (targetIndex > scrollViewItems.Count - 1)
            targetIndex = 0;
        SetHorizontalTargetItemIndex(targetIndex);
    }
 
    ///
    /// 向左选择按钮
    ///
    public void OnBtnLeftClick()
    {
        if (!canChangeItem)
            return;
        int targetIndex = centerItem.scrollViewItemIndex - 1;
        if (targetIndex < 0)
            targetIndex = scrollViewItems.Count - 1;
        SetHorizontalTargetItemIndex(targetIndex);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
 
public class EnhanceItem : MonoBehaviour {
 
    // 在ScrollViewitem中的索引
    // 定位当前的位置和缩放
    public int scrollViewItemIndex = 0;
    public bool inRightArea = false;
 
    private Vector3 targetPos = Vector3.one;
    private Vector3 targetScale = Vector3.one;
 
    private Transform mTrs;
    private Image mImage;
 
 
    void Awake()
    {
        mTrs = this.transform;
        mImage = this.GetComponent();
    }
 
    void Start()
    {
        this.gameObject.GetComponent().onClick.AddListener(delegate () { OnClickScrollViewItem(); });
    }
 
    // 当点击Item,将该item移动到中间位置
    private void OnClickScrollViewItem()
    {
        EnhancelScrollView.GetInstance().SetHorizontalTargetItemIndex(scrollViewItemIndex);
    }
 
    ///
    /// 更新该Item的缩放和位移
    ///
    public void UpdateScrollViewItems(float xValue, float yValue, float scaleValue)
    {
        targetPos.x = xValue;
        targetPos.y = yValue;
        targetScale.x = targetScale.y = scaleValue;
 
        mTrs.localPosition = targetPos;
        mTrs.localScale = targetScale;
    }
 
    public void SetSelectColor(bool isCenter)
    {
        if (mImage == null)
            mImage = this.GetComponent();
 
        if (isCenter)
            mImage.color = Color.white;
        else
            mImage.color = Color.gray;
    }
}
  • 有遮罩无卡顿加载 
    思路:协程加载,先加载屏幕显示的数量,然后返回一帧在继续加载,防止出现数量太大卡顿的现象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
while (CardsList.Count > roleInfo.Count)
{
    DestroyImmediate(CardsList[0].gameObject);
    CardsList.RemoveAt(0);
}
StartCoroutine(createRoleCards());
 
private IEnumerator createRoleCards()
{
    List charInfos = new List();
    charInfos.AddRange(roleInfo);
    int index = 0;
    for (int i = 0; i < charInfos.Count; i++)
    {
        _createRoleCard(charInfos[i], index++);
        if (index % 10 == 0)
            yield return null;
    }
}
 
private void _createRoleCard(CLocalCharInfo roleInfo, int index)
{
    CUIPlayedCharCardWidget charCardWidget = null;
    if (CardsList.Count > index)
    {
        charCardWidget = CardsList[index];
    }
    else
    {
        var obj = Instantiate(Resources.Load("Prefab/RoleCard")) as GameObject;
        if (obj == null)
        {
            UnityEngine.Debug.LogError("有误");
            return;
        }
        obj.name = roleInfo.Name;
 
        charCardWidget = obj.GetComponent();
 
        if (charCardWidget == null)
        {
            UnityEngine.Debug.LogError("有误");
            return;
        }
        obj.transform.parent = Obj_ScrollViewContent.transform;
        obj.transform.localScale = Vector3.one;
        CardsList.Add(charCardWidget);
    }
 
    CUIPlayedCharCardWidget.CUIContent uiContent = new CUIPlayedCharCardWidget.CUIContent();
    uiContent.RoleInfo = roleInfo;
    uiContent.ScrollRectObj = m_ScrollRect;
    uiContent.FixGridRect = m_FixGrid;
    charCardWidget.InitContent(uiContent);
}
  • 支持ScrollRect拖拽或点击 
    思路:在卡片的Image上添加一个继承了IBeginDragHandler,IGradHandler,IEndDragHandler的脚本,重写接口里面的Drag事件方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
 
namespace Mga
{
    [RequireComponent(typeof(Image))]
    public class CPlayedCardOnDrag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
    {
        public bool dragOnSurfaces = true;
        public ScrollRect m_ScrollRect = null;
        public CFixGridRect m_FixGridRect = null;
        private GameObject m_DraggingCard;
        private RectTransform m_DraggingPlane;
 
        public bool isVertical = false;
        private bool isSelf = false;
 
        private System.Action m_OnBeginDragCallBack = null;
        private System.Action m_OnEndDragCallBack = null;
 
        private System.Action m_OnBeginScroll = null;
        private System.Action m_OnEndScroll = null;
        public void Init(CLocalCharInfo roleInfo, System.Action beginCallBack = null, System.Action endCallBack = null, System.Action beginScroll = null, System.Action endScroll = null)
        {
            m_OnBeginDragCallBack = beginCallBack;
            m_OnEndDragCallBack = endCallBack;
            m_OnBeginScroll = beginScroll;
            m_OnEndScroll = endScroll;
        }
        public void OnBeginDrag(PointerEventData eventData)
        {
            Vector2 touchDeltaPosition = Vector2.zero;
#if UNITY_EDITOR
            float delta_x = Input.GetAxis("Mouse X");
            float delta_y = Input.GetAxis("Mouse Y");
            touchDeltaPosition = new Vector2(delta_x, delta_y);
 
#elif UNITY_ANDROID || UNITY_IPHONE
        touchDeltaPosition = Input.GetTouch(0).deltaPosition; 
#endif
            if (isVertical)
            {
                if (Mathf.Abs(touchDeltaPosition.x) > Mathf.Abs(touchDeltaPosition.y))
                {
                    isSelf = true;
                    var canvas = FindInParents(gameObject);
                    if (canvas == null)
                        return;
                    m_DraggingCard = createCard();
                    m_DraggingCard.transform.SetAsLastSibling();
 
                    m_DraggingCard.AddComponent();
 
                    if (dragOnSurfaces)
                        m_DraggingPlane = transform as RectTransform;
                    else
                        m_DraggingPlane = canvas.transform as RectTransform;
 
                    SetDraggedPosition(eventData);
                    if (m_OnBeginDragCallBack != null)
                    {
                        m_OnBeginDragCallBack();
                    }
                }
                else
                {
                    isSelf = false;
                    if (m_ScrollRect != null)
                        m_ScrollRect.OnBeginDrag(eventData);
                }
            }
            else
            {
                if (Mathf.Abs(touchDeltaPosition.x) < Mathf.Abs(touchDeltaPosition.y))
                {
                    isSelf = true;
                    var canvas = FindInParents(gameObject);
                    if (canvas == null)
                        return;
                    m_DraggingCard = createCard();
                    m_DraggingCard.transform.SetAsLastSibling();
 
                    m_DraggingCard.AddComponent();
 
                    if (dragOnSurfaces)
                        m_DraggingPlane = transform as RectTransform;
                    else
                        m_DraggingPlane = canvas.transform as RectTransform;
 
                    SetDraggedPosition(eventData);
                    if (m_OnBeginDragCallBack != null)
                    {
                        m_OnBeginDragCallBack();
                    }
                }
                else
                {
                    isSelf = false;
                    if (m_ScrollRect != null)
                        m_ScrollRect.OnBeginDrag(eventData);
                }
            }
            if (m_OnBeginScroll != null)
                m_OnBeginScroll();
        }
 
        public void OnDrag(PointerEventData data)
        {
            if (isSelf)
            {
                if (m_DraggingCard != null)
                {
                    SetDraggedPosition(data);
                }
            }
            else
            {
                if (m_ScrollRect != null)
                    m_ScrollRect.OnDrag(data);
            }
        }
 
        private void SetDraggedPosition(PointerEventData data)
        {
            if (dragOnSurfaces && data.pointerEnter != null && data.pointerEnter.transform as RectTransform != null)
                m_DraggingPlane = data.pointerEnter.transform as RectTransform;
 
            var rt = m_DraggingCard.GetComponent();
            Vector3 globalMousePos;
            if (RectTransformUtility.ScreenPointToWorldPointInRectangle(m_DraggingPlane, data.position, data.pressEventCamera, out globalMousePos))
            {
                rt.position = globalMousePos;
                rt.rotation = m_DraggingPlane.rotation;
            }
        }
 
        private GameObject createCard()
        {
            CUIPlayedCharCardWidget charCardWidget = null;
            m_DraggingCard = Instantiate(Resources.Load("Prefab/RoleCard") as GameObject);
            if (m_DraggingCard == null)
            {
                return null;
            }
            charCardWidget = m_DraggingCard.GetComponent();
 
            if (charCardWidget == null)
            {
                return null;
            }
 
            CUIPlayedCharCardWidget.CUIContent uiContent = new CUIPlayedCharCardWidget.CUIContent();
 
            charCardWidget.InitContent(uiContent);
            return m_DraggingCard;
        }
 
        public void OnEndDrag(PointerEventData eventData)
        {
            if (isSelf)
            {
                if (m_DraggingCard != null)
                {
                    Destroy(m_DraggingCard);
                    if (m_OnEndDragCallBack != null)
                    {
                        m_OnEndDragCallBack();
                    }
                }
            }
            else
            {
                if (m_ScrollRect != null)
                    m_ScrollRect.OnEndDrag(eventData);
                if (m_FixGridRect != null)
                    m_FixGridRect.OnEndDrag(eventData);
            }
 
        }
 
        static public T FindInParents(GameObject go) where T : Component
        {
            if (go == null) return null;
            var comp = go.GetComponent();
 
            if (comp != null)
                return comp;
 
            Transform t = go.transform.parent;
            while (t != null && comp == null)
            {
                comp = t.gameObject.GetComponent();
                t = t.parent;
            }
            return comp;
        }
    }
}
如果想要实现拖拽到目标位置的检测,还要在目标位置放一个Image并且添加上继承了IDropHandler,IPointerEnterHandler,IPointerExitHanler的组件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
using System.Reflection;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System.Collections;
namespace Mga
{
    public class CPlayedCardOnDrop : MonoBehaviour, IDropHandler, IPointerEnterHandler, IPointerExitHandler
    {
        public Image containerImage;
        public Image receivingImage;
        private Color normalColor;
        public Color highlightColor = Color.yellow;
        private int drapAreaIndex = 0;
 
        void Start()
        {
            drapAreaIndex = System.Convert.ToInt32(this.transform.parent.name);
        }
 
        public void OnEnable()
        {
            if (containerImage != null)
                normalColor = containerImage.color;
        }
 
        public void OnDrop(PointerEventData data)
        {
            containerImage.color = normalColor;
 
            if (receivingImage == null)
                return;
            Sprite dropSprite = GetDropSprite(data);
            if (dropSprite != null)
                receivingImage.overrideSprite = dropSprite;
        }
 
        public void OnPointerEnter(PointerEventData data)
        {
            if (containerImage == null)
                return;
            Sprite dropSprite = GetDropSprite(data);
            if (dropSprite != null)
                containerImage.color = highlightColor;
        }
 
        public void OnPointerExit(PointerEventData data)
        {
            if (containerImage == null)
                return;
            containerImage.color = normalColor;
        }
 
        private Sprite GetDropSprite(PointerEventData data)
        {
            var originalObj = data.pointerDrag;
            if (originalObj == null)
                return null;
 
            var srcImage = originalObj.GetComponent();
            if (srcImage == null)
                return null;
 
            return srcImage.sprite;
        }
    }
}
在ScrollRect物体上添加吸附功能组件,工程里面要使用DoTween插件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
 
//TODO:当前只试应横向的ScrollRect,还需要扩展支持纵向
public class CFixGridRect : MonoBehaviour, IEndDragHandler
{
    public GameObject content;
    public ScrollRect scorllRect;
    public float itemWidth;
    private RectTransform contentRectTf;
 
    private float formalPosX = 0;
    private float currentPosX = 0;
    private float halfItemLength = 0;
 
    void Start()
    {
        if (itemWidth <= 0)
            UnityEngine.Debug.LogError("请设置Item的宽度");
        halfItemLength = itemWidth / 2;
        this.contentRectTf = this.content.GetComponent();
    }
 
    public void OnEndDrag(PointerEventData eventData)
    {
        this.scorllRect.StopMovement();
        Vector2 afterDragPagePos = this.content.transform.localPosition;
        currentPosX = afterDragPagePos.x; //当前拖动的位置  负
        if (scorllRect.horizontalNormalizedPosition < 0 || scorllRect.horizontalNormalizedPosition > 1)
            return;
        int count = (int)(Mathf.Abs(currentPosX) / itemWidth);
        var targetPos = -(float)(count * itemWidth);
 
        if (((float)(count * itemWidth + halfItemLength)) < Mathf.Abs(currentPosX))
        {
            targetPos = -(float)((count + 1) * itemWidth);
        }
        formalPosX = targetPos;
        this.contentRectTf.DOLocalMoveX(targetPos, .2f);
    }
}

优化支持横竖屏的ScrollRect吸附功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
 
namespace Mga
{
    public enum DragDirection
    {
        Horizontal,
        Vertical,
    }
 
    public class CFixGridRectBase : MonoBehaviour, IEndDragHandler
    {
        public class CUIContent
        {
            public GameObject ScrollRectContent;
            public ScrollRect m_ScorllRect;
            public float ItemSize;
            public float ItemSpaceLength; //间隙
            public float Margin = 0; //顶部边缘间隙
            public DragDirection m_DragDirection = DragDirection.Vertical;
        }
        private RectTransform contentRectTf;
        private float halfItemLength = 0;
        private CUIContent m_uiContent = null;
        private bool m_bWidgetReady = false;
        void Start()
        {
            m_bWidgetReady = true;
            _initContent();
        }
 
        public void InitContent(CUIContent uiContent)
        {
            m_uiContent = uiContent;
 
            if (m_bWidgetReady)
                _initContent();
        }
 
        private void _initContent()
        {
            if (m_uiContent == null) return;
 
            if (m_uiContent.ItemSize <= 0)
            {
                UnityEngine.Debug.LogError("请设置Item的宽度");
                return;
            }
            halfItemLength = m_uiContent.ItemSize / 2;
            this.contentRectTf = m_uiContent.ScrollRectContent.GetComponent();
        }
 
        public void OnEndDrag(PointerEventData eventData)
        {
            m_uiContent.m_ScorllRect.StopMovement();
            Vector2 afterDragPagePos = m_uiContent.ScrollRectContent.transform.localPosition;
            var itemLength = m_uiContent.ItemSize + m_uiContent.ItemSpaceLength;
            if (m_uiContent.m_DragDirection == DragDirection.Horizontal)
            {
                var currentPosX = afterDragPagePos.x; //当前拖动的位置  负
                currentPosX -= m_uiContent.Margin;
                int count = (int)(Mathf.Abs(currentPosX) / m_uiContent.ItemSize);
                if (m_uiContent.m_ScorllRect.horizontalNormalizedPosition <= 0)
                {
                    return;
                }
                else if (m_uiContent.m_ScorllRect.horizontalNormalizedPosition >= 1)  //总数-当前显示的数量
                {
                    return;
                }
 
                var targetPosX = -(float)(count * itemLength);
                if (((float)(targetPosX + halfItemLength)) < Mathf.Abs(currentPosX))
                {
                    count++;
                    targetPosX = -(float)(count * itemLength);
                }
                this.contentRectTf.DOLocalMoveX(targetPosX, .2f);
            }
            else
            {
                var currentPosY = afterDragPagePos.y; //当前拖动的位置  正
                currentPosY -= m_uiContent.Margin;
                int count = (int)(Mathf.Abs(currentPosY) / itemLength);
                if (m_uiContent.m_ScorllRect.verticalNormalizedPosition <= 0)
                {
                    return;
                }
                else if (m_uiContent.m_ScorllRect.verticalNormalizedPosition >= 1)  //总数-当前显示的数量
                {
                    return;
                }
 
                var targetPosY = (float)(count * itemLength);
                if (((float)(targetPosY + halfItemLength)) < Mathf.Abs(currentPosY))
                {
                    count++;
                    targetPosY = (float)(count * itemLength);
                }
                this.contentRectTf.DOLocalMoveY(targetPosY, .2f);
            }
        }
    }
}

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

0个评论