最近Tv项目中有个小问题,需要gridview展示内容,但是不可获取焦点,于是xml中设置android:focusable=“false”,设想会成功,但是实际操作,发现还是可以获取焦点,只有在代码中设置setFocusable(false)才起作用,这个问题当时有点搞不懂,带着这个问题,我去从源码中寻找答案。
思路分析:
普通的view在xml设置android:focusable=false,是不会获取焦点的,那gridview会不会在初始化构造的时候就设置成可以获取焦点的呢,带着这个思路去看下构造。

1、首先看GridView的构造函数:

public GridView(Context context) {this(context, null);}public GridView(Context context, AttributeSet attrs) {this(context, attrs, R.attr.gridViewStyle);}public GridView(Context context, AttributeSet attrs, int defStyleAttr) {this(context, attrs, defStyleAttr, 0);}public GridView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);}

看最有一个构造函数,调用了super父类的构造函数,GridView和ListView一样,都是AbsListView的子类,所以去看AbsListView的构造。

   public AbsListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);initAbsListView();.....}

看下 initAbsListView()方法。

  private void initAbsListView() {// Setting focusable in touch mode will set the focusable property to truesetClickable(true);setFocusableInTouchMode(true);//......}

到这里好像看到了setFocusableInTouchMode,好像看到了希望,其实不完全是,这个是设置在触控模式下可获取焦点,但是上面注释说,在touch模式下设置focusable同样会设置可获取焦点的属性,看下其源码:

 @Overridepublic void setFocusableInTouchMode(boolean focusable) {final T adapter = getAdapter();//判断adapter是否为空final boolean empty = adapter == null || adapter.getCount() == 0;mDesiredFocusableInTouchModeState = focusable;//设置mDesiredFocusableState  为 FOCUSABLE,这个   mDesiredFocusableState 看意思是期望的获取焦点的状态if (focusable) {mDesiredFocusableState = FOCUSABLE;}super.setFocusableInTouchMode(focusable && (!empty || isInFilterMode()));}

从这个方法中我们看到设置 mDesiredFocusableState 为可获取焦点的状态,但是并没有发现其直接设置setFocusable为true,我们再去源码中寻找。
再次整理思路:
从上面的方法中我们发现adapter的内容非常重要,那会不会是在setAdapter中改变了焦点状态呢?

 @Overridepublic void setAdapter(ListAdapter adapter) {//省略部分代码super.setAdapter(adapter);if (mAdapter != null) {mOldItemCount = mItemCount;mItemCount = mAdapter.getCount();mDataChanged = true;checkFocus();}

发现了checkFocus(),开心了,找到了目标,继续探寻。该方法在
AdapterView父类中。

void checkFocus() {final T adapter = getAdapter();//设置了内容后,empty为false。final boolean empty = adapter == null || adapter.getCount() == 0;//focusable为truefinal boolean focusable = !empty || isInFilterMode();//刚才构造的时候,mDesiredFocusableInTouchModeState为truesuper.setFocusableInTouchMode(focusable && mDesiredFocusableInTouchModeState);//重点来了,focusable为true,取 mDesiredFocusableState 的值super.setFocusable(focusable ? mDesiredFocusableState : NOT_FOCUSABLE);if (mEmptyView != null) {updateEmptyStatus((adapter == null) || adapter.isEmpty());}}

倒数第三行调用了 super.setFocusable(),传入的是mDesiredFocusableState ,上面已经分析过了,经过构造函数,这个mDesiredFocusableState 为 FOCUSABLE,这样就找到原因了,为什么GridView是可以获取自动获取焦点了。

不过这里为什么用一个mDesiredFocusableState 的值而不是直接focusable传进呢?以及我项目中在setAdapter之前,构造方法调用之后,设置了setFocusable(false),生效了,这里就是源码的精髓,
看下该方法实现:
setFousbale(boolean)调用的是view的方法,最终调用了AdapterView的其override方法。

 @Overridepublic void setFocusable(@Focusable int focusable) {final T adapter = getAdapter();final boolean empty = adapter == null || adapter.getCount() == 0;//这里 mDesiredFocusableState 变成了我传入进来的NOT_FOCUSABLEmDesiredFocusableState = focusable;if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {mDesiredFocusableInTouchModeState = false;}//调用父类的方法,但是此时还是内容为空,所以设置不可获取焦点super.setFocusable((!empty || isInFilterMode()) ? focusable : NOT_FOCUSABLE);}

总结:

GridView以及ListView在是否获取焦点的问题上,最重要参考就是我们是否设置了Adapter,以及Adapter是否有内容,如果有内容了,就可以获取焦点,除非我们自己显式的调用了setFocusable为false。

GridView xml中设置android:focusable=false无效的原因相关推荐

  1. 安卓xml文件中设置动画匀速旋转无效?

    最近写的自定义progressdialog,在写上面的loading进度条旋转动画时出现了问题,在布局文件中设置了匀速转动的属性之后,没有作用 也就是这个属性     android:interpol ...

  2. 【Flutter】Flutter 启动白屏问题 ( 问题描述 | 在 launch_background.xml 中设置启动过渡 UI )

    文章目录 一.Flutter 启动白屏问题 二.在 launch_background.xml 中设置启动过渡 UI 三.博客源码 一.Flutter 启动白屏问题 启动 Flutter 应用 , 在 ...

  3. 使用xslt将.xml,转换成一个html网页时中文显示乱码怎么办,用dom将数据写到xml中 设置xml文件gbk编码时中文会出现乱码...

    问题:我用dom将数据写到xml中 设置xml文件的编码格式是gbk时再dos下运行jar包中文会出现乱码 如下: 代码如下: StringWriter strWtr = new StringWrit ...

  4. android+listview设置行高,android – 无法在行xml中设置listView行高的高度

    这是我的自定义适配器的getView方法: public View getView(int position, View convertView, ViewGroup viewGroup) { Sin ...

  5. Android 在java代码中获取xml中设置的dimen值

    1.如果dimen值写在了dimen.xml中: int width = (int)context.getResources().getDimension(R.dimen.thumb_img_widt ...

  6. 【错误记录】未安装该应用 ( 在 Android 12 之后 组件设置 android:exported=“false“ 属性 )

    文章目录 一.报错信息 二.解决方案 一.报错信息 报错信息 : 点击应用图标后 , 应用并未启动 , 并弹出 " 未安装该应用 " 提示信息 ; 二.解决方案 排查了一下相关地方 ...

  7. android自定义控件是一个 内部类 如何在xml中引用,android 自定义view属性

    android 自定义view属性 一个完美的自定义控件也可以添加xml来配置属性和风格.要实现这一点,可按照下列步骤来做: 1) 添加自定义属性到xml文件中 2) 在xml的中,指定属性的值 3) ...

  8. 【Android布局】在程序中设置android:gravity 和 android:layout_Gravity属性

    在进行UI布局的时候,可能常常会用到 android:gravity  和 android:layout_Gravity 这两个属性. 关于这两个属性的差别,网上已经有许多人进行了说明,这边再简单说一 ...

  9. 在xml中设置spinner文字大小、颜色

    Spinner用的还是挺多的,很多时候spinner的选项都是从后台数据库中查询得到,然后用adapter绑定进去:但是也有一些时候选项值是直接通过entries属性将string-array资源绑定 ...

最新文章

  1. 我的WCF之旅(6):在Winform Application中调用Duplex Service出现TimeoutException的原因和解决方案...
  2. java int转String全部方式的效率对照与深入解析
  3. UIButton-初识IOS
  4. [转]关于HTTP服务器每个客户端2个连接的限制
  5. Python学习8 函数 匿名函数 内置函数
  6. 经验之谈:10位顶级PHP大师的开发原则
  7. 征稿 | 软件学报专刊征文:知识赋能的信息系统
  8. 计算机设计大赛国奖作品_4. 界面设计
  9. C/C++混淆点-strcat和strcpy区别
  10. 使用ORACLE生成随机数
  11. 单独招生计算机笔试是考什么,单招考试一般考什么内容
  12. mysql查字段的备注_Mysql 查看表注释或字段注释
  13. 知识管理系统Data Solution研发日记之七 源代码与解决方案
  14. OpenGL入门教程
  15. 《神经网络与深度学习》编程笔记
  16. MATLAB求分数阶微分的数值解,G-L定义,R-L定义,Caputo定义
  17. Office VBA开发经典-中级进阶卷(75元包邮)
  18. Matlab:二维傅里叶变换
  19. python scripts 目录空
  20. 计量经济学计算机答案14章,伍德里奇---计量经济学第8章部分计算机习题详解(STATA)...

热门文章

  1. VMware运行Ubuntu 三种网络连接方式:bridge、NAT、Host-Only的区别
  2. 面对安利,谁能笑到最后
  3. python内存注入代码_Python模板注入
  4. 开源之旅之开源企业软件采购指南
  5. 华为P50E全方位曝光:延续P50设计 换装骁龙778G 4G芯片
  6. 新款iPhone SE来了,从二手市场保值率来看值不值得买?
  7. 阿里巴巴招募鉴黄体验官,日薪1000元,小姐姐优先,要求阅“片”无数
  8. Uzi宣布退役:身体条件不允许再继续战斗了!
  9. 官方暗示与TÜV莱茵合作? MIUI12真的不远了
  10. 华为P40系列全家福亮相:DxO冠军宝座已预订