NGUI无限滚动列表实现滑动条

当我们的游戏中需要长列表而且需要滑动时,如果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中了。

 

Super ScrollView for UGUI提供基于UGUI ScrollRect的可轻松定制的ScrollView。它是一组C#脚本,可帮助您创建所需的ScrollView。这是非常强大的和高度优化的性能。 文件 Android演示应用程序 演示: - 聊天消息列表演示 - 水平画廊演示 - 垂直画廊演示 - GridView演示 - PageVew演示 - TreeVew演示 - 与稠粘头演示的TreeView - 旋转日期选择器 - 更改项目高度演示 - 下拉刷新演示 - 拉起来加载更多的演示 - 点击加载更多演示 - 选择并删除演示 - GridView删除项目演示 - 顶部到底部的演示 - 自下而上的演示 - 从左到右的演示 - 右侧演示 - 响应GridView演示 - TreeViewWithChildrenIndent演示 特征: - ListView和GridView和TreeView - 无限的项目 - 项目在不同的大小(高度/宽度) - 具有不同预制的物品 - 在初始时间大小未知的项目 - 垂直滚动视图(从上到下,从下到上) - 水平滚动视图(从左到右,从右到左) - 项目填充 - 滚动到指定的项目 - 滚动到具有偏移量的项目 - 项目计数在运行时更改 - 项目大小(高度/宽度)在运行时更改 - 物品捕捉到视口中的任何位置 - 项目循环,如微调 - 添加/删除项目 - 全部删除/删除所有项目 - 刷新并重新加载项目 - 使用池缓存项目,不要在运行时销毁项目 - 有效回收物品 - 平台无关 - UGUI支持 - 支持Unity平台(IOS / Android / Mac / PC / Console / Winphone / WebGL ...)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值