layout中引用后定义的控件id不报错?

如何在android style文件中使用自定义属性 前几天我在项目中遇到了这样一个问题:我为项目写了一个自定义控件,这个控件会被大量复用,所以我准备在style.xml文件中定义一个style来减少重复xml布局内容的编写,但是里面有一个自定义的控件属性,问题出现在这里,虽然自定义属性在layout布局xml中可以使用正常,但是却无法在style中定义,本来这个控件是大量服用的,style也是为了复用减少xml内容写的,我可以把自定义属性内容直接写 阅读详情

1、问题

最近写layout时遇到一个奇怪的问题,layout布局中有两个控件属性都引用了在其后定义的控件id,编译时其中一个报id找不到,但是另一个却没有报错,而且布局显示都正常。布局layout大致如下:

<TextView
    android:id="@+id/title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_toLeftOf="@id/btn"
    android:textStyle="bold" />

<Button
    android:id="@+id/btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_toLeftOf="@id/arrow" />

<ImageView
    android:id="@+id/arrow"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_centerVertical="true"
    android:src="@drawable/arrow" />

如上layout所示,Button控件引用了id arrow,TextView控件又引用了id btn。最终报的是找不到btn id,将Button控件挪到TextView前面后发现,编译正常,没有报错,程序运行后布局也没有错乱现象,完全没有影响。

2、分析

这不科学,按照常规来说,被引用的id应该必须先于引用它的控件声明。这里大概可以分为三种情况:

  • 可以先添加被引用的控件,声明id属性,然后再添加引用它的控件
  • 也可以后添加被引用的控件,但是在添加引用它的控件时需要使用@+id先添加被引用控件的id,例如android:layout_toLeftOf=”@+id/arrow”
<Button
    android:id="@+id/btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_toLeftOf="@+id/arrow" />
<ImageView
    android:id="@id/arrow"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_centerVertical="true"
    android:src="@drawable/arrow" />
  • 使用android sdk自带的id,例如@android:id/text1

以上三种情况,不管哪种,都是保证在引用控件id时,该id已经存在R文件中。可是我们这里这三种情况均不符合,为什么也是可以的呢?
难道是arrow的某些属性比较特殊,例如layout_alignParentRight属性,会导致控件优先被解析?去掉该属性测试下也没有报错,这应该不是问题根源所在。因为Android对于xml解析是从上往下递归进行的;另外,layout中控件的位置确定应该在是运行时加载这个布局文件才会去measure、layout的。
换个思路,既然没有报错,那么应该是在解析这个layout时,已经存在了该arrow id。我们知道在编译打包阶段,aapt会为所有的资源生成唯一id(R文件)。在解析layout时,aapt会去R文件中检查id的正确性。那么也就是说项目中其他地方也定义了相同的id,并且先于该layout被解析了。
这样出现的问题也就可以解释了,该layout所在的项目main依赖了一个底层的base项目,base项目中已经定义了arrow id。打包时,aapt会先将base打包成aar,因此R文件中已经存在了arrow id,导致我们的layout没有报找不到id的错误。另外,事实上btn id在main项目中也存在多处重复定义,但是却报了找不到id的错误,原因应该是另一处的double_user所在的layout并没有先于被解析导致的。

3、总结

虽然引用后定义的控件id可能不会报错,但是还是应该遵循先定义,后引用的规则。否则,不知道什么时候底层依赖的aar改了id,上层就会报错,修改起来将很麻烦。

4、脚本开发

为了彻底解决这样的潜在bug,特地学习了下python,写了个小脚本,用于检查项目中存在问题的layout文件。脚本主要针对ReleativeLayout中的相对位置属性进行扫描检查,代码如下:

#!/usr/bin/env python

import xml.etree.ElementTree as XmlTree
import os

dir = '../Demo/build/intermediates/res/merged/common/debug/layout/'

attrib_id = '{http://schemas.android.com/apk/res/android}id'
attrib_toleft = '{http://schemas.android.com/apk/res/android}layout_toLeftOf'
attrib_toright = '{http://schemas.android.com/apk/res/android}layout_toRightOf'
attrib_above = '{http://schemas.android.com/apk/res/android}layout_above'
attrib_below = '{http://schemas.android.com/apk/res/android}layout_below'
attrib_tostart = '{http://schemas.android.com/apk/res/android}layout_toStartOf'
attrib_end = '{http://schemas.android.com/apk/res/android}layout_toEndOf'

attrs = [attrib_toleft, attrib_toright, attrib_above, attrib_below, attrib_tostart, attrib_end]

#parse each layout to find error
def checklayout(layoutname):
    xmltree = XmlTree.parse(dir + layoutname)
    root = xmltree.getroot()
    ids = []
    for element in root.iter():
        for key in element.attrib.keys():
            value = element.attrib.get(key)
            if key == attrib_id:
                id = value.split('/')[1]
                ids.append(id)
            if key in attrs:
                target = element.attrib.get(key).split('/')
                if target[0] != '@+id' and target[0] != '@android:id' and target[1] not in ids:
                    return layoutname
    return ''

#main function to start this script
def main():
    print '******loading******'
    layouts = [filename for filename in os.listdir(dir) if os.path.isfile(dir + filename)
               and os.path.splitext(filename)[1] == '.xml']
    result = []
    for layout in layouts:
        error_layout = checklayout(layout)
        if error_layout != '':
            result.append(error_layout)
    print result

main()
配置oem 13c以监控管理数据库 使用oem13c监控数据库 阅读详情

相关推荐

Versal - 从零构建Petalinux 2024.2 AI边缘计算平台(VD100+SDT+JupyterLab实战)

本文详细介绍了如何从零开始,基于AMD Versal VD100开发板和Petalinux 2024.2构建AI边缘计算平台。内容涵盖开发环境搭建、Petalinux工程创建与配置、SDT新流程实战、启动SD卡制作,并最终集成JupyterLab与Conda,打造出开箱即用的交互式AI开发环境,帮助开发者快速进行算法验证与部署。

5f4d3s2a1q的博客 489

Android引入布局

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。

star_nwe的博客 382

Unity面试题总结

Unity面试题

sinat_34014668的博客 1万+

findViewById(R.id.btn_first) 给写成 R.layout.

窗体内放了个按钮, findViewById(R.id.btn_first) 给写成 R.layout. 在java 里边引用结果就是找不到那个id 找了半天找不到原因, 奔着网上常见R找不到的问题,半天没发现,最后也找到了这个R文件 里边有自动生成的button的id 但是我以为编译器没有使用这个文件,因为网上有说使用的系统自带的R文件的问题,可能比较老的问题 最后Gradle 里边也...

weixin_33961829的博客 617

RNA 8. SCI文章中差异基因表达--热图 (heatmap) 进阶:从数据标准化到多维度注释

本文深入探讨了RNA差异基因表达分析中热图(heatmap)的进阶应用,从数据标准化到多维度注释。详细介绍了FPKM标准化、Z-score转换等关键技术,以及pheatmap包的高级注释功能,帮助研究者制作发表级热图。文章还提供了视觉优化策略和生物学意义衔接的实用建议,助力SCI论文的数据可视化。

weixin_29051149的博客 302

《QEMU/KVM源码分析与应用》读书笔记1 —— 第1章 QEMU与KVM概述

《QEMU/KVM源码分析与应用》学习笔记1 —— 第一章 QEMU与KVM概述

phmatthaus的专栏 1984

在 Android Studio 的布局编辑器(Layout Editor)中,如果删除了 .xml 文件中的所有代码,会导致无法拖拽其他布局组件,解决办法

文件完全为空,编辑器将无法识别这是一个合法的布局文件,因此无法启用可视化拖拽功能。的视图(View)和视图组(ViewGroup)构成的。通过上述步骤恢复根布局后,即可正常拖拽组件!如果删除了根布局,相当于移除了这棵树的“根”,自然无法操作子节点。:布局文件必须有一个根布局作为容器,否则设计器无法解析结构。拖拽到预览界面中,系统会自动生成对应的 XML 代码。:即使代码为空,也需要保留合法的 XML 标签结构。文件中重新添加一个根布局容器(例如。),确保编辑器重新加载内容。

2303_76756730的博客 544

【WRFDA教程】客观分析(OBSGRID)详解

客观分析(OBSGRID)详解

WW、forever的博客 1133

android中在Layout布局文件中添加控件ID,在Activity中findViewById找不到

一直用着好好的eclipse开发android的应用,突然新建的项目中发现在Layout布局文件中控件ID在R中不能自动生成了。然后在Eclipse中通过Project->Clean操作之后在R中就生成了控件的ID,这样也太麻烦了。突然想到前几天做个项目需要把eclipse中的自动构建取消掉了,然后目前就不能自动生成了,需要手动操作,在eclipse中设置自动构建就好了,具体操作Project->B

gogmz的博客 2568

[HBM] RAM Cell Self Repair | 内存单元自我修复

对抗错误的大都是冗余,内存颗粒在设计的时候也考虑增加冗余。具体的说:添加冗余或备用的存储单元行和列,及时将测试中的故障进行修复和替换,存储器修复包括行修复,列修复或两者的组合。

串起点滴 785

网工、运维利器:MobaXterm,一款全能的远程工具

你好,这里是网络技术联盟站,我是瑞哥。是一款由Mobatek开发的多功能远程计算机管理工具,集成了多种网络协议和工具,专为网络工程师和系统管理员设计。它提供了丰富的远程连接功能,包括SSH、RDP、VNC、X11转发等,支持文件传输和多标签界面,内置了文本编辑器和多种网络工具,是一款全能的远程管理软件。MobaXterm的开发起始于2008年,最初只是一个简单的X服务器,但随着用户需求的不断增加和软件的逐步完善,MobaXterm逐渐发展成了一款功能全面、界面友好的远程管理工具。

网络技术联盟站 5230

android 之@+id与@id以及引用中用@+id/的原因

在Android xml文件中大家都知道一般在定义一个id时用@+id/id名字,而在引用一个id,比如在已定义的控件的左边,就要用到@id/已定义的控件。        详细的解释童鞋们可以看这篇文章http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1019/443.html       今天下了一份代码,在

不系之舟王的专栏 3539

AI智能体丨使用Coze生成自媒体短视频分镜生成器(附保姆级教程)

【短视频分镜脚本生成器】是一款由Coze平台开发出来的智能体,可快速解析某音/某书视频或本地文件,自动生成专业分镜脚本。用户只需输入视频链接或上传文件,系统即会分析镜头节奏、叙事逻辑和画面内容,输出包含画面、模板和话术参考的标准化脚本(支持3分钟内视频)。该工具还能生成HTML网页和可下载图片,提供可视化呈现。工作流程包括视频解析、帧提取、AI画面理解、脚本生成和网页制作,大幅提升短视频创作效率。

李同学Lino的博客 1535

[Android布局]Relativelayout内部控件使用layout_toLeftOf或layout_toRightOf出错(会造成不能解析R文件)

问题描述 text属性为"18" 的TextView控件需要在ImageView左边,于是我就按从左到右的顺序写了控件布局,然后在TextView中加入layout_toLeftOf="@id/age_more"属性值,这导致R文件解析出错。 原因 在定义ImageView的id之前使用了该id,即"@id/age_more",会使编译程序不能找到该id。 解决办法 将id定义移动到使用之前,因为...

qq_40055714的博客 1045

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

android studio databinding和include使用控件id获取报错 不影响项目正常运行

android studio databinding和include使用控件id获取报错 不影响项目正常运行 解决办法: 1.android studio3.6.3 使用gradle版本由5.6.4 换为 6.1.1 2.删除目录下的build,重新编译 3.删除.idea文件重新打开AS

康__的博客 1251

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

android的xml登录,Android----xml文件中的控件的id设置

Android开放中要想得到布局文件中控件的引用,该控件必须设置id属性,这两有两种方式设置id:(1)@+id/xxxx;(2)@id/xxxx;下面做个简单的介绍。@+id/xxx:如果R文件中没有该id则创建;注意:一个xml文件中不能出现两个以该形式设置同一id的两个控件(include标签例外);示例1 正确的使用:android:id="@+id/mytv"android:layout...

weixin_33262687的博客 956

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Android LinearLayout中子控件layout_gravity=“center“无效 问题解决

LinearLayout中子控件layout_gravity="center"无效 问题解决 在一些情况下,两个子控件,其中一个需要居中,另外一个在这个控件的后边 当时理所当然的默认使用了LinearLayout布局,想着设置成android:orientation=“horizontal”,然后其中一个控件居中即可 万万没想到居然不可以 代码如下: <LinearLayout android:layout_width="match_parent" android:la

使命初始的博客 1443

页面布局Layout

1、编写XMl <1>、利用 Android 的 XML 词汇,按照在 HTML 中创建包含一系列嵌套元素的网页的相同方式快速设计 UI 布局及其包含的屏幕元素 。 <2>、每个布局文件都必须只包含一个根元素,并且该元素必须是视图对象或 ViewGroup 对象 。 <3>、定义根元素后,可以子元素的形式添加其他布局对象或控件,从而逐步构建定义布局的视图层次结 构 在 XML 中声明布局后,以 .xml 扩展名将文件保存在Android 项目的 res/layout

米兰的糖果罐的博客 1169

Caused by: java.lang.NullPointerException: Missing required view with ID: com:id/chk_bl

* 既然你确认 `res/layout/` 里的文件没问题,那一定是 `layout-land` 或 `layout-watch` 里的同名文件在作怪。* **场景 B**:如果你的设备系统属性被识别为 **watch**(某些嵌入式 Android 设备会有这个属性),系统会去 `layout-watch` 文件夹里找。* **场景 A**:如果你的设备当前处于**横屏**状态,系统会自动去 `layout-land` 文件夹里找 `fragment_test_setting.xml`。

weixin_40388758的博客 582

Android中自定义组合控件

Android中自定义控件的情况非常多,一般自定义控件可以分为两种:继承控件及组合控件。前者是通过继承View或其子类,重写方法实现自定义的显示及事件处理方式;后者是通过组合已有的控件,来实现结构的简化和代码的重用。 本篇文章主要介绍自定义组合控件,继承控件后续有机会再述。 自定义组合控件一般来说都是以ViewGroup及其子类(LinearLayout、RelativeLayout、Fram...

weixin_30546933的博客 199

Android studio layout布局2

相对布局(重点) 1.1 相对布局窗口内子组件的位置总是相对兄弟组件、父容器来决定的,因此叫相对布局 1.2 如果A组件位置是由B组件的位置决定的,Android要求先定B组件,再定义A组件 如果A组件位置是由B组件的位置决定的,Android要求先定B组件,再定义A组件 如果A组件位置是由B组件的位置决定的,Android要求先定B组件,再定义A组件 注1:注意XML中组件的顺序,不然会报错...

qq_41038970的博客 518

安卓控件及控件属性

一。控件的创建和获取 1.声明控件对象时,要确保类型与xml中控件的类型保持一致 2.findViewById(R.id.名)返回的是View类型的对象,需要强转类型为对应的控件类型 3.参数R.id.名要确保导入的是正确的R文件,否则会报错 二、控件的宽和高 layout_width  控件宽度 layout_height 控件高度 可以设置的值有 1.fill_parent(不常用)或mat

张小贝的博客 1050

framework 增加了控件,编译报错找不到符号

【代码】framework 增加了控件,编译报错找不到符号。

xiaowang_lj的博客 162

导入module或三方自定义控件报错NoSuchFieldError

报错内容:java.lang.NoSuchFieldError: No field tv of type I in class L com/mic/adressselectorlib/R$id; or its 原因:没有找到“tv”这个id,可能是因为你的项目下有重名文件,造成一个名字多个id解决方案:不要专注于错误信息给定的重复名称,比如tv没有找到,去它所在的layout,查看一下layout...

fynzhy的博客 440

【转载】android 中Xml里面的id重名问题

转载自:http://blog.youkuaiyun.com/luckyjda/article/details/8548127  今天在做项目的时候,居然发现@+id 居然可以重名,而且程序还不会报错。郁闷了,这到底怎么回事呢?经过google 和百度之后,才有所了解。 情况一:同个一个Xml文件中的同名 在同个一个Xml文件的中若同名了,则前一个有效,而后一个无效,即后一个Nu

chenloxiaoea的博客 538

在约束布局中使用include标签报错

问题出现的场景: 我在约束布局ConstraintLayout中引入了一个布局,然后给引入布局添加了底部约束,让它距离底部8dp,但是引入布局仍然出现在顶部。并报错如下: 问题分析: 报错原文:Layout parameter layout_marginBottom ignored unless both layout_width and layout_height are also s...

Ein3614的博客 7807
上一篇: Android性能优化
下一篇: Multidex何弃疗
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值