码迷,mamicode.com
首页 > 移动开发 > 详细

Unity NGUI ScrollView 苹果式滑动

时间:2017-09-23 15:24:08      阅读:443      评论:0      收藏:0      [点我收藏+]

标签:分享   获取   pos   lamp   summary   解决   拖动   es2017   tool   

又回来写博客了,这回已经开始上班了,所以就发一发工作中解决的难题吧。

单个展示Panel(苹果式)

以前对UI的滑动组件很烦心,不是很会用,这回项目要求写一个类似于苹果的文件滑动效果,但是苹果就展示一个文件,而我这边展示数目不定,头疼!

下面就直接来干货吧~,这里附送一个苹果式滑动解决方式 : 点这里

多个展示Panel(改写)

而我追求的效果呢,稍微改动一下,如下:(中间显示很多个,旁边的在叠起来的效果)

技术分享

这里我们采用比例的方式,这样好控制一些。

几个比较重要的点:

  • 每个Panel之间的比例差值
_offset = 1f / (totalPanelCount - showPanelCount); // 1f / (总共Panel - 展示Panel)
  • 获得拖动结束要偏移到的目标位置
private float GetTarget()
{
    return Mathf.Clamp01(Mathf.RoundToInt(_scrollValue / _offset) * _offset); // 取得最近的整数位
}
  • 分成三个区域,左缩放区域,右缩放区域,中间展示区域
 1     private void AnimationCore(int index)
 2     {
 3         float sourcePos = index * _offset;
 4         // 左边区域
 5         if (sourcePos < _scrollValue)
 6         {
 7             float dif = _scrollValue - sourcePos;
 8             int depth = _currentIndex - index;
 9             _panelPool[index].transform.SetSiblingIndex(totalPanelCount - depth - 2);
10             _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, GetTargetPos(index, dif, true), 100 * Time.deltaTime);
11         }
12         // 右边区域
13         else if (sourcePos > _scrollValue + _offset * (showPanelCount - 1))
14         {
15             float dif = sourcePos - _scrollValue - _offset * (showPanelCount - 1);
16             int depth = index - _currentIndex - showPanelCount + 1;
17             _panelPool[index].transform.SetSiblingIndex(totalPanelCount - depth - 2);
18             _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, GetTargetPos(index, dif, false), 100 * Time.deltaTime);
19         }
20         // 中间区域
21         else
22         {
23             _panelPool[index].transform.SetAsLastSibling();
24             _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, _panelPoolPos[index], 100 * Time.deltaTime);
25         }
26     }
  • 获取Panel的滑动偏移位置
    private Vector3 GetTargetPos(int index, float dif, bool isLeft)
    {
        float offSetDif = 60 / _offset * dif;
        if (isLeft)
        {
            return _panelPoolPos[index] + Vector3.right * offSetDif; // 左区域
        }
        else
        {
            return _panelPoolPos[index] - Vector3.right * offSetDif; // 右区域
        }
    }
  • 获取当前滑动的位置
 1     private float _scrollValue
 2     {
 3         get
 4         {
 5             return _scrollRect.horizontal ?
 6                 _scrollRect.horizontalNormalizedPosition :
 7                 _scrollRect.verticalNormalizedPosition;
 8         }
 9 
10         set
11         {
12             if (_scrollRect.horizontal)
13             {
14                 _scrollRect.horizontalNormalizedPosition = value;
15             }
16             else
17             {
18                 _scrollRect.verticalNormalizedPosition = value;
19             }
20         }
21     }

需要继承NGUI的EventSystem的时间来触发管理拖动 PS:用DOTween做最后的回滑效果

完整代码如下:

  1 using System;
  2 using UnityEngine;
  3 using UnityEngine.EventSystems;
  4 using UnityEngine.UI;
  5 using DG.Tweening;
  6 
  7 [RequireComponent(typeof(ScrollRect))]
  8 public class ScrollController : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
  9 {
 10     [Tooltip("创建出来的对象")]
 11     public GameObject imageObject;
 12     [Tooltip("展示页面数量")]
 13     public int showPanelCount = 8;
 14     [Tooltip("总计页面数量")]
 15     public int totalPanelCount = 20;
 16     [Tooltip("拖动结束制动弹回制动时间")]
 17     public float endDragMoveTime = 1f;
 18     public Ease doTweenEase = Ease.OutExpo;
 19 
 20     private int _currentIndex;
 21     private ScrollRect _scrollRect;
 22     private Tweener _tweener;
 23     private GameObject[] _panelPool = new GameObject[20];
 24     private Vector3[] _panelPoolPos = new Vector3[20];
 25     private float _offset;
 26 
 27     void Start()
 28     {
 29         _currentIndex = 1;
 30         _scrollRect = GetComponent<ScrollRect>();
 31         _scrollRect.inertia = false;
 32 
 33         for (int i = 0; i < totalPanelCount; i++)
 34         {
 35             GameObject go = Instantiate(imageObject) as GameObject;
 36             go.transform.SetParent(_scrollRect.content.transform);
 37             go.GetComponent<RectTransform>().sizeDelta = new Vector2(100, 200);
 38             go.GetComponent<RectTransform>().anchorMax = new Vector2(0, 0.5f);
 39             go.GetComponent<RectTransform>().anchorMin = new Vector2(0, 0.5f);
 40             go.GetComponent<RectTransform>().pivot = new Vector2(0, 0.5f);
 41             go.GetComponent<RectTransform>().anchoredPosition = new Vector2(100 + 100 * i, 0);
 42             go.transform.localScale = Vector3.one;
 43             _panelPool[i] = go;
 44             _panelPoolPos[i] = go.transform.localPosition;
 45         }
 46 
 47         _scrollRect.content.GetComponent<RectTransform>().sizeDelta = new Vector2(totalPanelCount * 100 + 200, 200);
 48 
 49         _offset = 1f / (totalPanelCount - showPanelCount);
 50 
 51         for (int i = 0; i < totalPanelCount; i++)
 52         {
 53             AnimationCore(i);
 54         }
 55     }
 56 
 57     public void OnBeginDrag(PointerEventData eventData)
 58     {
 59         if (_tweener != null && _tweener.IsActive())
 60         {
 61             _tweener.Kill();
 62         }
 63     }
 64 
 65     public void OnDrag(PointerEventData eventData)
 66     {
 67         _currentIndex = Mathf.RoundToInt(GetTarget() * (totalPanelCount - showPanelCount));
 68 
 69         OnDragAnimation();
 70     }
 71 
 72     public void OnEndDrag(PointerEventData eventData)
 73     {
 74         _tweener = DOTween.To(() => _scrollValue, (v) => _scrollValue = v, GetTarget(), endDragMoveTime).SetEase(doTweenEase);
 75         _tweener.onUpdate = () =>
 76         {
 77             OnDragAnimation();
 78         };
 79     }
 80 
 81     private void OnDragAnimation()
 82     {
 83         //向左拉动(解决层级问题)
 84         if (_scrollValue > 0)
 85         {
 86             for (int i = 0; i < totalPanelCount; i++)
 87             {
 88                 AnimationCore(i);
 89             }
 90         }
 91         else
 92         {
 93             for (int i = totalPanelCount - 1; i >= 0; i--)
 94             {
 95                 AnimationCore(i);
 96             }
 97         }
 98     }
 99 
100     private void AnimationCore(int index)
101     {
102         float sourcePos = index * _offset;
103         // 左边区域
104         if (sourcePos < _scrollValue)
105         {
106             float dif = _scrollValue - sourcePos;
107             int depth = _currentIndex - index;
108             _panelPool[index].transform.SetSiblingIndex(totalPanelCount - depth - 2);
109             _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, GetTargetPos(index, dif, true), 100 * Time.deltaTime);
110         }
111         // 右边区域
112         else if (sourcePos > _scrollValue + _offset * (showPanelCount - 1))
113         {
114             float dif = sourcePos - _scrollValue - _offset * (showPanelCount - 1);
115             int depth = index - _currentIndex - showPanelCount + 1;
116             _panelPool[index].transform.SetSiblingIndex(totalPanelCount - depth - 2);
117             _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, GetTargetPos(index, dif, false), 100 * Time.deltaTime);
118         }
119         // 中间区域
120         else
121         {
122             _panelPool[index].transform.SetAsLastSibling();
123             _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, _panelPoolPos[index], 100 * Time.deltaTime);
124         }
125     }
126 
127     /// <summary>
128     /// 获取到页面的偏移后位置
129     /// </summary>
130     /// <returns></returns>
131     private Vector3 GetTargetPos(int index, float dif, bool isLeft)
132     {
133         float offSetDif = 60 / _offset * dif;
134         if (isLeft)
135         {
136             return _panelPoolPos[index] + Vector3.right * offSetDif;
137         }
138         else
139         {
140             return _panelPoolPos[index] - Vector3.right * offSetDif;
141         }
142     }
143 
144     /// <summary>
145     /// 获得偏转目标位置
146     /// </summary>
147     /// <returns></returns>
148     private float GetTarget()
149     {
150         return Mathf.Clamp01(Mathf.RoundToInt(_scrollValue / _offset) * _offset);
151     }
152 
153     /// <summary>
154     /// 当前滑动位置
155     /// </summary>
156     /// <returns></returns>
157     private float _scrollValue
158     {
159         get
160         {
161             return _scrollRect.horizontal ?
162                 _scrollRect.horizontalNormalizedPosition :
163                 _scrollRect.verticalNormalizedPosition;
164         }
165 
166         set
167         {
168             if (_scrollRect.horizontal)
169             {
170                 _scrollRect.horizontalNormalizedPosition = value;
171             }
172             else
173             {
174                 _scrollRect.verticalNormalizedPosition = value;
175             }
176         }
177     }
178 }

 

Unity NGUI ScrollView 苹果式滑动

标签:分享   获取   pos   lamp   summary   解决   拖动   es2017   tool   

原文地址:http://www.cnblogs.com/SHOR/p/7581142.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!