ListView 中 getSelectedView() 和 getSelectedItem() 区别
2015-11-11 16:44
447 查看
本文是基于作者遇到的一个bug而来,如果正常情况下,可以不考虑本文做法。
从官方的注释上看
首先,看到
可以看到 return 的是
再接着看
返回的是
再看到
由于一般
根据源码可以看出这两个方法得到的数据是有一点区别的,可是我们平时用的时候好像完全感觉不到,直到遇到特定的情况的时候,也就是我遇到的bug。
项目有个需求,是在右边的
为什么要这样做,就是因为
第一焦点
第二焦点
接下来执行操作,当选中项为“媒体”且焦点不在
我的做法是:在
当两个方法使用的都是
看打印发现
而
如前言所述,
可以根据现象证明,两次调用第一次把“媒体”设置为了第一焦点,第二次把“媒体”设置为了第二焦点。这显然不是我想要的结果。根据“应用”选项放大也可以看出现在选中项是“应用”。
如果这样调整:在
效果变成了:
很明显,应该改成
完整效果图示:
1.作为第一焦点时
2.按右,作为第二焦点时
3.按下,第二焦点切换
从官方的注释上看
getSelectedView()好像是得到当前选中的 item 的
view,
getSelectedItem()得到的当前选中的 item 所绑定的数据。这两个得到的数据类型都不相同怎么比较?
首先,看到
getSelectedItem()的源码 实现:
[code] /** * @return The data corresponding to the currently selected item, or * null if there is nothing selected. */ public Object getSelectedItem() { T adapter = getAdapter(); int selection = getSelectedItemPosition(); if (adapter != null && adapter.getCount() > 0 && selection >= 0) { return adapter.getItem(selection); } else { return null; } }
可以看到 return 的是
adapter.getItem(selection),也就是我们要重写的 Adapter 里面的
getItem()函数。如果重写的时候我们返回的不是
data数据,而是当前选中的
itemView(自定义的view)的话,就可以与
getSelectedView()相比较了(在重写
getView()里面,已经把自定义的
itemView设置为了
convertView的
tag了,也就是
(getSelectedView().getTag() instanceof itemView))。
再接着看
int selection = getSelectedItemPosition();,点击看到
getSelectedItemPosition()的源码:
[code] public int getSelectedItemPosition() { return mNextSelectedPosition; }
返回的是
mNextSelectedPosition!下一个位置!
再看到
getSelectedView()的源码
[code]public View getSelectedView() { if (mItemCount > 0 && mSelectedPosition >= 0) { return getChildAt(mSelectedPosition - mFirstPosition); } else { return null; } }
由于一般
mFirstPosition的值为0,所以也可以看作是返回
getChildAt(mSelectedPosition)当前选中的位置!
根据源码可以看出这两个方法得到的数据是有一点区别的,可是我们平时用的时候好像完全感觉不到,直到遇到特定的情况的时候,也就是我遇到的bug。
项目有个需求,是在右边的
Fragment切换时,左边的菜单
ListView会刷新选中项,并且选中项改变时,做一些效果(选中和失去)。我给
ListView注册了一个监听器
OnFocusChangeListener,代码如下:
[code]OnFocusChangeListener onFocusChangeListner = new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { Log.d(TAG, "hasFocus = " + hasFocus + ", pos = " + menuListView.getSelectedItemPosition()); Log.d(TAG, "getSelectedView = " + menuListView.getSelectedView().getTag()); Log.d(TAG, "getSelectedItem = " + menuListView.getSelectedItem()); if (hasFocus) { //给菜单ListView选中项设置为“第一焦点” setFirstFocus(); } else { //给菜单ListView选中项设置为“第二焦点” setSecondFocus(); } } }; menuListView.setOnFocusChangeListener(onFocusChangeListner);
为什么要这样做,就是因为
menuListView有两种状态的焦点,一种是选中时并且也得到焦点时(称为“第一焦点”),另一种是选中时但是焦点不在上面(称为“第二焦点”)。
第一焦点
第二焦点
接下来执行操作,当选中项为“媒体”且焦点不在
ListView上时,切换右侧
Fragment到“应用”,这个时候理想状况是“第二焦点”状态转移到“应用”。
我的做法是:在
setFirstFocus()中得到当前选中
menuListView.getSelectedView().getTag()设置为第一焦点文字颜色;在
setSecondFocus()中得到当前选中
menuListView.getSelectedView().getTag()设置为第二焦点文字颜色。(这里不考虑红色块背景以及右侧红色条,因为不属于ListView里面的部分,为了有滑动动画,是用
ImageView另外做的)。
当两个方法使用的都是
getSelectedView()时,效果变成了这个样子:
看打印发现
onFocusChange调用了两次,第一次打印
hasFocus = true, pos = 2;第二次打印
hasFocus = false, pos = 2。
而
getSelectedView().getTag()得到的
itemView是
pos = 1的
view,
getSelectedItem()得到的
itemView是
pos = 2的
view。(怎么知道的?通过打印
getView()里面所有
position的
itemView对比 id 号得出)
如前言所述,
getSelectedItem()得到的是
getSelectedView()的下一项!
可以根据现象证明,两次调用第一次把“媒体”设置为了第一焦点,第二次把“媒体”设置为了第二焦点。这显然不是我想要的结果。根据“应用”选项放大也可以看出现在选中项是“应用”。
如果这样调整:在
setFirstFocus()和
setSecondFocus()中把
menuListView.getSelectedView().getTag()替换为
menuListView.getSelectedItem()。
效果变成了:
很明显,应该改成
setFirstFocus()里面调用
menuListView.getSelectedView().getTag(),
setSecondFocus()里面调用
menuListView.getSelectedItem()。
完整效果图示:
1.作为第一焦点时
2.按右,作为第二焦点时
3.按下,第二焦点切换
[code]/** * ━━━━━━神兽出没━━━━━━ * ┏┓ ┏┓ * ┏┛┻━━━┛┻┓ * ┃ ┃ * ┃ ━ ┃ * ┃ ┳┛ ┗┳ ┃ * ┃ ┃ * ┃ ┻ ┃ * ┗━┓ ┏━┛ 看不懂,没关系.. * ┃ ┃ * ┃ ┗━━━┓ * ┃ ┣┓ * ┃ ┏┛ * ┗┓┓┏━┳┓┏┛ * ┃┫┫ ┃┫┫ * ┗┻┛ ┗┻┛ * * ━━━━━━神兽保佑,代码无bug━━━━━━ */
相关文章推荐
- Spark on Intellij IDEA
- MySQL - 基本操作
- spark on yarn模式:yarn命令杀除当前的application
- Hadoop+Hbase+Zookeeper(独立)环境搭建
- 第四章 Controller接口控制器详解(7 完)——跟着开涛学SpringMVC
- 使用js动态添加组件
- springMvc入门配置Validation
- 使用js动态添加组件
- MySql连接CommunicationsException错误
- BAT解密:互联网技术发展之路(4)- 存储层技术剖析
- 在Windows Server 2008如何安装Subversion
- 常用设计模式(三)——工厂设计模式
- PHP - MySQL数据库
- 网格部件和树型部件查找并定位焦点
- BAT解密:互联网技术发展之路(3)- 牛逼公司的技术架构都是这个范
- spark+hive win7开发环境配置
- Android——分别获取导航栏、状态栏高度
- 第四章 Controller接口控制器详解(6)——跟着开涛学SpringMVC
- PHP - 图像处理
- Spark报错:Failed to locate the winutils binary in the hadoop binary path