zoukankan      html  css  js  c++  java
  • Unity3d—做一个年月日选择器(Scroll Rect拖动效果优化)— 无限滚动 + 锁定元素

    效果图

    用的是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值

    以上就是年月日选择器的具体步骤

  • 相关阅读:
    心理学安全威胁
    设计模式是在运用构造定律
    分形理论
    构造定律
    [SOA]REST与SOA两种架构的异同比较
    加法是自然之道
    ES : 软件工程学的复杂度理论及物理学解释
    软件架构的灵活设计
    软件复杂度与结构:(影响复杂度的因素)
    socket 的通信过程
  • 原文地址:https://www.cnblogs.com/sangblog/p/6995534.html
Copyright © 2011-2022 走看看