当我们的游戏中需要长列表而且需要滑动时,如果Item的数量过多,我们需要用到无限滚动列表,在NGUI中是使用UIWrapContent解决这个问题的。
使用方式大概如下:
具体可参考 :NGUI-UIWrapContent解析 - 知乎
我这里主要说的是,实现了无限滑动列表后,再加上滚动条会有一个问题,随着我们逐渐向下滚动滚动条会逐渐变小。原因是实现了无限滚动后,在初始化时只计算了初始Item的数量来显示滚动条的大小。下面是自己实现滚动条的显示和滚动。
using UnityEngine;
using System.Collections;
public class MyScrollBar : MonoBehaviour
{
public UIScrollView ScrollView;
public UIWrapContent WrapContent;
public UIPanel ScrollViewPanel;
public UIScrollBar ScrollBar;
public int ItemNum = 0;
public int RowNum = 1;
private Vector3 mStartLocalPos;
private float mScrollLegth;
[SerializeField] bool isSetItemNum = true;
[SerializeField] float strength = 10;
private float currentClipOffset = 0f;
void Start()
{
ScrollView.onMomentumMove += UpdateScrollbar;
mStartLocalPos = ScrollView.transform.localPosition;
SetCount(ItemNum);
ScrollBar.onChange.Add(new EventDelegate(delegate ()
{
//ChangeScrollBarValue(ScrollBar.value);
ScrollView.InvalidateBounds();
}));
if (null != ScrollBar.backgroundWidget)
{
UIEventListener bgl = UIEventListener.Get(ScrollBar.backgroundWidget.gameObject);
if (null != bgl)
{
bgl.onPress += OnScrollBarPressed;
//bgl.onDrag += OnScrollBarDragged;
}
UIEventListener fgl = UIEventListener.Get(ScrollBar.foregroundWidget.gameObject);
if (null != fgl)
{
fgl.onDrag += OnScrollBarDragged;
}
}
}
public void ChangeScrollBarValue(float value)
{
ScrollBar.value = value;
OnScrollBarChange();
}
public void SetCount(int itemNum)
{
mScrollLegth = WrapContent.itemSize * itemNum;
if (ScrollView.movement == UIScrollView.Movement.Vertical)
{
ScrollBar.barSize = ScrollViewPanel.GetViewSize().y / mScrollLegth;
currentClipOffset = ScrollViewPanel.clipOffset.y;
}
else if (ScrollView.movement == UIScrollView.Movement.Horizontal)
{
ScrollBar.barSize = ScrollViewPanel.GetViewSize().x / mScrollLegth;
currentClipOffset = ScrollViewPanel.clipOffset.x;
}
if (ScrollBar.barSize >= 0.99f)
{
ChangeScrollBarValue(0);
ScrollBar.gameObject.SetActive(false);
}
else
{
ScrollBar.gameObject.SetActive(true);
}
if (ItemNum > itemNum)
{
OnScrollBarChange();
}
else if (ItemNum < itemNum)
{
UpdateScrollbar();
}
ItemNum = itemNum;
}
/// <summary>
/// 设置无限滑动条总长数据
/// </summary>
/// <param name="totalCount">总数</param>
/// <param name="strength">滑动速度</param>
/// <param name="rowNum">每组几个</param>
public void SetItemNum(int totalCount,float strength = 10, int rowNum = 1)
{
if (isSetItemNum == false) return;
//ItemNum = totalCount;
RowNum = rowNum;
SetStrength(strength);
//this.Init();
SetCount(totalCount);
isSetItemNum = false;
}
public void SetStrength(float value)
{
strength = value;
SpringPanel sp = ScrollViewPanel.GetComponent<SpringPanel>();
if (sp)
{
sp.strength = value;
}
}
/// <summary>
/// 设置 scrollbar value 的值
/// </summary>
/// <param name="index">目标index</param>
public void SetValue(int index)
{
float value = 0;
if (ScrollView.movement == UIScrollView.Movement.Horizontal)
{
value = index* WrapContent.itemSize / (mScrollLegth - ScrollViewPanel.GetViewSize().y);
}
else if (ScrollView.movement == UIScrollView.Movement.Vertical)
{
value = index* WrapContent.itemSize / (mScrollLegth - ScrollViewPanel.GetViewSize().y);
}
ScrollBar.value = value;
}
void Init()
{
ScrollView.onMomentumMove += UpdateScrollbar;
mStartLocalPos = ScrollView.transform.localPosition;
mScrollLegth = WrapContent.itemSize * Mathf.CeilToInt(ItemNum / (float)RowNum);
if (ScrollView.movement == UIScrollView.Movement.Horizontal)
{
ScrollBar.barSize = ScrollViewPanel.GetViewSize().x / mScrollLegth;
}
else if (ScrollView.movement == UIScrollView.Movement.Vertical)
{
ScrollBar.barSize = ScrollViewPanel.GetViewSize().y / mScrollLegth;
}
if (null != ScrollBar.backgroundWidget)
{
UIEventListener bgl = UIEventListener.Get(ScrollBar.backgroundWidget.gameObject);
if (null != bgl)
{
bgl.onPress += OnScrollBarPressed;
}
UIEventListener fgl = UIEventListener.Get(ScrollBar.foregroundWidget.gameObject);
if (null != fgl)
{
fgl.onDrag += OnScrollBarDragged;
}
}
}
void UpdateScrollbar()
{
float pct = 0.0f;
float endPos = 0.0f;
if (ScrollView.movement == UIScrollView.Movement.Horizontal)
{
endPos = (mScrollLegth - ScrollViewPanel.GetViewSize().x) -
Mathf.Abs(mStartLocalPos.x);
pct = Mathf.Clamp((ScrollView.transform.localPosition.x - mStartLocalPos.x) / (mStartLocalPos.x - endPos), 0,
1f);
}
else if (ScrollView.movement == UIScrollView.Movement.Vertical)
{
endPos = (mScrollLegth - ScrollViewPanel.GetViewSize().y) + mStartLocalPos.y;
pct = Mathf.Clamp((ScrollView.transform.localPosition.y - mStartLocalPos.y) / (endPos - mStartLocalPos.y), 0f,
1f);
}
ScrollBar.value = Mathf.Lerp(ScrollBar.value, pct, 1f);
}
void OnScrollBarPressed(GameObject go, bool isPressed)
{
if (!isPressed)
{
OnScrollBarChange();
}
}
void OnScrollBarDragged(GameObject go, Vector2 delta)
{
OnScrollBarChange();
}
void OnScrollBarChange()
{
Vector3 newLocalPos = ScrollView.transform.localPosition;
if (ScrollView.movement == UIScrollView.Movement.Vertical)
{
newLocalPos.y = ScrollBar.value *
(mScrollLegth - ScrollViewPanel.GetViewSize().y) +
mStartLocalPos.y;
}
else if (ScrollView.movement == UIScrollView.Movement.Horizontal)
{
newLocalPos.x = -ScrollBar.value *
(mScrollLegth - ScrollViewPanel.GetViewSize().x) +
mStartLocalPos.x;
}
SpringPanel.Begin(ScrollView.panel.cachedGameObject, newLocalPos, strength).onFinished = OnSprinPanelFinished;
}
void OnSprinPanelFinished()
{
ScrollView.RestrictWithinBounds(false);
}
void LateUpdate() {
#if UNITY_ANDROID || UNITY_IPHONE
if (ScrollView.movement == UIScrollView.Movement.Vertical)
{
if (ScrollViewPanel.clipOffset.y != currentClipOffset)
{
UpdateScrollbar();
currentClipOffset = ScrollViewPanel.clipOffset.y;
}
}
else if (ScrollView.movement == UIScrollView.Movement.Horizontal)
{
if (ScrollViewPanel.clipOffset.x != currentClipOffset)
{
UpdateScrollbar();
currentClipOffset = ScrollViewPanel.clipOffset.x;
}
}
#endif
}
}
注意这时候我们的ScrollBar就不要拖到ScrollView中了。