• Unity NGUI ScrollView 苹果式滑动


    又回来写博客了,这回已经开始上班了,所以就发一发工作中解决的难题吧。

    单个展示Panel(苹果式)

    以前对UI的滑动组件很烦心,不是很会用,这回项目要求写一个类似于苹果的文件滑动效果,但是苹果就展示一个文件,而我这边展示数目不定,头疼!

    下面就直接来干货吧~,这里附送一个苹果式滑动解决方式 : 点这里

    多个展示Panel(改写)

    而我追求的效果呢,稍微改动一下,如下:(中间显示很多个,旁边的在叠起来的效果)

    这里我们采用比例的方式,这样好控制一些。

    几个比较重要的点:

    • 每个Panel之间的比例差值
    _offset = 1f / (totalPanelCount - showPanelCount); // 1f / (总共Panel - 展示Panel)
    • 获得拖动结束要偏移到的目标位置
    private float GetTarget()
    {
        return Mathf.Clamp01(Mathf.RoundToInt(_scrollValue / _offset) * _offset); // 取得最近的整数位
    }
    • 分成三个区域,左缩放区域,右缩放区域,中间展示区域
     1     private void AnimationCore(int index)
     2     {
     3         float sourcePos = index * _offset;
     4         // 左边区域
     5         if (sourcePos < _scrollValue)
     6         {
     7             float dif = _scrollValue - sourcePos;
     8             int depth = _currentIndex - index;
     9             _panelPool[index].transform.SetSiblingIndex(totalPanelCount - depth - 2);
    10             _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, GetTargetPos(index, dif, true), 100 * Time.deltaTime);
    11         }
    12         // 右边区域
    13         else if (sourcePos > _scrollValue + _offset * (showPanelCount - 1))
    14         {
    15             float dif = sourcePos - _scrollValue - _offset * (showPanelCount - 1);
    16             int depth = index - _currentIndex - showPanelCount + 1;
    17             _panelPool[index].transform.SetSiblingIndex(totalPanelCount - depth - 2);
    18             _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, GetTargetPos(index, dif, false), 100 * Time.deltaTime);
    19         }
    20         // 中间区域
    21         else
    22         {
    23             _panelPool[index].transform.SetAsLastSibling();
    24             _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, _panelPoolPos[index], 100 * Time.deltaTime);
    25         }
    26     }
    • 获取Panel的滑动偏移位置
        private Vector3 GetTargetPos(int index, float dif, bool isLeft)
        {
            float offSetDif = 60 / _offset * dif;
            if (isLeft)
            {
                return _panelPoolPos[index] + Vector3.right * offSetDif; // 左区域
            }
            else
            {
                return _panelPoolPos[index] - Vector3.right * offSetDif; // 右区域
            }
        }
    • 获取当前滑动的位置
     1     private float _scrollValue
     2     {
     3         get
     4         {
     5             return _scrollRect.horizontal ?
     6                 _scrollRect.horizontalNormalizedPosition :
     7                 _scrollRect.verticalNormalizedPosition;
     8         }
     9 
    10         set
    11         {
    12             if (_scrollRect.horizontal)
    13             {
    14                 _scrollRect.horizontalNormalizedPosition = value;
    15             }
    16             else
    17             {
    18                 _scrollRect.verticalNormalizedPosition = value;
    19             }
    20         }
    21     }

    需要继承NGUI的EventSystem的时间来触发管理拖动 PS:用DOTween做最后的回滑效果

    完整代码如下:

      1 using System;
      2 using UnityEngine;
      3 using UnityEngine.EventSystems;
      4 using UnityEngine.UI;
      5 using DG.Tweening;
      6 
      7 [RequireComponent(typeof(ScrollRect))]
      8 public class ScrollController : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
      9 {
     10     [Tooltip("创建出来的对象")]
     11     public GameObject imageObject;
     12     [Tooltip("展示页面数量")]
     13     public int showPanelCount = 8;
     14     [Tooltip("总计页面数量")]
     15     public int totalPanelCount = 20;
     16     [Tooltip("拖动结束制动弹回制动时间")]
     17     public float endDragMoveTime = 1f;
     18     public Ease doTweenEase = Ease.OutExpo;
     19 
     20     private int _currentIndex;
     21     private ScrollRect _scrollRect;
     22     private Tweener _tweener;
     23     private GameObject[] _panelPool = new GameObject[20];
     24     private Vector3[] _panelPoolPos = new Vector3[20];
     25     private float _offset;
     26 
     27     void Start()
     28     {
     29         _currentIndex = 1;
     30         _scrollRect = GetComponent<ScrollRect>();
     31         _scrollRect.inertia = false;
     32 
     33         for (int i = 0; i < totalPanelCount; i++)
     34         {
     35             GameObject go = Instantiate(imageObject) as GameObject;
     36             go.transform.SetParent(_scrollRect.content.transform);
     37             go.GetComponent<RectTransform>().sizeDelta = new Vector2(100, 200);
     38             go.GetComponent<RectTransform>().anchorMax = new Vector2(0, 0.5f);
     39             go.GetComponent<RectTransform>().anchorMin = new Vector2(0, 0.5f);
     40             go.GetComponent<RectTransform>().pivot = new Vector2(0, 0.5f);
     41             go.GetComponent<RectTransform>().anchoredPosition = new Vector2(100 + 100 * i, 0);
     42             go.transform.localScale = Vector3.one;
     43             _panelPool[i] = go;
     44             _panelPoolPos[i] = go.transform.localPosition;
     45         }
     46 
     47         _scrollRect.content.GetComponent<RectTransform>().sizeDelta = new Vector2(totalPanelCount * 100 + 200, 200);
     48 
     49         _offset = 1f / (totalPanelCount - showPanelCount);
     50 
     51         for (int i = 0; i < totalPanelCount; i++)
     52         {
     53             AnimationCore(i);
     54         }
     55     }
     56 
     57     public void OnBeginDrag(PointerEventData eventData)
     58     {
     59         if (_tweener != null && _tweener.IsActive())
     60         {
     61             _tweener.Kill();
     62         }
     63     }
     64 
     65     public void OnDrag(PointerEventData eventData)
     66     {
     67         _currentIndex = Mathf.RoundToInt(GetTarget() * (totalPanelCount - showPanelCount));
     68 
     69         OnDragAnimation();
     70     }
     71 
     72     public void OnEndDrag(PointerEventData eventData)
     73     {
     74         _tweener = DOTween.To(() => _scrollValue, (v) => _scrollValue = v, GetTarget(), endDragMoveTime).SetEase(doTweenEase);
     75         _tweener.onUpdate = () =>
     76         {
     77             OnDragAnimation();
     78         };
     79     }
     80 
     81     private void OnDragAnimation()
     82     {
     83         //向左拉动(解决层级问题)
     84         if (_scrollValue > 0)
     85         {
     86             for (int i = 0; i < totalPanelCount; i++)
     87             {
     88                 AnimationCore(i);
     89             }
     90         }
     91         else
     92         {
     93             for (int i = totalPanelCount - 1; i >= 0; i--)
     94             {
     95                 AnimationCore(i);
     96             }
     97         }
     98     }
     99 
    100     private void AnimationCore(int index)
    101     {
    102         float sourcePos = index * _offset;
    103         // 左边区域
    104         if (sourcePos < _scrollValue)
    105         {
    106             float dif = _scrollValue - sourcePos;
    107             int depth = _currentIndex - index;
    108             _panelPool[index].transform.SetSiblingIndex(totalPanelCount - depth - 2);
    109             _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, GetTargetPos(index, dif, true), 100 * Time.deltaTime);
    110         }
    111         // 右边区域
    112         else if (sourcePos > _scrollValue + _offset * (showPanelCount - 1))
    113         {
    114             float dif = sourcePos - _scrollValue - _offset * (showPanelCount - 1);
    115             int depth = index - _currentIndex - showPanelCount + 1;
    116             _panelPool[index].transform.SetSiblingIndex(totalPanelCount - depth - 2);
    117             _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, GetTargetPos(index, dif, false), 100 * Time.deltaTime);
    118         }
    119         // 中间区域
    120         else
    121         {
    122             _panelPool[index].transform.SetAsLastSibling();
    123             _panelPool[index].transform.localPosition = Vector3.Lerp(_panelPool[index].transform.localPosition, _panelPoolPos[index], 100 * Time.deltaTime);
    124         }
    125     }
    126 
    127     /// <summary>
    128     /// 获取到页面的偏移后位置
    129     /// </summary>
    130     /// <returns></returns>
    131     private Vector3 GetTargetPos(int index, float dif, bool isLeft)
    132     {
    133         float offSetDif = 60 / _offset * dif;
    134         if (isLeft)
    135         {
    136             return _panelPoolPos[index] + Vector3.right * offSetDif;
    137         }
    138         else
    139         {
    140             return _panelPoolPos[index] - Vector3.right * offSetDif;
    141         }
    142     }
    143 
    144     /// <summary>
    145     /// 获得偏转目标位置
    146     /// </summary>
    147     /// <returns></returns>
    148     private float GetTarget()
    149     {
    150         return Mathf.Clamp01(Mathf.RoundToInt(_scrollValue / _offset) * _offset);
    151     }
    152 
    153     /// <summary>
    154     /// 当前滑动位置
    155     /// </summary>
    156     /// <returns></returns>
    157     private float _scrollValue
    158     {
    159         get
    160         {
    161             return _scrollRect.horizontal ?
    162                 _scrollRect.horizontalNormalizedPosition :
    163                 _scrollRect.verticalNormalizedPosition;
    164         }
    165 
    166         set
    167         {
    168             if (_scrollRect.horizontal)
    169             {
    170                 _scrollRect.horizontalNormalizedPosition = value;
    171             }
    172             else
    173             {
    174                 _scrollRect.verticalNormalizedPosition = value;
    175             }
    176         }
    177     }
    178 }
  • 相关阅读:
    Docker 学习笔记
    Docker 镜像加速器(如何加速下载)
    Simple-DQN代码的理解笔记
    c语言NULL和0区别及NULL详解
    C 语言的 const 指针,指针的const有什么不同
    Edge和Level触发的中断
    尚硅谷设计模式笔记-适配器模式
    nginx服务器部署dist文件夹
    nginx服务器部署dist文件夹
    Jexl表达式引擎-根据字符串动态执行JAVA.md
  • 原文地址:https://www.cnblogs.com/SHOR/p/7581142.html
Copyright © 2020-2023  润新知