Flutter ListView优雅的获取第一个可见Item的Position_flutter listview定位第一个item-程序员宅基地

技术标签: ListVie  Position  Flutter  可见Item  

      Flutter给我们提供了丰富的控件和控制方法,但是也有不少问题,就这两天,我就遇到去获取ListView第一个可见Item的Position的问题,Flutter并没有提供方法,只能我们想办法,我记得有大佬说过ListView和Android的RecyleView一样,那ListView的ItemBuilder肯定是用多少创建多少,用哪个创建哪个,抱着试试的态度,我在ItemBuilder打印了一下,果然,他只创建当前要用的Item,下来我们看看我的思路

     我们首先考虑初始化了多少个Item,这个信息对我们又什么用呢?? 这个数据我们缓存成Items的位置数组“positions”,(例如初始化Item数量为 5  ,表示初始化了0-5  Position 的 Item),初始化完成后,ListView滑动时,builder会根据需要创建新的Item,回收不用的Item。 builder每添加一个Item(前面说过,用一个添加一个,已经初始化好的Item,builder不在创建,即不再执行创建方法),我们就在初始化时缓存的位置变量“positions”的基础上改动,那Position 数组就可以自行调整头和尾了。

       这样,我们就知道大概第一个可见Item就在数组变量“positions”的前几个,为什么说是前几个,而不是第一个,因为我们缓存的Position 包括 屏幕可见+缓存的,所以第一个并不一定时可见的。

       好了,讲了那么多,那怎么去知道初始化了多少个Item??? 在初始化时 ,我们不确定到底会 初始创建 多少Item,数组变量也不好创建, 所以我们用一个整形变量“memoryPosition”去记录 初始化创建 多少Item,好了,我们现在知道Item数量了(包括 屏幕可见+缓存的)。      初始化Item的数量我们知道了。接下来 我们找个合适的时机将Item数量 Position 缓存成List数组—>“positions”,我是在NotificationListener的ScroStartNotification里面缓存Position的。    positions数组可以自行调整头和尾 那不就更简单了  ,看代码 ↓↓↓↓

 

     注意:大家尽量把cacheEctent的值调小,缓存越小,后面获取position越快

List<int> positions;
int memoryPosition;

child: new ListView.builder(
    cacheExtent: 30.0,
    itemBuilder: (context, index) {
       //根据positions==null来判断是否已经初始化
       if(positions!=null) {
            //已经初始化过的话 滑动自行调整头和尾
            if (index > positions.last) {
                positions.removeAt(0);
                positions.add(index);
            } else if (index < positions.first) {
                positions.removeLast();
                positions.insert(0, index);
            }
        }else{
            //记录初始化了多少个Item
            memoryPosition=index;
        }
},),

  NotificationListener的ScroStartNotification里面将变量memoryPosition 缓存成数组 positions,看代码

new NotificationListener(
    onNotification: (notification){
        if(notification is ScrollStartNotification){
            if(positions==null) {
                positions=new List();
                for(int i=0 ;i<=memoryPosition;i++){
                    positions.add(i);
                }
            }
        }
    },
    child: new ListView.builder(),

这样我们就知道头和尾了,并实时更新,可是头不一定是第一个可见Item,有可能是缓存的item,那我们怎么办呢,

我当时在想 我在调用时 如果我让 ListView在屏幕的位置 和  Item在屏幕中的位置+Item的高度  做比较  如果Item可见 ,那么Item在屏幕中的位置+Item的高度肯定大于ListView在屏幕的位置 (大家别忘了给ListView和它的Item们设置Key哟),好了,我们看代码

int firstChildPosition=positions.first;
int lastChildPosition=positions.last;

double chileGlobalPositionY;
double chileHeight;

//获取ListView在屏幕中的位置
double listViewGlobalPositionY=listViewKey.currentContext.findRenderObject().getTransformTo(null).getTranslation().y;
for(int i=firstChildPosition;i<=lastChildPosition;i++){
    if(adsorptionDatas[i].adsorptionKey.currentContext==null){
        continue;
    }
     //子控件在屏幕中的位置 用于计算第一个可见Item的位置
    chileGlobalPositionY=adsorptionDatas[i].adsorptionKey.currentContext.findRenderObject().getTransformTo(null).getTranslation().y;
    //控件高度 用于计算第一个可见Item的位置
    chileHeight=adsorptionDatas[i].adsorptionKey.currentContext.findRenderObject().paintBounds.size.height;
    //如果在屏幕中可见
    if(chileGlobalPositionY+chileHeight>listViewGlobalPositionY){
        //TODO i就是第一个可见Item的位置
        break;
    }
}

这样,我们的第一个可见Item的位置就获取到了

详细代码可参考https://github.com/baoolong/PullToRefresh 吸顶布局模块的代码

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/baoolong/article/details/82744871

智能推荐

Redis 缓存穿透 击穿 雪崩_同类型的key固定时间+随机值间,-程序员宅基地

文章浏览阅读96次。Redis 缓存穿透 击穿 雪崩_同类型的key固定时间+随机值间,

【算法习题】数组中未出现的最小正整数-程序员宅基地

文章浏览阅读1.2k次。题目:给定一个无序整型数组arr,找到数组中未出现的最小正整数。要求时间复杂度为O(N)空间复杂度为O(1)。例如:arr=[-1,2,3,4]。返回1。arr=[1,2,3,4]。返回5。=========================================================分析:这道题要理解最小正整数的意思,最小的正整数就是1,所以考..._最小未出现的正整数

分治算法③-使用分治算法实现二分查找-python_python实现分治法二分搜索从控制台输入-程序员宅基地

文章浏览阅读1k次,点赞3次,收藏6次。如果 target >array[mid] ,令 left=middle+1,继续在数组的后半部分进行搜索;如果 target 判定 left_python实现分治法二分搜索从控制台输入

信息系统项目管理师必背核心考点(二十七)关键路径法(CPM)_关键路径的考点-程序员宅基地

文章浏览阅读1k次。科科过为您带来软考信息系统项目管理师核心重点考点(二十七)关键路径法(CPM),内含思维导图+真题_关键路径的考点

【氧化镓】Ga2O3 MOSFET器件的单SEB机制TCAD研究-程序员宅基地

文章浏览阅读636次,点赞8次,收藏9次。本文是一篇关于氧化镓(Ga2O3)金属氧化物半导体场效应晶体管(MOSFET)在单粒子烧毁(single event burnout, SEB)事件中的机制研究的文章。文章通过使用技术计算机辅助设计(TCAD)模拟来探究侧向耗尽型氧化镓MOSFET设备在SEB中的敏感区域和安全操作电压,并提出了辐射损伤机制。

分享一个关于生鲜电商的竞品分析报告-程序员宅基地

文章浏览阅读1.8k次,点赞3次,收藏17次。1.行业分析近年来,生鲜电商在资本的加持下迅速发展。2019年随着资本态度趋于保守,加之多数生鲜电商尚未实现规模化盈利,多家生鲜电商平台开始出现危机,生鲜电商行业又迎来新一轮洗牌,与此同时..._电子商务数据分析测试一一家生鲜店铺为进一步占据更多市场份额,需要对其竞争对手

随便推点

Kanzi软件开发与Android的关系_kanzi_on_android_3_9_4_setup-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏6次。随着Android在汽车领域尤其是在车载娱乐系统方向使用的场景越来越多,Kanzi作为Android提高界面效果、提升界面开发效率的优质小伙伴,Android+Kanzi的组合被越来越多的整车厂和供应商采用。那么这对小伙伴是怎样打交道的呢?这一期就来给大家介绍下。一、Kanzi On Android原理我们先来了解下Kanzi On Android应用的基本知识。从Kanzi的kanzi_engine.jar源码中可以看到,KanziActivity继承自Android的Activity,渲染的Ka_kanzi_on_android_3_9_4_setup

【ChatGLM3】(7):在autodl上,使用A50显卡,使用LLaMa-Factory开源项目对ChatGLM3进行训练,非常方便的,也方便可以使用多个数据集_chatglm3 训练-程序员宅基地

文章浏览阅读3.4k次,点赞20次,收藏20次。工具还是非常的简单,可以把机构参数进行设置下。主要就是把参数可视化,同时把结果也可视化。非常的方便。进度也可以看到。_chatglm3 训练

高管内斗或使浆量下滑,海尔集团125亿元战投上海莱士存变数?_上海莱士 海尔-程序员宅基地

文章浏览阅读874次,点赞26次,收藏27次。季某进入血浆事业部后,进行大刀阔斧的改革,降本增效,将有能力的人放到关键岗位上,现在的大化,武宁,兴平、石门、澧县、沂源、白沙等浆站站长都是季某在岗期间挑选的浆站一把手,这些浆站浆量都大幅提升。朱某为了谋求回到浆站,指示浆站内部员工捣乱,对全州新到的站长黄某进行各种骚扰,包括砸车窗,浆站电闸纵火,在车上放纸条威胁,内外勾连故意找体格不达标的浆员进站献浆恶意到卫监所投诉浆站等,半年时间折腾下来,导致全州浆站的浆量从2022年的57.8吨掉到了2023年的50.23吨,降幅达-13%。_上海莱士 海尔

ChatGPT AIGC 办公自动化拆分Excel工作表_ai 拆分excel-程序员宅基地

文章浏览阅读259次。在这样的一份数据源中,我们需要完成将每个人的工资用一个单独的表存放。3.在“移动或复制”对话框中,选择“新工作簿”,然后勾选“将选定工作表复制到新工作簿”选项。chatGPT自动生成的VBA代码就能很轻松的实现工作表拆分,再也不用手动复制与粘贴了。4.点击“确定”,Excel会创建一个新的工作簿,并将您选择的工作表复制到该工作簿中。复制---新建工作表---粘贴,反复这几个步骤进行工作表拆分,即费时又费力。1.打开您的Excel工作簿,选择您要拆分的工作表。5.如果需要拆分多个工作表,请重复上述步骤。_ai 拆分excel

删除一个英文字符串当中所有的字母d C语言学习日志#3_编写程序,删除输入字符串中的字符d-程序员宅基地

文章浏览阅读284次。【代码】删除一个英文字符串当中所有的字母d C语言学习日志#3。_编写程序,删除输入字符串中的字符d

python实现接口上传文件的两种方法_python上传文件-程序员宅基地

文章浏览阅读3.7w次,点赞12次,收藏76次。文件上传:上传图片的类型是file,这里没有用到头部信息import requestsdef sendImg(img_path, img_name, img_type='image/jpeg'): """ :param img_path:图片的路径 :param img_name:图片的名称 :param img_type:图片的类型,这里写的是image/jpeg,也可以是png/..._python上传文件