如果一个ListView太长,有时我们希望ListView在从其他界面返回的时候能够恢复上次查看的位置,这就涉及到ListView的定位问题:
解决的办法如下:
1
2
3
4
5
6
7
|
// 保存当前第一个可见的item的索引和偏移量
int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0);
int top = (v ==
null
) ? 0 : v.getTop();
// ...
//根据上次保存的index和偏移量恢复上次的位置
mList.setSelectionFromTop(index, top);
|
这里使用了setSelectionFromTop来定位ListView。其实还可以使用setSelection也可以定位,只是setSelectionFromTop要比setSelection更精准。因为通过getFirstVisiblePosition
得到的第一个item可能已经有一部分是不可见的了,如果用setSelection无法反映出这不可见的部分。
为了说明setSelectionFromTop的参数值的意义,以及与setSelection的区别,下面从源码上来分析:
看一下setSelectionFromTop()的具体实现,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
/**
* Sets the selected <span id="4_nwp" style="width: auto; height: auto; float: none;"><a id="4_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?rs=1&u=http%3A%2F%2Fwww%2Ejcodecraeer%2Ecom%2Fa%2Fanzhuokaifa%2Fandroidkaifa%2F2014%2F0924%2F1709%2Ehtml&p=baidu&c=news&n=10&t=tpclicked3_hc&q=01072140_cpr&k=item&k0=%B6%A8%CE%BB&kdi0=8&k1=%D4%B4%C2%EB&kdi1=8&k2=touch&kdi2=8&k3=%D5%FB%D0%CD&kdi3=8&k4=top&kdi4=8&k5=item&kdi5=8&sid=d58c89a715216433&ch=0&tu=u1921070&jk=40713c5299f4b88d&cf=29&rb=0&fv=11&stid=9&urlid=0&luki=6&seller_id=1&di=128" target="_blank" mpid="4" style="text-decoration: none;"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">item</span></a></span> and positions the selection y pixels from the <span id="5_nwp" style="width: auto; height: auto; float: none;"><a id="5_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?rs=1&u=http%3A%2F%2Fwww%2Ejcodecraeer%2Ecom%2Fa%2Fanzhuokaifa%2Fandroidkaifa%2F2014%2F0924%2F1709%2Ehtml&p=baidu&c=news&n=10&t=tpclicked3_hc&q=01072140_cpr&k=top&k0=%B6%A8%CE%BB&kdi0=8&k1=%D4%B4%C2%EB&kdi1=8&k2=touch&kdi2=8&k3=%D5%FB%D0%CD&kdi3=8&k4=top&kdi4=8&k5=item&kdi5=8&sid=d58c89a715216433&ch=0&tu=u1921070&jk=40713c5299f4b88d&cf=29&rb=0&fv=11&stid=9&urlid=0&luki=5&seller_id=1&di=128" target="_blank" mpid="5" style="text-decoration: none;"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">top</span></a></span> edge
* of the ListView. (If in <span id="6_nwp" style="width: auto; height: auto; float: none;"><a id="6_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?rs=1&u=http%3A%2F%2Fwww%2Ejcodecraeer%2Ecom%2Fa%2Fanzhuokaifa%2Fandroidkaifa%2F2014%2F0924%2F1709%2Ehtml&p=baidu&c=news&n=10&t=tpclicked3_hc&q=01072140_cpr&k=touch&k0=%B6%A8%CE%BB&kdi0=8&k1=%D4%B4%C2%EB&kdi1=8&k2=touch&kdi2=8&k3=%D5%FB%D0%CD&kdi3=8&k4=top&kdi4=8&k5=item&kdi5=8&sid=d58c89a715216433&ch=0&tu=u1921070&jk=40713c5299f4b88d&cf=29&rb=0&fv=11&stid=9&urlid=0&luki=3&seller_id=1&di=128" target="_blank" mpid="6" style="text-decoration: none;"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">touch</span></a></span> 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.<span id=
"7_nwp"
style=
"width: auto; height: auto; float: none;"
><a id=
"7_nwl"
href=
"http://cpro.baidu.com/cpro/ui/uijs.php?rs=1&u=http%3A%2F%2Fwww%2Ejcodecraeer%2Ecom%2Fa%2Fanzhuokaifa%2Fandroidkaifa%2F2014%2F0924%2F1709%2Ehtml&p=baidu&c=news&n=10&t=tpclicked3_hc&q=01072140_cpr&k=top&k0=%B6%A8%CE%BB&kdi0=8&k1=%D4%B4%C2%EB&kdi1=8&k2=touch&kdi2=8&k3=%D5%FB%D0%CD&kdi3=8&k4=top&kdi4=8&k5=item&kdi5=8&sid=d58c89a715216433&ch=0&tu=u1921070&jk=40713c5299f4b88d&cf=29&rb=0&fv=11&stid=9&urlid=0&luki=5&seller_id=1&di=128"
target=
"_blank"
mpid=
"7"
style=
"text-decoration: none;"
><span style=
"color:#0000ff;font-size:14px;width:auto;height:auto;float:none;"
>top</span></a></span> + y;
if
(mNeedSync) {
mSyncPosition = position;
mSyncRowId = mAdapter.getItemId(position);
}
requestLayout();
}
}
|
从上面的代码可以得知,setSelectionFromTop()的作用是设置ListView选中的位置,同时在Y轴设置一个偏移量。
而setSelection()方法,传入一个index整型数值,就可以让ListView定位到指定Item的位置。
这两个方法有什么区别呢?看一下setSelection()的具体实现,代码如下:
1
2
3
4
5
6
7
8
9
10
11
|
/**
* Sets the currently selected <span id="0_nwp" style="width: auto; height: auto; float: none;"><a id="0_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?rs=1&u=http%3A%2F%2Fwww%2Ejcodecraeer%2Ecom%2Fa%2Fanzhuokaifa%2Fandroidkaifa%2F2014%2F0924%2F1709%2Ehtml&p=baidu&c=news&n=10&t=tpclicked3_hc&q=01072140_cpr&k=item&k0=%B6%A8%CE%BB&kdi0=8&k1=%D4%B4%C2%EB&kdi1=8&k2=touch&kdi2=8&k3=%D5%FB%D0%CD&kdi3=8&k4=top&kdi4=8&k5=item&kdi5=8&sid=d58c89a715216433&ch=0&tu=u1921070&jk=40713c5299f4b88d&cf=29&rb=0&fv=11&stid=9&urlid=0&luki=6&seller_id=1&di=128" target="_blank" mpid="0" style="text-decoration: none;"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">item</span></a></span>. If in <span id="1_nwp" style="width: auto; height: auto; float: none;"><a id="1_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?rs=1&u=http%3A%2F%2Fwww%2Ejcodecraeer%2Ecom%2Fa%2Fanzhuokaifa%2Fandroidkaifa%2F2014%2F0924%2F1709%2Ehtml&p=baidu&c=news&n=10&t=tpclicked3_hc&q=01072140_cpr&k=touch&k0=%B6%A8%CE%BB&kdi0=8&k1=%D4%B4%C2%EB&kdi1=8&k2=touch&kdi2=8&k3=%D5%FB%D0%CD&kdi3=8&k4=top&kdi4=8&k5=item&kdi5=8&sid=d58c89a715216433&ch=0&tu=u1921070&jk=40713c5299f4b88d&cf=29&rb=0&fv=11&stid=9&urlid=0&luki=3&seller_id=1&di=128" target="_blank" mpid="1" style="text-decoration: none;"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">touch</span></a></span> 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()有了更深刻的认识了。