[UGUI]ListLayoutGroup--可重用的滚动列表

为了不生成太多的GameObject,当滚动的时候,需要将出框的item重复利用起来。这个网上已经有了很多例子。我为了项目使用方便,在GridLayoutGroup基础上修改了一下,配合ScrollRect使用

首先在传入数据的时候,需要知道要显示多少数据,为了拖动时看不到突然消失的item,会多显示一个(往前滑动的时候和往后滑动的时候会放在最前面或最后面):

    private float GetScrollRectSize()
    {
        var rectSize = m_scrollRect.GetComponent<RectTransform> ().rect.size;
        return m_Constraint = IsVertical ? rectSize.y : rect.y;
    }
    private float GetCellSize()
    {
        return m_Constraint = IsVertical ? cellSize.y + spacing.y : cellSize.x + spacing.x;
    }
    public void SetData<P, D>(ICollection<D> dataList, System.Action<int, P, D> setContentHandler)
        where P : MonoBehaviour
    {
        ........
        displayListCount = Mathf.CeilToInt(GetScrollRectSize () / GetCellSize()) + 1;
        .......
    }

在滚动的时候,首先需要知道最左上角的数据index:

    public int GetStartIndex()
    {
        if (m_dataList == null || m_dataList.Count == 0)
            return 0;
        float anchorPosition = IsVertical ? rectTransform.anchoredPosition.y : rectTransform.anchoredPosition.x;
        if(!IsVertical)
            anchorPosition *= -1;
        anchorPosition -=  GetCellSize() * 0.5f - GetPadding();
        return (int)(anchorPosition / GetCellSize()) * constraintCount;
    }

为了不产生其他开销,Item的实际顺序不会改动,这就需要在已有的顺序中对其在数据中的实际顺序做映射,举个例子,如果一屏可以显示四个数据,那么对应不同的startIndex,四个item的映射关系如下:

Start Index Actual Index
0 0 1 2 3
1 4 1 2 3
2 4 5 1 2

如下公式可得到Actual Index(对于无限滚动的列表,start index可能小于0):

    private  int GetActualIndex(int startIndex, int index)
    {
        var count = GetChildCount;
        return ((startIndex + (startIndex >= 0 ? (count - index - 1) : -index)) / count * count + index);
    }

滚动时,可根据Actual Index设置Item的位置,并对比滚动前的Actual Index是否改变,决定是否更新数据:

    private void SetCellsAlongAxis (int axis)
    {
        ......
        for(int i = 0; i < m_childCount; ++i)
        {
            var child = m_childList[i];
                        ...
            if (IsVertical) {
                positionX = Mathf.Abs(actualIndex) % cellsPerMainAxis;
                positionY = actualIndex / cellsPerMainAxis;
            } else {
                positionX = actualIndex / cellsPerMainAxis;
                positionY = Mathf.Abs(actualIndex) % cellsPerMainAxis;
            }

            if (cornerX == 1)
                positionX = actualCellCountX - 1 - positionX;
            if (cornerY == 1)
                positionY = actualCellCountY - 1 - positionY;
                        ......            if(actualIndex != previousIndex)
            {
                 SetItemContent(acutalIndex, child, m_dataList[i]);
            }
            SetChildAlongAxis (child, 0, startOffset.x + (cellSize [0] + spacing [0]) * positionX, cellSize [0]);
            SetChildAlongAxis (child, 1, startOffset.y + (cellSize [1] + spacing [1]) * positionY, cellSize [1]);
        }
    }
时间: 2024-08-25 05:21:33

[UGUI]ListLayoutGroup--可重用的滚动列表的相关文章

在滚动列表中实现视频的播放(ListView &amp; RecyclerView)

英文原文:Implementing video playback in a scrolled list (ListView & RecyclerView) 本文将讲解如何在列表中实现视频播放.类似于诸如 Facebook, Instagram 或者 Magisto这些热门应用的效果: Facebook: Magisto: Instagram: 这片文章基于开源项目: VideoPlayerManager. 所有的代码和示例都在那里.本文将跳过许多东西.因此如果你要真正理解它是如何工作的,最好下载

(更新版)Android VideoPlayer 在滚动列表实现item视频播放(ListView控件和RecyclerView)

由于写这篇文章时挂着梯子 ,回来发现没有图片 对不起各位了-.. 现在我改好了! 2016.5.27 15时 阴 at BJ 转载请标明出处:粪乧 http://blog.csdn.net/wooder111/article/details/51513582 原文翻译: 点击跳转 在这篇文章中,我将介绍如何实现列表中的视频播放.在流行的应用,如Facebook,Instagram的或Magisto的工作原理相同: Facebook的: Magisto的: Instagram的: 这篇文章是基于开

Android在滚动列表中实现视频的播放 ListView RecyclerView

英文原文:Implementing video playback in a scrolled list (ListView & RecyclerView) 本文将讲解如何在列表中实现视频播放.类似于诸如 Facebook, Instagram 或者 Magisto这些热门应用的效果: Facebook: Magisto: Instagram: 这片文章基于开源项目: VideoPlayerManager. 所有的代码和示例都在那里.本文将跳过许多东西.因此如果你要真正理解它是如何工作的,最好下载

Cocos2d-x滚动列表具体解释(CCScrollView的使用)

今天要写一个滚动列表功能,类似以下这样.(图片资源都是自己从天天酷跑里面抠的,仅用于学习方便) 首先,这样一个列表就和iOS里面的UITableView没什么两样,当然,Android中肯定也存在类似的控件. 在cocos2d-x引擎中參照ios中的UITableView实现了一个叫做CCTableView的类,用于创建列表,对于熟悉ios程序设计的人来说,这个内容应该是非常好理解的. 以下就介绍下CCTableView. 首先,mark几个比較好的博文. Cocos2d-x CCTableVi

Cocos2d-x滚动列表详解(CCScrollView的使用)

今天要写一个滚动列表功能,类似下面这样.(图片资源都是自己从天天酷跑里面抠的,仅用于学习方便) 首先,这样一个列表就和iOS里面的UITableView没什么两样,当然,Android中肯定也存在类似的控件. 在cocos2d-x引擎中参照ios中的UITableView实现了一个叫做CCTableView的类,用于创建列表,对于熟悉ios程序设计的人来说,这个内容应该是很好理解的. 下面就介绍下CCTableView. 首先,mark几个比较好的博文. Cocos2d-x CCTableVie

列表组件抽象(4)-滚动列表及分页说明

这是我写的关于列表组件的第4篇博客.前面的相关文章有: 1. 列表组件抽象(1)-概述 2. 列表组件抽象(2)-listViewBase说明 3. 列表组件抽象(3)-分页和排序管理说明 本文介绍列表组件中我对滚动列表及滚动分页的实现思路. 在pc端,通过滚动进行翻页的需求非常常见:移动端也是,只不过移动端由于scroll事件触发有延迟,必须等到屏幕停止滑动后才会触发,而不是在用户的手指离开屏幕就立即触发,所以移动端最好是不用scroll事件直接做滚动翻页,而是用iscroll这类插件提供更实

Jquery制作--循环滚动列表

自己模仿JQ插件的写法写了一个循环滚动列表插件,支持自定义上.下.左.右四个方向,支持平滑滚动或者间断滚动两种方式,都是通过参数设置.JQ里面有些重复的地方,暂时没想到更好的方法去精简.不过效果还是可以的,如下(效果图上传后都加速了,实际效果比这个要慢很多): html代码如下: <!doctype html> <html lang="zh-cn"> <head> <meta charset="utf-8"> <

用Vue来实现音乐播放器(十六):滚动列表的实现

滚动列表是一个基础组件  他是基于scroll组件实现的 在base文件夹下面创建一个list-view文件夹 里面有list-view.vue组件   <template> <!-- 当父组件传递给子组件的数据发生变化的时候 scroll可以监听到此时高度会发生变化 --> <!-- 子组件这里的:data和props里面的data相对于 --> <!-- 父传子的时候 data是对应的props里面的值 --> <scroll class=&quo

当滚动列表的时候,让input框失去焦点(移动端会收起键盘)

1.拓展scroll.vue事件 1 beforeScroll:{ 2 type:Boolean, 3 default:false 4 } 5 6 7 if(this.beforeScroll){//滚动列表的时候收起键盘(移动端) 8 this.scroll.on('beforeScrollStart',()=>{ 9 this.$emit('beforeScroll') 10 }) 11 } 2.在suggest.vue里声明beforeScrll:true,并$emit(beforeScr