Unity 制作时间选择器

首先来看一下要实现的功能效果
在这里插入图片描述
一、搭建场景
新建一个按钮,用来控制选择时间界面的显示的。如下,按钮下有一个图片,一个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

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小温同学的账号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值