效果图
用的是UGUI
我先说思路
通过判断元素的位置信息来改变Hierarchy的顺序 实现无限滚动
改变位置的同时也要不断的调整Content的位置防止乱跳
元素锁定就是直接锁死的元素的移动范围 当只有拖动大于一定程度时才会发生改变
然后是面板设置
整体结构是这样子的
需要注意的是Content需要的两个组件
Content的爸爸只需要一个脚本
大小改变曲线(大致就行)
颜色渐变曲线
最后是脚本
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值
以上就是年月日选择器的具体步骤