Layout inflate遇到的坑

Android进阶之View.inflate和LayoutInflater.inflate方法区别 1 LayoutInflater   LayoutInflater用于加载布局的。加载布局的任务通常都是在Activity中调用setContentView()方法来完成的。其实setContentView()方法的内部也是使用LayoutInflater来加载布局的,只不过这部分源码是内部的。   我们先看下LayoutInflater的基本用法,首先需要获取到LayoutInflater的... 阅读详情

对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/10
            view.setOnClickListener(mClickListener);
            ...
        }
    }

    private final View.OnClickListener mClickListener = new View.OnClickListener() {
        @Override
        public 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/10
       view.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的方式解决,仅此记录。

View.inflate()和LayoutInflater.inflate()的区别 一、LayoutInflater.inflate() 1. 获取LayoutInflater实例 getLayoutInflater(); 这个方法可以在Activity和Fragment中使用,不过在Fragment中使用时,要传入一个bundle参数 // Activity中使用 LayoutInflater layoutInflater = getLayoutInflater(); //... 阅读详情

相关推荐

Arduino+NRF24L01 无线遥控舵机与无刷电机系统搭建指南

本文详细介绍了使用Arduino和NRF24L01模块搭建无线遥控系统的完整指南,涵盖舵机和无刷电机的无线控制。从硬件选型、电路连接到代码编写与调试,提供了实用技巧和常见问题解决方案,帮助DIY爱好者低成本实现稳定可靠的无线遥控应用。

sre5engineer的博客 589

android Unable to inflate view tag without class attribute

今天 写  一 tv 项目布局文件 ,运行报错   java.lang.RuntimeException: Unable to start activity ComponentInfo{com.droid/com.droid.activitys.UserCenterActivity}: java.lang.NullPointerException: Attempt to invoke v

chaoxionghuai的专栏 6509

ControlCAN.dll开发适配USBCAN_E/2E_U设备

摘要:本文提供了USBCAN_E/2E_U设备的配置指南:1)安装专用驱动;2)获取最新的ControlCAN.dll文件;3)修改VCI调用顺序,新增VCI_SetReference函数设置波特率;4)使用工具计算波特率配置值,并给出了常见波特率对应的代码参考值(如500K对应0x060007)。配置过程强调使用特定工具计算精确的波特率参数,并提供了相关软件下载链接。

weixin_43969033的博客 392

Android Studio环境下,LayoutInflater的inflate方法取不到自定义布局文件

今天在跟着《第一行代码》敲那个聊天界面的小demo时碰到了一个问题,就是在调用 LayoutInflater 的 inflate 方法时,无法获取自定义布局文件。正确的代码如下所示,但是未解决问题之前一直会有错误提示: View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item, parent,fal...

IamHYN的博客 1782

测绘无人船避坑指南:云卓H12Pro遥控器接海康摄像头,从网络设置到RTSP流延迟优化全流程

本文详细解析了测绘无人船视频子系统的优化方案,重点介绍海康威视摄像头与云卓H12Pro遥控器的深度适配流程。从网络设置到RTSP流延迟优化,提供了一套经过实测的低延迟(<200ms)解决方案,适用于复杂水域环境下的测绘任务。

weixin_30415113的博客 628

[Python] 为什么你的脚本明明没报错,却什么也没发生?

Python脚本运行后没报错却没结果?这是许多开发者遇到的棘手问题。文章分析了六种常见原因:代码未进入目标逻辑分支、输出路径错误、中间数据为空、异常被吞掉、异步操作未完成、运行了错误脚本版本。建议通过"过程可视化"排查,如打印关键变量、检查工作目录、验证数据状态等。职场中更应关注结果验证而非单纯代码执行,确保脚本真正解决问题。建立结果验证意识是从"会写代码"到"稳定交付"的关键转变。

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 303

LayoutInflate的使用

LayoutInflater作用是将layout的xml布局文件实例化为View类对象。 setContentView()一旦调用, layout就会立刻显示UI;而inflate只会把Layout形成一个以view类实现成的对象,有需要时再用setContentView(view)显示出来。一般在activity中通过setContentView()将界面显示出来,但是如果在非acti

hjj0212的专栏 4008

EtherCAT用TwinCAT 3跑DC报0x2C或者0x1A错误码

EtherCAT用TwinCAT 3跑DC报0x2C或者0x1A DC报错 ///////////////////////////////////////////////////////////////////////////////////////// /** \brief Checks communication and synchronisation variables and update AL status / AL status code if an error has occurr

PI_sunyang的博客 5308

使用 View.inflate 时产生 "找不到符号" 或者 "找不到ID" 的错误

因为引用的 layout 的 xml 文件名包含了大写字母或者特殊符号! 导致出现这个错误. 改成小写的标准文件名即可.

geekqian的博客 1300

8.19华为OD机试真题 新系统 - 基站低能耗时段统计 (Java/Py/C/C++/Js/Go)

8.19华为OD机试真题 新系统 - 基站低能耗时段统计 (Java/Py/C/C++/Js/Go)

算法大师! 1156

insightface scrfd人脸检测测试

pip install mmdet 自动安装mmcv win10上可以,服务器上没成功

jacke121的专栏 4023

Android inflate解析

对于inflate,我相信大家都不陌生,它的作用是将一个layout.xml布局文件变为一个View对象。尤其在ListView、GridView的Adapter中,我们继承BaseAdapter时必须重写的几个方法中有一个getView()方法,在这个方法中基本都会出现,使用inflate方法去加载一个布局,作为ListView、GridView的每个Item的布局。这篇博客就来分析一下Android中inflate的过程。

ITRenj的博客 6869

【电机应用控制】——步进电机控制原理(四相五线/两相四线/细分驱动)&驱动器&梯形/S形加减速算法&直线/圆弧插补

步进电机是一种把电脉冲信号转换为角位移(左)或线位移(右)的电动机。两相通常1.8°,三相通常1.2°、无相通常0.72°,角位移=脉冲个数X步距角。在非超载且不超频的情况下,电机的旋转位置只取决于脉冲个数,转速只取决脉冲信号的频率。所以只需要统计脉冲个数和频率,不再需要编码器测速和位置,具有优秀的开环能力,当然也可接编码器反馈速度和位置数据,实现更加精准的闭环控制。永磁式动态性能好,输出力矩大,但步距角大通常7.5°;反应式(磁阻式)结构简单成本低,步距角小一般1.2°,但振动噪音大动态性能差;

weixin_51658186的博客 5万+

Android layout Inflate 性能浅析

Android layout Inflate 性能浅析本文从三个测试方法测试 android 的 LayoutInflater.inflate 函数的性能。先上代码;以下的时间的单位都是ns(纳秒)package com.chillingvan.samplecode.xml;import android.app.Activity; import android.content.res.XmlReso

我的专栏 3515

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Android吃透inflate方法(一)

从inflate方法开始,搞懂LayoutInflater的inflate过程 在Android开发过程中,很多地方都不可避免的使用到inflate方法,如在使用RecycleView的时候构建ViewHolder对象,给Fragment进行CreateView 我们通常是inflater.inflate(R.layout.xxx, container, false)或者LayoutInflater.from(parent.context).inflate(R.layout.xxx, parent,

indeedes的博客 5402

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

三种inflate方式的区别

在安卓开发中,经常要将一个xml布局文件inflate成一个view对象,用到的方法通常是三种: (1)View.inflate(Context context, int resource, ViewGroup root); (2)LayoutInflater.from(context).inflate(int resource, ViewGroup root); (3)getSystemServ...

whoami_I的博客 829

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

266.inflate

想象你有一张建筑图纸(XML布局文件),而inflate就是按照这张图纸盖房子的过程。它把 XML 文件"充气"成真正可以看到和操作的 View 对象。Inflate 是 Android 中将 XML 布局文件转换为 View 对象的过程,让静态的 XML 描述变成动态的界面组件。// 创建对话框视图:使用 LayoutInflater 将 custom_dialog 布局文件解析成 View 对象// 使用 AlertDialog.Builder 创建对话框。

2303_79132118的博客 1323

inflate方法参数总结

inflate方法是LayoutInflater的方法,用来使用xml资源文件创建view对象,一般这样使用: LayoutInflater.from(viewGroup.getContext()).inflate... 我们来比较一下两种重载方法: inflate(@LayoutRes int resource, @Nullable ViewGroup root) inflate(@L

jiashuai94的博客 854

inflate 属性失效

 获得 LayoutInflater 实例的三种方式 1.LayoutInflater infalte=context.getSytemService(Context.LAYOUT_INFLATE_SERVICE); 2.LayoutInflater inflater = getLayoutInflater(); //调用Activity的getLayoutInflater() 3.LayoutI...

bobo的博客 534

android layout.inflater,LayoutInflater.inflate详解

LayoutInflater概述从XML文件中实例化一个布局成对应的View类, 它从来不会直接使用, 而是使用getLayoutInflater()或者getSystemService(String)来获得一个对应当前context的标准LayoutInflater 实例。例如:LayoutInflaterinflater=(LayoutInflater)context.getSystem...

weixin_42515136的博客 379

Android的inflate你所需要知道的一切

‘’xml布局转换为view对象‘’一碰到这个需求时我们心中的思路就来了,简直小case。安卓提供的api:View的inflate方法、LayoutInflater的inflate方法都可以快速的完成我们的需求。然而生活并不是一帆风顺的哈,我们在recyclerview中使用时或者在fragment中使用时或许会碰到这样的问题: 1、布局参数获取不到,项目有时直接崩溃了。 2、奔溃报错:子vi...

dev晴天的博客 1377

LayoutInflater.inflate()方法解析

1、基本介绍在开发中 LayoutInflater. inflate() 这个方法还是非常有用的,它的作用类似于 findViewById()。不同点是 inflate() 是用来找 res/layout/ 下的 xml 布局文件,并且实例化,而 findViewById() 是找 xml 布局文件下的具体 widget 控件(如 Button、TextView 等)。对于一个没有被载入或者想要动态

HardWorkingAnt的博客 4157

安卓中的inflate方法

inflate方法有如下两种: public View inflate (int resource, ViewGroup root) public View inflate (int resource, ViewGroup root, boolean attachToRoot) 查看源码,我们发现两个参数的方法内部引用了三个参数的方法 public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) { retur

weixin_44898389的博客 2853

View.inflate和LayoutInflater的inflate方法区别

平时ListView加载item中,adapter的getView方法中,我们经常用到: LayoutInflater.from(mContext).inflate(R.layout.it ,parent,false); 这样的方法来加载布局xml,平时一直就是这么用的,也没什么疑问。今天网上看了个自定义布局的源码,自定义布局中加载布局xml用的View.inflate方法: public cl

渴望飞翔的猪 1万+

Android中inflate方法的用法总结

Inflate()作用就是将xml定义的一个布局找出来,但仅仅是找出来而且隐藏的,没有找到的同时并显示功能。而setContentView()将布局设置成当前屏幕即Activity的内容,可以直接显示出来。 SetContentView()一旦调用, layout就会立刻显示UI;而inflate只会把Layout形成一个以view类实现成的对象。有需要时再用setContentView(vie

KenHuang的专栏 7307
上一篇: 使用requests处理cookie
下一篇: Android闹钟遇到的那些坑
ttdevs
博客等级 码龄15年 388粉丝 91原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值