android ListView定位

如果一个ListView太长,有时我们希望ListView在从其他界面返回的时候能够恢复上次查看的位置,这就涉及到ListView的定位问题:

smoothScrollToPosition需要2.2以上,smoothScrollByOffset需要3.0以上。smoothScrollToPosition可以实现平滑滚动

解决的办法如下:

// 保存当前第一个可见的item的索引和偏移量

int index = mList.getFirstVisiblePosition();

View v = mList.getChildAt(0);

int top = (v == null) ? 0 : v.getTop();

// ...

注解:ListView.getChildAt(int position), 这个position指的是在可视的item中的索引,跟cursor里的位置是大不一样的。

可以看看ListView.getChildCount()函数得到个数是小于或等于Cursor里的个数的(不考虑header的话)。

虽然一共可能有20条数据,但是界面只能看到8条,那么这个ChildCount大约就是8了。

另一方面, FirstVisiblePosition取出的是在总的条数中的索引,再将会消失的header考虑进来,所以就是 FirstVisiblePosition为0时要设为1,大于0时又要设为0。

//根据上次保存的index和偏移量恢复上次的位置

mList.setSelectionFromTop(index, top);

为了说明setSelectionFromTop的参数值的意义,以及与setSelection的区别,下面从源码上来分析:

看一下setSelectionFromTop()的具体实现,代码如下:

/**

* Sets the selected item and positions the selection y pixels from the top edge

* of the ListView. (If in touch mode, the item will not be selected but it will

* still be positioned appropriately.)

*

* @param position Index (starting at 0) of the data item to be selected.

* @param y The distance from the top edge of the ListView (plus padding) that the

*        item will be positioned.

*/

public void setSelectionFromTop(int position, int y) {

if (mAdapter == null) {

return;

}

if (!isInTouchMode()) {

position = lookForSelectablePosition(position, true);

if (position >= 0) {

setNextSelectedPositionInt(position);

}

} else {

mResurrectToPosition = position;

}

if (position >= 0) {

mLayoutMode = LAYOUT_SPECIFIC;

mSpecificTop = mListPadding.top + y;

if (mNeedSync) {

mSyncPosition = position;

mSyncRowId = mAdapter.getItemId(position);

}

requestLayout();

}

}

从上面的代码可以得知,setSelectionFromTop()的作用是设置ListView选中的位置,同时在Y轴设置一个偏移量。

而setSelection()方法,传入一个index整型数值,就可以让ListView定位到指定Item的位置。

这两个方法有什么区别呢?看一下setSelection()的具体实现,代码如下:

/**

* Sets the currently selected item. If in touch mode, the item will not be selected

* but it will still be positioned appropriately. If the specified selection position

* is less than 0, then the item at position 0 will be selected.

*

* @param position Index (starting at 0) of the data item to be selected.

*/

@Override

public void setSelection(int position) {

setSelectionFromTop(position, 0);

}

原来,setSelection()内部就是调用了setSelectionFromTop(),只不过是Y轴的偏移量是0而已。现在应该对setSelection()和setSelectionFromTop()有了更深刻的认识了。

其实还可以使用setSelection也可以定位,只是setSelectionFromTop要比setSelection更精准。

因为通过getFirstVisiblePosition得到的第一个item可能已经有一部分是不可见的了,如果用setSelection无法反映出这不可见的部分。

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

(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就都有了。

时间: 2024-10-16 06:51:25

android ListView定位的相关文章

android之listView定位到指定行同时隐藏输入键盘

帮别人该bug遇到的一个问题,记录下来. listView.setSelection(a); 这个方法可以让让你的listview定位到指定行 但是如果紧接着执行隐藏输入键盘的代码,则会有bug,这个时候定位无法实现. imm.hideSoftInputFromWindow(PatientAddActivity.this .getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); 使用切换这个方法隐藏输入法键

Android ListView使用BaseAdapter与ListView的优化 (转至 http://www.open-open.com/lib/view/open1339485728006.html)

在ListView的使用中,有时候还需要在里面加入按钮等控件,实现单独的操作.也就是说,这个ListView不再只是展示数据,也不仅仅是这一行要来处理用户的操作,而是里面的控件要获得用户的焦点.读者可以试试用SimpleAdapter添加一个按钮到ListView的条目中,会发现可以添加,但是却无法获得焦点,点击操作被ListView的Item所覆盖.这时候最方便的方法就是使用灵活的适配器BaseAdapter了. ▲图4-35 BaseAdapter中的方法 使用BaseAdapter必须写一

Android ListView使用BaseAdapter与ListView的优化

在ListView的使用中,有时候还需要在里面加入按钮等控件,实现单独的操作.也就是说,这个ListView不再只是展示数据,也不仅仅是这一行要来处理用户的操作,而是里面的控件要获得用户的焦点.读者可以试试用SimpleAdapter添加一个按钮到ListView的条目中,会发现可以添加,但是却无法获得焦点,点击操作被ListView的Item所覆盖.这时候最方便的方法就是使用灵活的适配器BaseAdapter了. ▲图4-35 BaseAdapter中的方法 使用BaseAdapter必须写一

Android ListView分页加载(服务端+android端)Demo

Android ListView分页加载功能 在实际开发中经常用到,是每个开发者必须掌握的内容,本Demo给出了服务端+Android端的两者的代码,并成功通过了测试. 服务端使用MyEclipse,Android端使用Eclipse. 实现效果图: 服务端一共100条数据,共分四页,每页有25条数据. 源代码: 服务端: 需要导入图中这几个jar包. 在运行Android端代码前,需要开启服务端: 下面先给出服务端的代码: 类EmpDataSource: package com.android

Android ListView分页载入(服务端+android端)Demo

Android ListView分页载入功能 在实际开发中经经常使用到,是每一个开发人员必须掌握的内容,本Demo给出了服务端+Android端的两者的代码,并成功通过了測试. 服务端使用MyEclipse,Android端使用Eclipse. 实现效果图: 服务端一共100条数据,共分四页,每页有25条数据. 源码: 服务端: 须要导入图中这几个jar包. 在执行Android端代码前,须要开启服务端: 以下先给出服务端的代码: 类EmpDataSource: package com.andr

Android: ListView与Button的共存问题解决

ListView 和 其它能触发点击事件的widget无法一起正常工作的原因是加入其它widget后,ListView的itemclick事件将无法触发,被其它widget的click事件屏蔽. 首先,说明一下,ListView中每一行包括以下三项: 一个ImageView, 一个TextView,一个ImageButton,依次排开. 以下是layout的内容,分为两部分: res/layout/main.xml <?xml version="1.0" encoding=&qu

Android listview与adapter用法

listview与adapter用法 博客分类: android 一个ListView通常有两个职责. (1)将数据填充到布局. (2)处理用户的选择点击等操作. 第一点很好理解,ListView就是实现这个功能的.第二点也不难做到,在后面的学习中读者会发现,这非常简单. 一个ListView的创建需要3个元素. (1)ListView中的每一列的View. (2)填入View的数据或者图片等. (3)连接数据与ListView的适配器. 也就是说,要使用ListView,首先要了解什么是适配器

Android ListView OnItemLongClick和OnItemClick事件内部细节分享以及几个比较特别的属性

本文转自 http://blog.sina.com.cn/s/blog_783ede030101bnm4.html 作者kiven 辞职3,4个月在家休息,本以为楼主要程序员逆袭,结果失败告终继续码农生涯今天开始更新博客. 正文. 项目中有个ListView内容比较复杂现在要添加长按删除功能.楼主自然想到利用ListView的onItemLongClick事件来处理.结果可想而知在实际体验中很不好,会出现失灵有些选项能触发onItemLongClick事件有些却没反应.楼主去网上看了都是focu

Android——ListView布局+适配器(三)

Android--ListView布局+适配器(三) package com.example.administrator.newstop; import android.os.Bundle; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import andro