Unity3d—作一個年月日選擇器(Scroll Rect拖動效果優化)— 無限滾動 + 鎖定元素

效果圖ide

 

用的是UGUIlua

我先說思路spa

經過判斷元素的位置信息來改變Hierarchy的順序 實現無限滾動3d

改變位置的同時也要不斷的調整Content的位置防止亂跳code

元素鎖定就是直接鎖死的元素的移動範圍 當只有拖動大於必定程度時纔會發生改變orm

 

而後是面板設置blog

總體結構是這樣子的ci

須要注意的是Content須要的兩個組件get

Content的爸爸只須要一個腳本string

大小改變曲線(大體就行)

顏色漸變曲線

 

最後是腳本

  1 using System;
  2 using System.Collections;
  3 using System.Collections.Generic;
  4 using UnityEngine;
  5 using UnityEngine.EventSystems;
  6 using UnityEngine.UI;
  7 
  8 public class DateControl : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
  9 
 10     public enum ItemType { _year, _month, _day }
 11 
 12     public ItemType _itemtype;
 13 
 14     RectTransform conentRect;
 15 
 16     RectTransform targetRec;
 17 
 18     Vector3 oldDragPos;
 19 
 20     Vector3 newDragPos;
 21 
 22     public AnimationCurve curve_scale;//改變大小曲線
 23     public AnimationCurve curve_color;//漸變效果曲線
 24 
 25 
 26     List<Text> textList = new List<Text>();
 27 
 28     Button testBtn;
 29 
 30     float 
 31         itemHeight,             //子項item的高
 32         contentParentHeight,    //Content爸爸的高
 33         itemNum,                //子項數量
 34         itemHeight_min,         //子項最小發生改變位置
 35         itemHeight_max,         //子項最大發生改變位置
 36         conentLimit,            //Conent糾正位置
 37         conentSpacing;          //子項間隔大小
 38 
 39     float deltaX, deltaY;
 40 
 41     [HideInInspector]
 42     public static int _year, _month, _day;
 43 
 44     [HideInInspector]
 45     int dateItemNum;
 46 
 47     Color itemColor_hig = new Color32(255, 255, 255, 255);
 48 
 49     void Awake() {
 50         conentRect = transform.FindChild("Content").GetComponent<RectTransform>();
 51         targetRec = transform.parent.FindChild("HighlightTarget").GetComponent<RectTransform>();
 52 
 53     }
 54 
 55     void OnEnable() {
 56         ItemList();
 57     }
 58 
 59     void Start() {
 60         switch (_itemtype) {
 61             case ItemType._year: InstantiateData(15, 2017); break;
 62             case ItemType._month: InstantiateData(12, 12); break;
 63             case ItemType._day: InstantiateData(31, 31); break;
 64         }
 65 
 66         itemNum = transform.FindChild("Content").childCount - 1;
 67 
 68         contentParentHeight = conentRect.parent.GetComponent<RectTransform>().sizeDelta.y;
 69 
 70         conentSpacing = conentRect.GetComponent<VerticalLayoutGroup>().spacing / 2;
 71 
 72         itemHeight = textList[0].rectTransform.sizeDelta.y + conentSpacing;
 73 
 74         if (itemNum % 2 == 0) conentLimit = (itemHeight + 5) / 2;
 75 
 76         else conentLimit = 0;
 77 
 78         conentRect.anchoredPosition = new Vector2(conentRect.anchoredPosition.x, conentLimit);
 79 
 80         deltaX = textList[0].GetComponent<RectTransform>().sizeDelta.x;
 81         deltaY = textList[0].GetComponent<RectTransform>().sizeDelta.y;
 82 
 83         Invoke("ItemList", 0.05f);
 84 
 85     }
 86 
 87     /// <summary>
 88     /// 生成子項item
 89     /// </summary>
 90     /// <param name="itemNum">子項數量</param>
 91     /// <param name="dat">子項最大值</param>
 92     void InstantiateData(int itemNum, int dat) {
 93         GameObject go;
 94         Text testObj = conentRect.FindChild("Text").GetComponent<Text>();
 95         for (int i = dat - itemNum + 1; i <= dat; i++) {
 96             go = Instantiate(testObj.gameObject, conentRect);
 97             go.GetComponent<Text>().text = i.ToString();
 98             go.name = i.ToString();
 99             textList.Add(go.GetComponent<Text>());
100             ShowItem(true);
101         }
102         Destroy(conentRect.FindChild("Text").gameObject);
103     }
104 
105     /// <summary>
106     /// 是增長或減小
107     /// </summary>
108     /// <param name="isIncreaseOrdecrease"></param>
109     void ShowItem(bool isIncreaseOrdecrease) {
110         itemHeight_min = -itemHeight;
111 
112         if (_itemtype == ItemType._day) itemHeight_max = -itemHeight * itemNum - 95;
113         else itemHeight_max = -itemHeight * itemNum;
114 
115         if (isIncreaseOrdecrease) {
116             foreach (Text rectItem in textList) {
117                 if (rectItem.GetComponent<RectTransform>().anchoredPosition.y > itemHeight_min) {
118                     print("+");
119                     rectItem.transform.SetSiblingIndex((int)itemNum);
120                 }
121             }
122             print(itemHeight_min);
123         } else {
124             foreach (Text rectItem in textList) {
125                 if (rectItem.GetComponent<RectTransform>().anchoredPosition.y < itemHeight_max) {
126                     print("-");
127                     rectItem.transform.SetSiblingIndex(0);
128                 }
129             }
130             print(itemHeight_max);
131 
132         }
133     }
134 
135     /// <summary>
136     /// 漸變效果,改變大小,高亮顯示
137     /// </summary>
138     void ItemList() {
139         foreach (Text item in textList) {
140             float indexA = Mathf.Abs(item.GetComponent<RectTransform>().position.y - targetRec.position.y);
141             float indexSc_scale = Mathf.Abs(curve_scale.Evaluate(indexA / contentParentHeight));
142             float indexSc_color = Mathf.Abs(curve_color.Evaluate(indexA / contentParentHeight));
143             if (indexA < 15) {
144                 item.color = itemColor_hig;
145                 switch (_itemtype) {
146                     case ItemType._year: _year = int.Parse(item.text); break;
147                     case ItemType._month: _month = int.Parse(item.text); break;
148                     case ItemType._day: _day = int.Parse(item.text); break;
149                 }
150             } else item.color = new Color(0, 0, 0, 1 - indexSc_color);
151 
152             item.GetComponent<RectTransform>().localScale = new Vector3(1 - indexSc_scale, 1 - indexSc_scale * 3, 1 - indexSc_scale);
153             //item.GetComponent<RectTransform>().sizeDelta = new Vector2(deltaX - (deltaX * indexSc), deltaY - (deltaY * indexSc));
154         }
155 
156     }
157 
158     /// <summary>
159     /// 獲取int類型日期,並轉換爲指定格式
160     /// </summary>
161     /// <returns></returns>
162     public static string GetDateInfo() { return _year + "-" + _month + "-" + _day; }
163 
164     /// <summary>
165     /// 糾正Conent位置
166     /// </summary>
167     void UpdateEx() {
168         if (conentRect.anchoredPosition.y > conentLimit) {
169             ShowItem(true);
170             conentRect.anchoredPosition = new Vector2(conentRect.anchoredPosition.x, conentRect.anchoredPosition.y - itemHeight);
171         }
172         if (conentRect.anchoredPosition.y < conentLimit) {
173             ShowItem(false);
174             conentRect.anchoredPosition = new Vector2(conentRect.anchoredPosition.x, conentRect.anchoredPosition.y + itemHeight);
175         }
176     }
177 
178     /// <summary>
179     /// 獲取拖拽信息並改變Conent位置
180     /// </summary>
181     /// <param name="eventData"></param>
182     void SetDraggedPosition(PointerEventData eventData) {
183         if (RectTransformUtility.ScreenPointToWorldPointInRectangle(conentRect, eventData.position, eventData.pressEventCamera, out newDragPos)) {
184             newDragPos = eventData.position;
185             if (Mathf.Abs(newDragPos.y - oldDragPos.y) >= itemHeight) {
186                 if (newDragPos.y > oldDragPos.y) {
187                     conentRect.anchoredPosition = new Vector2(conentRect.anchoredPosition.x, conentRect.anchoredPosition.y + itemHeight);
188                     oldDragPos += new Vector3(0, itemHeight, 0);
189                     ItemList();
190                 } else {
191                     conentRect.anchoredPosition = new Vector2(conentRect.anchoredPosition.x, conentRect.anchoredPosition.y - itemHeight);
192                     oldDragPos -= new Vector3(0, itemHeight, 0);
193                     ItemList();
194                 }
195             }
196         }
197     }
198 
199     /// <summary>
200     /// 當開始拖拽
201     /// </summary>
202     /// <param name="eventData"></param>
203     public void OnBeginDrag(PointerEventData eventData) {
204         oldDragPos = eventData.position;
205     }
206 
207     public void OnDrag(PointerEventData eventData) {
208         SetDraggedPosition(eventData);
209         UpdateEx();
210     }
211 
212     public void OnEndDrag(PointerEventData eventData) {
213         SetDraggedPosition(eventData);
214         UpdateEx();
215     }
216 }

 

照着來的話基本沒什麼問題

由於趕時間因此不少地方寫的簡單粗暴請諒解

若是調整元素大小或者間隙大小 須要改變itemHeight_min 和 itemHeight_max 的值

他們分別爲

itemHeight_min 

itemHeight_max 

也就是元素的最頂層和最底層的Y值

 

以上就是年月日選擇器的具體步驟

相關文章
相關標籤/搜索