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

二、實(shí)現(xiàn)思路
通過(guò)使用UGUI的拖拽接口,在拖拽結(jié)束時(shí)比較當(dāng)前滑動(dòng)框的NormalizedPositon與每一頁(yè)的NormalizedPositon值,找到距離當(dāng)前拖拽結(jié)束位置最近的頁(yè)并緩慢滑動(dòng)過(guò)去
三、使用說(shuō)明
——此功能腳本是對(duì)ScrollView的擴(kuò)展,所以必須添加UGUI提供的基礎(chǔ)Scroll View
——Content上必須添加GridLayoutGroup組件并添加所有列表中的項(xiàng)(不是動(dòng)態(tài)添加),只是為了方便滿(mǎn)足布局需求(我在代碼中對(duì)startCorner、startAxis、childAlignment和constraintCount進(jìn)行了限制,不需要對(duì)其設(shè)置)
——不能添加Content Size Fitter組件
——測(cè)試出適合的視為滑動(dòng)一頁(yè)的距離和視為滑動(dòng)多頁(yè)的距離數(shù)值并填入即可
四、完整代碼
將AutoAdsorbScrollView腳本掛載到ScrollView上
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
/// <summary>
/// 自動(dòng)吸附的滑動(dòng)列表
/// </summary>
public class AutoAdsorbScrollView : MonoBehaviour, IBeginDragHandler, IEndDragHandler
{
private ScrollRect scrollRect;//滑動(dòng)框組件
private RectTransform content;//滑動(dòng)框的Content
private GridLayoutGroup layout;//布局組件
private int totalPage; //總頁(yè)數(shù)
private int curPage; //當(dāng)前頁(yè)的下標(biāo)
private float[] eachPageNUPos; //每頁(yè)的NormalizedPositon的值
private float targetNUPos; //目標(biāo)頁(yè)的NormalizedPositon的值
private Vector2 beginMousePos; //鼠標(biāo)開(kāi)始按下的位置
private Vector2 endMousePos; //鼠標(biāo)結(jié)束按下的位置
private bool isDrag; //是否在拖拽
[Header("是否可以滑動(dòng)多頁(yè)")]
public bool sliderMultPage;
[Header("視為滑動(dòng)一頁(yè)的距離")]
[Space(25)]
public float sliderOnePageDis;
[Header("視為滑動(dòng)多頁(yè)的距離")]
public float sliderMultPageDis;
[Header("緩動(dòng)到目標(biāo)頁(yè)的持續(xù)時(shí)間")]
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();//計(jì)算每一頁(yè)的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>
/// 計(jì)算每一頁(yè)的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>
/// 拖拽開(kāi)始
/// </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("滑動(dòng)距離為:" + offset);
if (sliderMultPage)
{
//單頁(yè)滑動(dòng)
if (Mathf.Abs(offset.x) >= sliderOnePageDis && Mathf.Abs(offset.x) < sliderMultPageDis)
{
float tempHorizontalNUPos = scrollRect.horizontalNormalizedPosition;
FindNearlyPage(tempHorizontalNUPos);
}
//多頁(yè)滑動(dòng)
else if (Mathf.Abs(offset.x) >= sliderMultPageDis)
{
if (offset.x > 0)
{
curPage = 0;
}
else if (offset.x < 0)
{
curPage = totalPage - 1;
}
}
}
else
{
//單頁(yè)滑動(dòng)
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最近的頁(yè)
/// </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
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#基于正則表達(dá)式抓取a標(biāo)簽鏈接和innerhtml的方法
這篇文章主要介紹了C#基于正則表達(dá)式抓取a標(biāo)簽鏈接和innerhtml的方法,結(jié)合實(shí)例形式分析了C#使用正則表達(dá)式進(jìn)行頁(yè)面元素的匹配與抓取相關(guān)操作技巧,需要的朋友可以參考下2017-06-06
C# .net core HttpClientFactory用法及說(shuō)明
這篇文章主要介紹了C# .net core HttpClientFactory用法及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
本文主要介紹了C#中利用GDI來(lái)繪制圖形和文字的方法,并提供的簡(jiǎn)單的示例供大家參考學(xué)習(xí),希望能夠?qū)Υ蠹矣兴鶐椭?/div> 2016-03-03
詳解C#讀取Appconfig中自定義的節(jié)點(diǎn)
我們往往需要在App.config中自定義一些節(jié)來(lái)滿(mǎn)足實(shí)際需要,而不依賴(lài)于App.config的appSettings,下面通過(guò)一個(gè)簡(jiǎn)單的實(shí)例來(lái)說(shuō)明自定義配置節(jié)點(diǎn)的設(shè)置與讀取2015-06-06
C# List實(shí)現(xiàn)行轉(zhuǎn)列的通用方案
本篇通過(guò)行轉(zhuǎn)列引出了System.Linq.Dynamic,并且介紹了過(guò)濾功能,具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-03-03
Unity3D使用UGUI開(kāi)發(fā)原生虛擬搖桿
這篇文章主要為大家詳細(xì)介紹了Unity3D使用UGUI開(kāi)發(fā)原生虛擬搖桿,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04最新評(píng)論

