首先来看一下要实现的功能效果
一、搭建场景
新建一个按钮,用来控制选择时间界面的显示的。如下,按钮下有一个图片,一个Text。图片用来显示箭头,文字用来显示选择的时间
新建TimeDate界面(时间选择界面)。.背景啥的全看个人爱好设计。这里只是随便弄了一个。主要的内容全部在Time的下面。下面开始搭建一下,(以年为例,月,日,时,分,秒和年同理)
新建一张Image,起名Year_Picker.在Year_Picker上添加Mask(遮罩)组件(可有可无,不重要)。再在Year_Picker下创建一个Text,起名Item。在创建一个空物体,起名Content。添加组件Content Size Fitter和Vertical Layout Group。。注意。下图中Content的组件的设置,按照图片上的来就可以,如下图:
以此类推,创建好其他几个部分,UI界面如下:
UI界面已经全部完事了,加下来给Time上添加脚本:DatePickerGroup。将创建好的年月日等依次放到DatePickerList中。如下:
在年月日的分支上添加DatePicker脚本,其中DateType选择对应的选项(年月日时分秒),ItemNum填5(奇数),可根据自身情况修改,显示前后时间的各数,这里是一下显示五个。。ItemObj 为刚刚创建的Text,ItemParent为Content。效果如下:
接下来就开始编写脚本了,直接上代码,都有注释,应该是能看懂的
DatePickerGroup脚本:
using System;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 日期选择组
/// </summary>
public class DatePickerGroup : MonoBehaviour
{
/// <summary>
/// 最小日期和最大日期
/// </summary>
public DateTime _minDate, _maxDate;
/// <summary>
/// 选择的日期(年月日时分秒)
/// </summary>
public DateTime _selectDate;
/// <summary>
/// 时间选择器列表
/// </summary>
public List<DatePicker> _datePickerList;
/// <summary>
/// 当选择日期的委托事件
/// </summary>
public event OnDateUpdate _OnDateUpdate;
public static DateTime _selectTime;
void Awake()
{
//设置最大最小日期
_minDate = new DateTime(1999, 1, 1, 0, 0, 0);
_maxDate = new DateTime(2050, 1, 1, 0, 0, 0);
Init();
}
private void Update()
{
}
public void Init(DateTime dt)
{
_selectDate = dt;
for (int i = 0; i < _datePickerList.Count; i++)
{
_datePickerList[i].myGroup = this;
_datePickerList[i].Init();
_datePickerList[i]._onDateUpdate += onDateUpdate;
}
}
public void Init()
{
_selectDate = DateTime.Now;
for (int i = 0; i < _datePickerList.Count; i++)
{
_datePickerList[i].myGroup = this;
_datePickerList[i].Init();
_datePickerList[i]._onDateUpdate += onDateUpdate;
}
}
/// <summary>
/// 当选择的日期更新
/// </summary>
public void onDateUpdate()
{
Debug.Log("当前选择日期:" + _selectDate.ToString("yyyy年MM月dd日 HH : mm : ss"));
//将选中的时间给_selectTime ,供其他界面调用
_selectTime = _selectDate;
for (int i = 0; i < _datePickerList.Count; i++)
{
_datePickerList[i].RefreshDateList();
}
}
}
DatePicker脚本:
using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
/// <summary>
/// 当选择日期的委托
/// </summary>
public delegate void OnDateUpdate();
public enum DateType
{
_year, _month, _day,
_hour, _minute, _second
}
/// <summary>
/// 日期选择器
/// </summary>
public class DatePicker : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
/// <summary>
/// 日期类型 (年月日时分秒)
/// </summary>
public DateType _dateType;
/// <summary>
/// 子节点数量(奇数)
/// </summary>
public int _itemNum = 5;
[HideInInspector]
/// <summary>
/// 更新选择的目标值
/// </summary>
public float _updateLength;
/// <summary>
/// 子节点预制体
/// </summary>
public GameObject _itemObj;
/// <summary>
/// 子节点容器对象
/// </summary>
public Transform _itemParent;
/// <summary>
/// 我属于的日期选择组
/// </summary>
[HideInInspector]
public DatePickerGroup myGroup;
/// <summary>
/// 当选择日期的委托事件
/// </summary>
public event OnDateUpdate _onDateUpdate;
void Awake()
{
_itemObj.SetActive(false);
_updateLength = _itemObj.GetComponent<RectTransform>().sizeDelta.y;
}
/// <summary>
/// 初始化时间选择器
/// </summary>
public void Init()
{
for (int i = 0; i < _itemNum; i++)
{
//计算真实位置
int real_i = -(_itemNum / 2) + i;
SpawnItem(real_i);
}
RefreshDateList();
}
/// <summary>
/// 生成子对象
/// </summary>
/// <param name="dataNum">对应日期</param>
/// <param name="real_i">真实位置</param>
/// <returns></returns>
GameObject SpawnItem(float real_i)
{
GameObject _item = Instantiate(_itemObj);
_item.SetActive(true);
_item.transform.SetParent(_itemParent);
_item.transform.localScale = new Vector3(1, 1, 1);
_item.transform.localEulerAngles = Vector3.zero;
if (real_i != 0)
{
_item.GetComponent<Text>().color = new Color(1, 1, 1, 1 - 0.2f - (Mathf.Abs(real_i) / (_itemNum / 2 + 1)));
}
return _item;
}
Vector3 oldDragPos;
/// <summary>
/// 当开始拖拽
/// </summary>
/// <param name="eventData"></param>
public void OnBeginDrag(PointerEventData eventData)
{
oldDragPos = eventData.position;
}
public void OnDrag(PointerEventData eventData)
{
//Debug.Log("拖拽");
UpdateSelectDate(eventData);
}
public void OnEndDrag(PointerEventData eventData)
{
_itemParent.localPosition = Vector3.zero;
}
/// <summary>
/// 更新选择的时间
/// </summary>
/// <param name="eventData"></param>
void UpdateSelectDate(PointerEventData eventData)
{
//判断拖拽的长度是否大于目标值
if (Mathf.Abs(eventData.position.y - oldDragPos.y) >= _updateLength)
{
int num;
//判断加减
if (eventData.position.y > oldDragPos.y)
{
//+
num = 1;
}
else
{
//-
num = -1;
}
DateTime _data = new DateTime();
switch (_dateType)
{
case DateType._year:
_data = myGroup._selectDate.AddYears(num);
break;
case DateType._month:
_data = myGroup._selectDate.AddMonths(num);
break;
case DateType._day:
_data = myGroup._selectDate.AddDays(num);
break;
case DateType._hour:
_data = myGroup._selectDate.AddHours(num);
break;
case DateType._minute:
_data = myGroup._selectDate.AddMinutes(num);
break;
case DateType._second:
_data = myGroup._selectDate.AddSeconds(num);
break;
}
//判断是否属于时间段
if (IsInDate(_data, myGroup._minDate, myGroup._maxDate))
{
myGroup._selectDate = _data;
oldDragPos = eventData.position;
_onDateUpdate();
}
// _itemParent.localPosition = Vector3.zero;
}
else
{
//_itemParent.localPosition = new Vector3(0, (eventData.position.y - oldDragPos.y), 0);
}
}
/// <summary>
/// 刷新时间列表
/// </summary>
public void RefreshDateList()
{
DateTime _data = new DateTime();
for (int i = 0; i < _itemNum; i++)
{
//计算真实位置
int real_i = -(_itemNum / 2) + i;
switch (_dateType)
{
case DateType._year:
_data = myGroup._selectDate.AddYears(real_i);
break;
case DateType._month:
_data = myGroup._selectDate.AddMonths(real_i);
break;
case DateType._day:
_data = myGroup._selectDate.AddDays(real_i);
break;
case DateType._hour:
_data = myGroup._selectDate.AddHours(real_i);
break;
case DateType._minute:
_data = myGroup._selectDate.AddMinutes(real_i);
break;
case DateType._second:
_data = myGroup._selectDate.AddSeconds(real_i);
break;
}
string str = "";
if (IsInDate(_data, myGroup._minDate, myGroup._maxDate))
{
switch (_dateType)
{
case DateType._year:
str = _data.Year.ToString();
break;
case DateType._month:
str = _data.Month.ToString();
break;
case DateType._day:
str = _data.Day.ToString();
break;
case DateType._hour:
str = _data.Hour.ToString();
break;
case DateType._minute:
str = _data.Minute.ToString();
break;
case DateType._second:
str = _data.Second.ToString();
break;
}
}
_itemParent.GetChild(i).GetComponent<Text>().text = str;
}
}
/// <summary>
/// 判断某个日期是否在某段日期范围内,返回布尔值
/// </summary>
/// <param name="dt">要判断的日期</param>
/// <param name="dt_min">开始日期</param>
/// <param name="dt_max">结束日期</param>
/// <returns></returns>
public bool IsInDate(DateTime dt, DateTime dt_min, DateTime dt_max)
{
return dt.CompareTo(dt_min) >= 0 && dt.CompareTo(dt_max) <= 0;
}
}
最后一个,按钮脚本,控制选择时间的脚本:
using System;
using UnityEngine;
using UnityEngine.UI;
public class ChoiceTime : MonoBehaviour
{
[Tooltip("箭头图片")]
public Sprite[] Arrows;
//显示时间的文字
private Text ShowText;
//显示箭头的图片
private Image ArrowsImage;
//选择时间界面
private GameObject ChoiceTimeObj;
//按钮
private Button ChoiceBtn;
//是否选择时间
private bool isShowChoiceTime;
// Use this for initialization
void Start()
{
ShowText = GameObject.Find("Text").GetComponent<Text>();
ArrowsImage = GameObject.Find("ShowArrows").GetComponent<Image>();
ChoiceTimeObj = GameObject.Find("TimeData");
ChoiceBtn = GameObject.Find("Button").GetComponent<Button>();
ChoiceBtn.onClick.AddListener(StartChoiceTime);
//开始默认选择系统时间
ShowText.text = DateTime.Now.ToString("yyyy年MM月dd日 HH : mm : ss");
ChoiceTimeObj.SetActive(false);
}
// Update is called once per frame
void Update()
{
if (ChoiceTimeObj.activeSelf)
{
isShowChoiceTime = true;
}
else
{
isShowChoiceTime = false;
}
}
public void StartChoiceTime()
{
//作战时间的number为1,开始时间的number为2
if (!isShowChoiceTime)
{
//显示选择时间界面
ChoiceTimeObj.SetActive(true);
//箭头向下
ArrowsImage.sprite = Arrows[1];
}
else
{
//关闭选择时间界面
ChoiceTimeObj.SetActive(false);
//是否显示时间选择界面为false
isShowChoiceTime = false;
//箭头向上
ArrowsImage.sprite = Arrows[0];
//判断选没选择日期,当只点开选择框没有选择时,默认的日期会变为001年。所以要判断下
if (DatePickerGroup._selectTime.ToString("yyyy年MM月dd日 HH : mm : ss").Substring(0, 3) == "000")
{
ShowText.text = DateTime.Now.ToString("yyyy年MM月dd日 HH : mm : ss");
}
else
{
ShowText.text = DatePickerGroup._selectTime.ToString("yyyy年MM月dd日 HH : mm : ss");
}
}
}
}
附:工程文件下载地址
https://download.csdn.net/download/sinat_39291423/11228915