如何用UGUI實現滑頁效果
效果圖如下:
核心原理
在滑動結束的時刻,重新計算ScrollRect的normalizePosition,使得目標頁顯示在窗口正中。
數學推理
- 假定ScrollRect的NormalizePosition爲n,子控件數目爲c
- 當c=2時,要麼顯示第一頁,要麼顯示第二頁,n的取值爲0(n<=0.5)或1(n>0.5)
- 當c=3時,第一頁n=0,第二頁n=0.5,第三頁n=1,滑動中的n假設在(0, 0.5]區間,如果少於區間中位數,則置爲區間mix,否則置爲maz
- 可以看出,子控件數目c決定了區間的數目,只要把當前的滑動值n劃分到某一個區間,在判斷它靠近區間左邊或是右邊,就能計算出最後的目標值。
核心代碼片段
private float CalDragNormalizeValue() {
float normalizeValue = scrollRect.normalizedPosition.x;
int low =0, high=0;
float d = 1.0f;
CalRange(ref low, ref high, ref d);
normalizeValue = Near(normalizeValue, low * d, high * d);
normalizeValue = Mathf.Clamp(normalizeValue, 0f, 1f);
return normalizeValue;
}
private float CalClickNormalizeValue(int index) {
float normalizeValue = 0f;
if (content.childCount > 1) {
normalizeValue = 1.0f * index / (content.childCount - 1);
}
scrollRect.normalizedPosition = new Vector2(normalizeValue, normalizeValue);
return normalizeValue;
}
private void CalRange(ref int low, ref int high, ref float d) {
if (content.childCount <= 1) {
low = 0;
high = 0;
d = 1f;
return;
}
float normalizeValue = scrollRect.normalizedPosition.x;
d = 1.0f / (content.childCount - 1);
low =(int) Mathf.Floor(normalizeValue / d);
high = low + 1;
}
private float Near(float value, float a, float b) {
float mid = (a+b)/2;
return value <= mid ? a : b;
}
Github工程地址
SlidePage