using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; namespace JC.Unity.Picker { /// /// 日期选择器 /// public class DatePicker : MonoBehaviour, IDragHandler, IEndDragHandler { public enum DateType { Year, Month, Day, Hour, Minute, Second } /// /// 日期类型 (年月日时分秒) /// public DateType dateType; /// /// 子节点预制体 /// public GameObject _itemObj; /// /// 子节点容器对象 /// public Transform _itemParent; /// /// 我属于的日期选择组 /// [HideInInspector] public DatePickerGroup myGroup; /// /// 最少节点数量 /// void Awake() { _itemObj.SetActive(false); } public void Init() { InitItems(); } void InitItems() { DateTime dt = myGroup.selectDate; ItemData itemData = SpawnItem(GetTopPosY(), dt, GetDateValue(dt).ToString()); itemList.Add(itemData); MoveItems(0); CheckSelect(); } public void Refresh() { foreach (var item in itemList) { Destroy(item.obj); } itemList.Clear(); InitItems(); } float GetTopPosY() { return 0; } float GetBottomPosY() { return -myGroup.GetHeight(); } float _cellHeight = -1; float GetCellHeight() { if (_cellHeight == -1) _cellHeight = _itemObj.GetComponent().rect.height; return _cellHeight; } public void OnDrag(PointerEventData eventData) { MoveItems(eventData.delta.y); } void MoveItems(float dy) { foreach (var item in itemList) { item.SetY(dy, true); } while (itemList[0].GetY() < GetTopPosY()) { ItemData compareItemData = itemList[0]; DateTime dt = ChangeDateTime(compareItemData.dateTime, -1); if (!IsInDate(dt, myGroup.minDate, myGroup.maxDate)) { break; } ItemData itemData = SpawnItem(compareItemData.GetY() + GetCellHeight(), dt, GetDateValue(dt).ToString()); itemList.Insert(0, itemData); } while (itemList.Count > 1 && itemList[0].GetY() > GetTopPosY() + GetCellHeight()) { Destroy(itemList[0].obj); itemList.RemoveAt(0); } while (itemList[itemList.Count - 1].GetY() > GetBottomPosY()) { ItemData compareItemData = itemList[itemList.Count - 1]; DateTime dt = ChangeDateTime(compareItemData.dateTime, +1); if (!IsInDate(dt, myGroup.minDate, myGroup.maxDate)) { break; } ItemData itemData = SpawnItem(compareItemData.GetY() - GetCellHeight(), dt, GetDateValue(dt).ToString()); itemList.Add(itemData); } while (itemList.Count > 1 && itemList[itemList.Count - 1].GetY() < GetBottomPosY()) { Destroy(itemList[itemList.Count - 1].obj); itemList.RemoveAt(itemList.Count - 1); } } public void OnEndDrag(PointerEventData eventData) { CheckSelect(); myGroup.onDateUpdate(); } void CheckSelect() { float dy = 0; float minDist = float.MaxValue; ItemData targetItem = null; foreach (var item in itemList) { item.SetSelected(false); float val = item.GetY() - 0; float absVal = Mathf.Abs(val); if (absVal < minDist) { //选中最符合的节点 minDist = absVal; targetItem = item; dy = val; } } if (dy != 0) { MoveItems(-dy); } targetItem.SetSelected(true); myGroup.selectDate = targetItem.dateTime; } DateTime ChangeDateTime(DateTime dateTime, int num) { switch (dateType) { case DateType.Year: dateTime = dateTime.AddYears(num); break; case DateType.Month: dateTime = dateTime.AddMonths(num); break; case DateType.Day: dateTime = dateTime.AddDays(num); break; case DateType.Hour: dateTime = dateTime.AddHours(num); break; case DateType.Minute: dateTime = dateTime.AddMinutes(num); break; case DateType.Second: dateTime = dateTime.AddSeconds(num); break; } return dateTime; } int GetDateValue(DateTime dateTime) { switch (dateType) { case DateType.Year: return dateTime.Year; case DateType.Month: return dateTime.Month; case DateType.Day: return dateTime.Day; case DateType.Hour: return dateTime.Hour; case DateType.Minute: return dateTime.Minute; case DateType.Second: return dateTime.Second; } return 0; } bool IsInDate(DateTime dt, DateTime dt_min, DateTime dt_max) { return dt.CompareTo(dt_min) >= 0 && dt.CompareTo(dt_max) <= 0; } public class ItemData { public GameObject obj; public DateTime dateTime; public bool selected = false; public float GetY() { return obj.GetComponent().localPosition.y; } public void SetY(float y, bool plus = false) { RectTransform rectTF = obj.GetComponent(); Vector3 pos = rectTF.localPosition; if (plus) { pos.y += y; } else { pos.y = y; } rectTF.localPosition = pos; } public void SetText(string text) { obj.GetComponent().text = text; } public void SetColor(Color color) { obj.GetComponent().color = color; } public void SetSelected(bool val) { selected = val; SetColor(selected ? Color.green : Color.grey); } } List itemList = new List(); ItemData SpawnItem(float y, DateTime dateTime, string text) { ItemData itemData = new ItemData(); itemData.dateTime = dateTime; itemData.obj = Instantiate(_itemObj, _itemParent); itemData.SetY(y); itemData.SetText(text); itemData.SetSelected(false); itemData.obj.SetActive(true); return itemData; } } }