Layout inflate遇到的坑

2024-04-25 03:18
文章标签 遇到 layout inflate

本文主要是介绍Layout inflate遇到的坑,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

对inflate的理解

问题

    private void initVoiceItem() {viewMusicList.removeAllViews();int localResource = SysPreferences.getAlarmVoiceResource();LayoutInflater inflater = LayoutInflater.from(this);for (int i = 0; i < VOICE_KEY.length; i++) {View view = inflater.inflate(R.layout.item_voice_name, viewMusicList); // TODO: 2017/2/10view.setOnClickListener(mClickListener);...}}private final View.OnClickListener mClickListener = new View.OnClickListener() {@Overridepublic void onClick(View v) {int size = viewMusicList.getChildCount();for (int i = 0; i < size; i++) {View view = viewMusicList.getChildAt(i);...if (v == view) {{...1...}} else {{...2...}}}}};

有上面一串代码,你能发现有什么问题吗?

嗯嗯,是这样的:只会执行代码块{1},并没有像我们期待的那样点击的时候执行到代码块{2}中去。没有细究,通过下面的代码直接跨过去:

private void initVoiceItem() {viewMusicList.removeAllViews();int localResource = SysPreferences.getAlarmVoiceResource();LayoutInflater inflater = LayoutInflater.from(this);for (int i = 0; i < VOICE_KEY.length; i++) {View view = inflater.inflate(R.layout.item_voice_name, null); // TODO: 2017/2/10view.setOnClickListener(mClickListener);...viewMusicList.addView(view);}
}

虽然不知道什么原因,但是找到解决办法,不过还是挺惭愧的······

分析

很多人可能跟我一样,开始学的时候,记住该怎么写,这个方法是干嘛的。但是很难避免会记错某个方法,就像我们会写错某个字一样,当别人纠正的时候才知道,这个字自己已经写错十几活着几十年了。来看一下 View.inflate() 这个方法:

/**
* Inflate a new view hierarchy from the specified xml resource. Throws
* {@link InflateException} if there is an error.
* 
* @param resource ID for an XML layout resource to load (e.g.,
*        <code>R.layout.main_page</code>)
* @param root Optional view to be the parent of the generated hierarchy.
* @return The root View of the inflated hierarchy. If root was supplied,
*         this is the root View; otherwise it is the root of the inflated
*         XML file.
*/
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {return inflate(resource, root, root != null);
}

如果我们传入了 root View,那么返回的就是root View, 如果不传,则返回根据布局文件生成的 View。而根据我上面的代码,显然被我错误的理解,无论传不传 root View,返回的都是根据布局文件生成的 View,而我就这么相安无事的用了好几年······

你以为这就这样结束了

如果你执行我的错误代码,你会看到下面这个图:

这里写图片描述

这个这个图有两个信息:

  • 后面几个Item显示的名称是错误的
  • 点击某个Item,其他几个Item的checkbox也被选择

我们按照错误的代码执行的逻辑进行分析。首先:

for (int i = 0; i < VOICE_KEY.length; i++) {View view = inflater.inflate(R.layout.item_voice_name, viewMusicList);...
}

这段代码会循环多次,将inflate后的布局添加到viewMusicList,这样viewMusicList下面就有多个 item_voice_name 因此最终给我们展现的结果就是看到有多个Item。

对于第一个问题,我们需要从 view.findViewById() 说起,从View中你会发现这两段代码:

/**
* Look for a child view with the given id.  If this view has the given
* id, return this view.
*
* @param id The id to search for.
* @return The view that has the given id in the hierarchy or null
*/
@Nullable
public final View findViewById(@IdRes int id) {if (id < 0) {return null;}return findViewTraversal(id);
}/**
* {@hide}
* @param id the id of the view to be found
* @return the view of the specified id, null if cannot be found
*/
protected View findViewTraversal(@IdRes int id) {if (id == mID) {return this;}return null;
}

是不是太简单,根本没找到我们期待的逻辑——ViewGroup中怎么处理,细心的你会发现ViewGroup重写了 findViewTraversal() 方法:

@Override
protected View findViewTraversal(@IdRes int id) {if (id == mID) {return this;}final View[] where = mChildren;final int len = mChildrenCount;for (int i = 0; i < len; i++) {View v = where[i];if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {v = v.findViewById(id);if (v != null) {return v;}}}return null;
}

从这段代码可以看出,在ViewGroup中根据ID查找,找到就返回,而找到的永远是最前面的View。这就解释了为什么第一个Item和其他的不同了。

(对于点击某个Item,其他Item也出现波纹效果,猜测可能是因为波纹效果是根据ID来实现的。TODO )

总结

上面遇到的View inflate是我个人遇到的问题,主要是因为对基础知识掌握有问题。另外在使用inflate的时候,可能还会遇到LayoutParam设置无效的问题,这个可以通过套一个View的方式解决,仅此记录。

这篇关于Layout inflate遇到的坑的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/933572

相关文章

Anaconda 中遇到CondaHTTPError: HTTP 404 NOT FOUND for url的问题及解决办法

最近在跑一个开源项目遇到了以下问题,查了很多资料都大(抄)同(来)小(抄)异(去)的,解决不了根本问题,费了很大的劲终于得以解决,记录如下: 1、问题及过程: (myenv) D:\Workspace\python\XXXXX>conda install python=3.6.13 Solving environment: done.....Proceed ([y]/n)? yDownloa

ConstraintLayout布局里的一个属性app:layout_constraintDimensionRatio

ConstraintLayout 这是一个约束布局,可以尽可能的减少布局的嵌套。有一个属性特别好用,可以用来动态限制宽或者高app:layout_constraintDimensionRatio 关于app:layout_constraintDimensionRatio参数 app:layout_constraintDimensionRatio=“h,1:1” 表示高度height是动态变化

Android 友盟消息推送集成遇到的问题

友盟消息推送遇到的问题 集成友盟消息推送,步骤根据提供的技术文档接入便可。可是当你集成到项目中去的时候,可能并不是一帆风顺就搞定,因为你项目里面是可能集成了其他的sdk(比如支付宝,微信,七鱼等等三方的sdk)。那么这个时候,再加上友盟的消息推送sdk集成可能就会出现问题。 问题清单 友盟消息推送sdk和支付宝sdk冲突问题 后台配置了消息推送,也显示发送成功,但是手机没有收到消息通知

前端开发中遇到的小问题以及解决方案记录2

1、H5中适配屏幕的工具-postcss-px-to-viewport postcss-px-to-viewport。因为设计稿一般给的都是375px宽度的,所以假如一个字体是16px,那么在开发中不能直接写死为16px,因为各个厂商的手机屏幕大小是不同的,所以要根据屏幕大小去自适应修改px的大小,postcss-px-to-viewport这个工具就能很好地把项目中的px单位自动改为计算后的v

Android studio 遇到的问题总结

1、Error:Error: The WIFI_SERVICE must be looked up on the Application context or memory will leak on devices < Android N. Try changing getSystemService to getApplicationContext().getSystemService [Wifi

eclipse项目导入AS中遇到的问题

将eclipse的项目通过AS的启动中的导入(如果你的AS不是在这个界面,那么通过File->close project就可以进入这个界面了) 下面呢是导入后的一些问题 1、Android之Error: 'L' is not a valid file-based resource name character解决办法 参考:https://blog.csdn.net/u011068702

Android开发中遇到的各类问题汇总

Q1: Error:The number of method references in a .dex file cannot exceed 64K.Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html 应用中的Dex 文件方法数超过了最大值65536的上限

❤《实战纪录片 1 》原生开发小程序中遇到的问题和解决方案

《实战纪录片 1 》原生开发小程序中遇到的问题和解决方案 文章目录 《实战纪录片 1 》原生开发小程序中遇到的问题和解决方案1、问题一:原生开发中 request请求中返回 的数据无法 使用this传递给 data{}中怎么办?2、刚登录后如何将token信息保存,然后在后边的信息中使用。3、小程序下边的导航栏如何设置 1、问题一:原生开发中 request请求中返回 的数据无法

Vulkan描述符、描述符Pool、Layout概念

1、DescriptorSetLayout为了组织和管理着色器资源(如缓冲区、纹理、采样器等),多个相同类型的Descriptor放在一个Layout中以优化GPU对资源的访问   //DescriptorSetLayout定义了哪些描述符Descriptor类型(Buffers、Textures、Samplers)可以包含在其中 VkDescriptorSetLayoutBinding