在android的开发中,经常会遇到需要主动去设定某条ListItem的位置的需求。设置位置的函数有

ListView.setSelection(int position)

ListView.setSelectionFromTop(int position, int y);

其中

position指的是指定的item的在ListView中的索引,注意如果有Header存在的情况下,索引是从Header就开始算的。

y指的是到ListView可见范围内最上边边缘的距离。

函数有了,现在就是根据自身需求来进行设置。

这次遇到的需求,ListView要求是从下往上展示的,并且当Cursor更新时,要保持住原先的最上方的item(不包括header)的位置不变,然后新的历史数据在原先那条item上方继续向上展示。如图:

ListView从下往上展示,也就是

[java] view plaincopy
  1. android:stackFromBottom="true"

但是发现这一属性的设置不会影响索引的排序顺序,也就是item的索引都是从上往下递增的,不会变成从下往上递增。索引为0的item,都是在ListView的最上方的item(或header).

那么当Cursor更新时,原先第一条的索引便会发生变化。要想保持住它(图中的 R)的位置。步骤如下:

(1)获取这一条在新Cursor中的位置(posiition)

(2)获取这一条在更换Cursor后ListView中的位置。

(4)由于ListView的可滚动的属性,我们需要记录更换Cursor前可视的第一条item的索引(ListView.getFirstVisiblePosition())

(3)区分FirstVisiblePosition是0和大于0的情况。由于header,也就是图中的Loading那一条在新数据出来后是会消失的。

(4)当FirstVisiblePosition为0时实际指向的是header,我们要保持位置不变的是header下面第一条(R)的位置。那么此时要设置FirstVisiblePosition为1

(5)当FirstVisiblePosition大于0时实际指向的就是item,但是我们需要设置FirstVisiblePosition为0。*

(6)我们根据FirstVisiblePosition用ListView.getChildAt(int position)函数获取对应的item的View,再根据View.getTop()函数获取到ListView顶部的距离Y。

这样ListView.setSelectionFromTop(int position, int y)所需的两个参数 position 和 y就都有了。

*注解:ListView.getChildAt(int position), 这个position指的是在可视的item中的索引,跟cursor里的位置是大不一样的。可以看看ListView.getChildCount()函数得到个数是小于或等于Cursor里的个数的(不考虑header的话)。虽然一共可能有20条数据,但是界面只能看到8条,那么这个ChildCount大约就是8了。另一方面, FirstVisiblePosition取出的是在总的条数中的索引,再将会消失的header考虑进来,所以就是 FirstVisiblePosition为0时要设为1,大于0时又要设为0。

下面上代码:

调用的代码:

[java] view plaincopy
  1. int headerCount = mListContainer.getListView().getHeaderViewsCount();
  2. int firstVisiblePos = mListContainer.getListView().getFirstVisiblePosition();
  3. int newCursorPosition = getPositionInNewCursor(cursor.getCount(), firstVisiblePos);
  4. int offsetY = getOffsetY(cursor, firstVisiblePos, newCursorPosition);
  5. mAdapter.changeCursor(cursor);
  6. mUpRefreshLayout.setVisibility(View.GONE);
  7. mListContainer.getListView().setSelectionFromTop(newCursorPosition + headerCount, offsetY);

getPositionInNewCursor函数:

[java] view plaincopy
  1. private int getPositionInNewCursor(int newCursorCount, int firstVisiblePos){
  2. if(firstVisiblePos == 0){
  3. firstVisiblePos += 1;
  4. }
  5. int headerCount = mListContainer.getListView().getHeaderViewsCount();
  6. int newCursorPos = newCursorCount - mAdapter.getCount() + firstVisiblePos - headerCount;
  7. return newCursorPos;
  8. }

getOffsetY函数:

[java] view plaincopy
  1. private int getOffsetY(Cursor cursor, int firstVisiblePos, int newCursorPosition){
  2. int y;
  3. View firstVisibleItem = null;
  4. if(firstVisiblePos == 0){
  5. firstVisibleItem = mListContainer.getListView().getChildAt(1);
  6. }else{
  7. firstVisibleItem = mListContainer.getListView().getChildAt(0);
  8. }
  9. y = firstVisibleItem.getTop();
  10. View timeView = firstVisibleItem.findViewById(R.id.time_text_view);
  11. if(timeView != null && timeView.getVisibility() == View.VISIBLE){
  12. Cursor curItem = (Cursor)mAdapter.getItem(newCursorPosition);
  13. Cursor preItem = (Cursor)mAdapter.getItem(newCursorPosition - 1);
  14. if(curItem != null || preItem != null){
  15. long curTimeStamp = curItem.getLong(MessagesProjection.JEDI_CREATE_DATE_INDX);
  16. long preTimeStamp = preItem.getLong(MessagesProjection.JEDI_CREATE_DATE_INDX);
  17. if(Math.abs(curTimeStamp - preTimeStamp) <= SHOW_TIME_STAMP_TEN_MINS){
  18. LayoutParams param = (LinearLayout.LayoutParams)mTimeView.getLayoutParams();
  19. y += mTimeView.getHeight() + param.topMargin + param.bottomMargin;
  20. }
  21. }
  22. }
  23. return y;
  24. }

getOffsetY中有一段计算图中TimeStamp的高度的代码,不关心的可以自己跳过一下。因为查询出历史数据后可能会造成原先有TimeStamp的那一条在刷新后不再显示TimeStamp(与上一条合并到一个时间段了),所以要把它的高度也计算进去。

  • 上一篇android中View.measure方法详解
  • 下一篇Java语法 if((Boolean)null)会报空指针异常 java.lang.NullPointerException
3

Android入门 在ListView中如何进行精确的定位相关推荐

  1. android如何获取listview中的任意行数据

    android如何获取listview中的任意行数据 @Override public void onItemClick(AdapterView<?> arg0, View arg1, i ...

  2. android 部分区域点击,Android编程实现ListView中item部分区域添加点击事件功能

    本文实例讲述了Android编程实现ListView中item部分区域添加点击事件功能.分享给大家供大家参考,具体如下: 需求如题目:Android listview中item部分区域添加点击事件,在 ...

  3. Android单选中listview中的一项

    public class LipsListAdapter extends BaseAdapter {private Context context;private List<Lips> l ...

  4. Android中所有UI组件基类是,【详细】Android入门到放弃篇-YES OR NO-》各种UI组件,布局管理器,单元Activity...

    问:达叔,你放弃了吗? 答:不,放弃是不可能的,丢了Android,你会心疼吗?如果别人把你丢掉,你是痛苦呢?还是痛苦呢?~ 引导语 有人说,爱上一个人是痛苦的,有人说,喜欢一个人是幸福的. 人与人之 ...

  5. [转载]Android: 如何实现ScrollView中含有ListView?

    原文地址:Android: 如何实现ScrollView中含有ListView?作者:mailofzxf ListView本身就含有ScrollView,因此把ListView放到ScrollView ...

  6. Android将联系人读取到LISTVIEW中遇到的问题!

    最近在学习Android开发,学习到ListView控件使用的时候参考了<Android应用开发揭秘>中的代码,由于该书是基于Android  2.0进行编写的,其中的部分代码到了更新的A ...

  7. Android旋转切换条目,Android:当我添加动态新的ListView条目时,ListView中的旋转器会丢失它们的值...

    我的活动包含一个按钮和一个ListView. ListView包含Spinner和EditText视图.每次我想在Activity的ListView中插入一个新的行条目时,我都会使用该按钮. 我遵循了 ...

  8. Android在ListView中嵌套一个GridView时只显示一行的原因及解决方法

    在之前的编程里,我还没有遇到过要在一个ListView中嵌套一个GridView或是在一个GridView中嵌套一个ListView.所以今天事儿来了!我花了一将近3个小时,找到了为什么我在一个Lis ...

  9. android listview中item通过viewpager实现

    android listview中item通过viewpager实现 android listview中item通过viewpager实现,每一个item都支持viewpager实现图片切换功能.本项 ...

最新文章

  1. BZOJ 1597: [Usaco2008 Mar]土地购买( dp + 斜率优化 )
  2. 在IIS上部署基于django WEB框架的python网站应用
  3. 用两张图告诉你,为什么你的App会卡顿?
  4. opencv 图像上画出目标运动的轨迹_基于opencv的单目和双目标定平台手眼标定
  5. boost::stl_interfaces模块实现最小的随机访问迭代器的测试程序
  6. 浅谈ASP中Web页面间的数据传递
  7. JLBH示例2 –协调遗漏的会计处理
  8. Linux系统编程5:入门篇之在Linux下观察C/C++程序编译过程 gcc/g++使用详解
  9. android 启动白屏_从细节入手改善用户体验,Flutter跨平台App开发中设置Android和iOS的启动页
  10. 一文读懂数据平台、大数据平台、数据中台
  11. PAT 乙级 1016. 部分A+B (15) Java版
  12. openwrt信号弱掉线_QCA9880 openwrt 信号非常差
  13. 「职称」2022年度中高级职称线下申报材料组卷要求(下)
  14. 怎么写加密邮件,企业邮箱支持吗?【企业邮箱注册】
  15. [人工智能-深度学习-14]:神经网络基础 - 常见loss损失函数之逻辑分类,对数函数,交叉熵函数
  16. 天仙般的王祖贤和林青霞,她们都是用AI修复的
  17. 《超大流量分布式系统架构解决方案-人人都是架构师2.0》读书笔记
  18. python 爬取携程旅游景点评论
  19. 长方形与圆最近连线LISP_“认识长方形,正方形和圆”教学实录与评析
  20. dev c++ 中的Program received signal SIGSEGV Segmentation fault

热门文章

  1. 如何用纯 CSS 创作一只卡通鹦鹉
  2. 为什么列存储能够大幅度提高数据的查询性能?
  3. 18Python标准库系列之logging模块
  4. 我的失败与伟大 —— 产品原型的打造
  5. javascript实现java的StringBuffer功能
  6. 以后装个云集群和云节点啥的太简单了(ubuntu)
  7. Q108:浅析PBRT-V3的代码结构
  8. 大数据可视化需要遵循哪几个核心原则
  9. 物联网卡11位和13位号码的区别在于哪
  10. Web应用测试(一)Selenium介绍及环境搭建