Unity ScrollView實現(xiàn)自動吸附效果
本文實例為大家分享了Unity ScrollView實現(xiàn)自動吸附效果的具體代碼,供大家參考,具體內(nèi)容如下
一、效果演示

二、實現(xiàn)思路
通過使用UGUI的拖拽接口,在拖拽結(jié)束時比較當(dāng)前滑動框的NormalizedPositon與每一頁的NormalizedPositon值,找到距離當(dāng)前拖拽結(jié)束位置最近的頁并緩慢滑動過去
三、使用說明
——此功能腳本是對ScrollView的擴展,所以必須添加UGUI提供的基礎(chǔ)Scroll View
——Content上必須添加GridLayoutGroup組件并添加所有列表中的項(不是動態(tài)添加),只是為了方便滿足布局需求(我在代碼中對startCorner、startAxis、childAlignment和constraintCount進行了限制,不需要對其設(shè)置)
——不能添加Content Size Fitter組件
——測試出適合的視為滑動一頁的距離和視為滑動多頁的距離數(shù)值并填入即可
四、完整代碼
將AutoAdsorbScrollView腳本掛載到ScrollView上
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
/// <summary>
/// 自動吸附的滑動列表
/// </summary>
public class AutoAdsorbScrollView : MonoBehaviour, IBeginDragHandler, IEndDragHandler
{
private ScrollRect scrollRect;//滑動框組件
private RectTransform content;//滑動框的Content
private GridLayoutGroup layout;//布局組件
private int totalPage; //總頁數(shù)
private int curPage; //當(dāng)前頁的下標(biāo)
private float[] eachPageNUPos; //每頁的NormalizedPositon的值
private float targetNUPos; //目標(biāo)頁的NormalizedPositon的值
private Vector2 beginMousePos; //鼠標(biāo)開始按下的位置
private Vector2 endMousePos; //鼠標(biāo)結(jié)束按下的位置
private bool isDrag; //是否在拖拽
[Header("是否可以滑動多頁")]
public bool sliderMultPage;
[Header("視為滑動一頁的距離")]
[Space(25)]
public float sliderOnePageDis;
[Header("視為滑動多頁的距離")]
public float sliderMultPageDis;
[Header("緩動到目標(biāo)頁的持續(xù)時間")]
public float duration;
#region Init
private void Awake()
{
scrollRect = GetComponent<ScrollRect>();
content = scrollRect.content;
layout = content.GetComponent<GridLayoutGroup>();
Init();//初始化
}
/// <summary>
/// 初始化
/// </summary>
private void Init()
{
totalPage = content.childCount;
SetContentSize();//設(shè)置Content大小
CalcEachPageNUPos();//計算每一頁的NormalizedPositon值
SetLayout();//設(shè)置布局
}
/// <summary>
/// 設(shè)置Content大小
/// </summary>
private void SetContentSize()
{
content.sizeDelta = new Vector2
(
layout.padding.right + layout.padding.left + (totalPage - 1) * (layout.cellSize.x + layout.spacing.x) - layout.spacing.x,
content.sizeDelta.y
); ;
}
/// <summary>
/// 計算每一頁的NormalizedPositon值
/// </summary>
private void CalcEachPageNUPos()
{
float tempNUPos = 0;
eachPageNUPos = new float[totalPage];
for (int i = 0; i < totalPage; i++)
{
eachPageNUPos[i] = tempNUPos;
tempNUPos += 1f / (totalPage - 1);
}
}
/// <summary>
/// 設(shè)置布局
/// </summary>
private void SetLayout()
{
scrollRect.horizontal = true;
scrollRect.vertical = false;
layout.padding.right = layout.padding.left;
layout.startCorner = GridLayoutGroup.Corner.UpperLeft;
layout.childAlignment = TextAnchor.MiddleCenter;
layout.constraintCount = 1;
}
#endregion
#region Main
/// <summary>
/// 拖拽開始
/// </summary>
public void OnBeginDrag(PointerEventData eventData)
{
isDrag = true;
beginMousePos = Input.mousePosition;
}
/// <summary>
/// 拖拽結(jié)束
/// </summary>
/// <param name="eventData"></param>
public void OnEndDrag(PointerEventData eventData)
{
isDrag = false;
coe = 0;
endMousePos = Input.mousePosition;
Vector2 offset = endMousePos - beginMousePos;
Debug.Log("滑動距離為:" + offset);
if (sliderMultPage)
{
//單頁滑動
if (Mathf.Abs(offset.x) >= sliderOnePageDis && Mathf.Abs(offset.x) < sliderMultPageDis)
{
float tempHorizontalNUPos = scrollRect.horizontalNormalizedPosition;
FindNearlyPage(tempHorizontalNUPos);
}
//多頁滑動
else if (Mathf.Abs(offset.x) >= sliderMultPageDis)
{
if (offset.x > 0)
{
curPage = 0;
}
else if (offset.x < 0)
{
curPage = totalPage - 1;
}
}
}
else
{
//單頁滑動
if (Mathf.Abs(offset.x) >= sliderOnePageDis)
{
float tempHorizontalNUPos = scrollRect.horizontalNormalizedPosition;
FindNearlyPage(tempHorizontalNUPos);
}
}
targetNUPos = eachPageNUPos[curPage];
}
private float coe;//比例系數(shù)
private void Update()
{
if (isDrag)
{
return;
}
coe += Time.deltaTime / duration;
scrollRect.horizontalNormalizedPosition = Mathf.Lerp(scrollRect.horizontalNormalizedPosition, targetNUPos, coe);
}
#endregion
#region Tool
/// <summary>
/// 尋找距離當(dāng)前NormalizedPositon最近的頁
/// </summary>
private void FindNearlyPage(float tempHorizontalNUPos)
{
float minOffset = Mathf.Abs(eachPageNUPos[0] - tempHorizontalNUPos);
for (int i = 0; i < totalPage; i++)
{
float tempHorizontalOffset = Mathf.Abs(eachPageNUPos[i] - tempHorizontalNUPos);
if (tempHorizontalOffset <= minOffset)
{
minOffset = tempHorizontalOffset;
curPage = i;
}
}
}
#endregion
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#基于正則表達式抓取a標(biāo)簽鏈接和innerhtml的方法
這篇文章主要介紹了C#基于正則表達式抓取a標(biāo)簽鏈接和innerhtml的方法,結(jié)合實例形式分析了C#使用正則表達式進行頁面元素的匹配與抓取相關(guān)操作技巧,需要的朋友可以參考下2017-06-06
C# .net core HttpClientFactory用法及說明
這篇文章主要介紹了C# .net core HttpClientFactory用法及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11
本文主要介紹了C#中利用GDI來繪制圖形和文字的方法,并提供的簡單的示例供大家參考學(xué)習(xí),希望能夠?qū)Υ蠹矣兴鶐椭?/div> 2016-03-03
C# List實現(xiàn)行轉(zhuǎn)列的通用方案
本篇通過行轉(zhuǎn)列引出了System.Linq.Dynamic,并且介紹了過濾功能,具有很好的參考價值。下面跟著小編一起來看下吧2017-03-03最新評論

