关于限制scrollView滚动
- 这个限制滚动的需求,其实只能放置在LateUpdate函数里面进行操作
- ScrollView在update里面进行了移动,在lateupdate里面判断位置是否超过限制,并进行卡死
- 但是我为了图方便,在别人写好的接口里面进行开发,结果只要滑动速度过快,就会无法卡住。
计算某个具体元素的位置
- 因为这涉及到计算在ScrollView中某个元素在列表中的位置。
- 其实还是蛮难计算的。
- 这里以垂直滚动为例子。
- 首先我们要算出滚动的距离
滚动的距离 = content的高度-视口的高度
-
value = 计算第i个元素的高度/滚动距离
-
再把scrollRect的VerticalNormalization设置为这个值
-
一个坑
using UnityEngine;
using UnityEngine.UI;
public class ScrollDistanceCalculator : MonoBehaviour
{
public ScrollRect scrollRect;
void Update()
{
// 获取视口的大小
Vector2 viewportSize = new Vector2(scrollRect.viewport.rect.width, scrollRect.viewport.rect.height);
// 获取内容的大小
Vector2 contentSize = new Vector2(scrollRect.content.rect.width, scrollRect.content.rect.height);
// 获取当前的归一化位置
Vector2 normalizedPosition = scrollRect.normalizedPosition;
// 计算像素距离
float horizontalDistance = (contentSize.x - viewportSize.x) * normalizedPosition.x;
float verticalDistance = (contentSize.y - viewportSize.y) * normalizedPosition.y;
// 打印像素距离
Debug.Log("Horizontal Distance: " + horizontalDistance);
Debug.Log("Vertical Distance: " + verticalDistance);
}
}
- 我在设置的时候使用的是
Debug.Log($"ViewPort height_{
GetComponent<ScrollRect>().viewport.rect.height}");
Debug.Log($"ViewPort height_{
GetComponent<ScrollRect>().viewport.sizeDelta.y}");
-
ViewPort的SizeDelta和Rect的height是不一样的。这就涉及到另一个知识点。SizeDelta是什么,Rect又是什么
-
滚动到第i个元素的实现
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
public enum Align
{
Top,
Middle,
Bottom,
}
public Align align;
public int ItemIndex;
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.K))
{
Debug.Log($"content height_{
GetComponent<ScrollRect>().content.rect.height}");
Debug.Log($"content size_Y{
GetComponent<ScrollRect>().content.sizeDelta.y}");
Debug.Log($"content height_{
GetComponent<ScrollRect>().viewport.rect.height}");
Debug.Log($"content height_{
GetComponent<ScrollRect>().viewport.sizeDelta.y}");
}
if (Input.GetKeyDown(KeyCode.R))
{
var btns = GetComponent<ScrollRect>().content.GetComponentsInChildren<UnityEngine.UI.Button>();
int index = 0;
foreach (var item in btns)
{
item.transform.Find("Text").GetComponent<TextMeshProUGUI>().text = $"{
index++}";
}
var sumHeight = GetComponent<ScrollRect>().content.rect.height - GetComponent<ScrollRect>().viewport.rect.height;
float value = 0;
for (int i = 0; i < ItemIndex; i++)
{
value += btns[i].GetComponent<RectTransform>().rect.height;
}
switch (align)
{
case Align.Top:
value = value;
break;
case Align.Middle:
value = value + btns[ItemIndex].GetComponent<RectTransform>().rect.height / 2;
break;
case Align.Bottom:
value = value + btns[ItemIndex].GetComponent<RectTransform>().rect.height;
break;
default:
break;
}
GetComponent<ScrollRect>().verticalNormalizedPosition = 1 - value / sumHeight;
}
}
}