Android开发技巧之xml tools属性详解

我们知道,在 Android 开发过程中,我们的数据常常来自于服务端,只有在运行时才能获得数据展示,因此在布局 XML 的编写过程中,由于缺少数据,我们很难直接看到填充数据后的布局效果,那这个时候你一般是怎么做的呢?

经常看到一些小伙伴的做法是在布局文件中临时写死一些数据来查看布局展示效果,在查看结束后,再手动将这些数据进行删除。

是不是很麻烦,那我们有没有更简单点的方案呢?

针对上述的问题,Google 官方其实早就考虑到了,因此在开发工具中提供了 tools 命名空间的支持。

在布局 XML 文件中使用 tools: 命名空间添加的属性,在项目构建成 过程中,tools 属性会被构建工具自动移除,最终不会对构建程序产生任何的影响。

而除去在编写布局时的预览功能外,tools: 命名空间属性还提供了很多有用的功能,那么接下来我们就来详细介绍下 tools 属性的这些功能。


按照官方的定义, tools 属性划分为了三种类型:

错误控制属性(Error handling attributes)

主要用来帮助我们控制一些由 lint 产生的错误警告。


tools:ignore

适合于任意元素

我们知道,在 Android 开发工具中提供了 lint 工具,可以帮助您轻松地识别并纠正问题与结构质量的代码。

而 lint 中针对不同的问题警告定义了不同的 ID,该属性则可以通过设置 lint 中对应的问题 ID 来让 lint 忽略该种警告,同时也可以通过逗号分隔符的方式设置多个问题 ID 来忽略多种警告。

例:

<string name="show_all_apps" tools:ignore="MissingTranslation">All</string>

一般在存在多国语言资源包的情况下, 如果 strings.xml 里某个String 没有给出其他语言版本的翻译, 那么 lint 会给出 MissingTranslation 的警告提示,

而通过 tools:ignore="MissingTranslation" 我们就可以让 Lint 针对这条 String 忽略这个警告。

再例如我们开发中更常见的一个问题:

在使用 ImageView 标签时,如果不加 android:contentDescription 那么 lint 会给出 contentDescription 的相关警告,

此时,我们可以通过给 ImageView 标签添加 tools:ignore="contentDescription" 来忽略这个警告。

 <ImageView ...
  tools:ignore="contentDescription"
/>

tools:targetApi

适用于任何元素

这个属性类似我们在代码中使用 @TargetApi
注解

当我们使用的组件元素支持的 Android 最低版本大于我们项目所指定的最低版本 minSdkVersion 时, lint 会给出相应的版本警告。

该属性则可以通过给指定的布局设置对应的 API 版本来通知 lint 忽略警告。

例:

<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:targetApi="14" >

如果我们不使用 v4 包下的 GridLayout , 那么 GridLayout 则只支持 API LEVEL 14 以上系统,此时如果我们项目的 minSdkVersion 低于14 ,那么 lint 会给出版本警告

当添加了 tools:targetApi="14" 之后,Lint 就会停止对应的版本警告了。


tools:locale

适用于 <resources> 元素

这个属性用来指定默认的资源文件所使用的语言环境,从而避免 Lint 在拼写检测的时候带来不必要的警告提示。

默认情况下,开发工具会假设我们的语言环境为英语,因此单词检测器(spell checker)在检测过程中会对一些英文字母产生警告。

例如,我的 app_name 叫TRSDK, 默认情况下 TRSDK 下会产生波浪线的警告提示:

Paste_Image.png

此时如果我通过 tools:locale 设置默认环境为中文 zh,那么警告就会消失了

Paste_Image.png

设计时预览属性(Design-time view attributes)

这类属性主要是针对于 Android layout 布局的特征属性的,通过设置这类属性可以在 Android Studio 的布局预览界面快速预览布局展示效果。


tools: instead of android:(可替代任何 android: 开头的属性)

适用于 <view> 类视图元素

你可以针对视图组件的属性,通过使用 tools : 前缀来替换 android: 前缀,从而提前在布局预览界面预览属性设置的效果。

并且在代码构建的时候,构建工具会自动移除这些属性,不对最终打包的 APK 产生任何影响。

例如:

如果 TextView 的数据需要在运行时才能获取,那我们可以通过设置 tool:text 的值,在布局预览界面预览数据填充后的效果,如图:

通过将 tools:text 属性设置为 "Google Voice" 在布局预览界面直接查看效果

我们可以同时设置 android: 属性(运行时才能显示) 和匹配的 tools: 属性(只会在布局预览界面显示),构建项目时最终 tools 属性会被移除,只以 android: 属性的值显示。

假设 FrameLyout 中有多个子布局,并且我们只想预览有一个布局时的效果,此时,我们也可以通过设置 tools 属性来预览一个子布局时的显示效果:

<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="First" />

<Button
    android:id="@+id/button2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Second"
    tools:visibility="invisible"  />

tools:context

适用于部分 <view> 根布局

该属性用于设置布局文件相关的 Activity,从而使用开发工具的快速修复功能( quick fix )时能自动关联 Activity 上下文生成对应的代码。

例如:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <Button
          android:text="Button"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:id="@+id/button"
          android:layout_weight="1"
          android:onClick="onButtonClicked"/>
</LinearLayout>

这里我们给根布局 LinearLayout 设置了 tools:context = ".MainActivity",当我们使用 Android Studio 的快速修复功能时,则会关联相关的 Activity 进行提示:


Paste_Image.png

tools:layout

适用于 <fragment>

该属性用来定义需要在 fragment 内进行绘制的布局 layout ,从而在布局预览界面预览 fragment 的显示视图。

例如:

<fragment android:name="com.example.master.ItemListFragment"
    tools:layout="@layout/list_content" />

tools:listitem / tools:listheader / tools:listfooter

适用于 <AdapterView> 还有 <ListView> 的子类

我们知道,在编写列表的时候,列表的 item 布局都是在 adapter 的 getView 里通过代码来进行设置的,在非运行时的环境下,无法看到列表的直接预览效果。

这几个属性便提供了这样的功能,通过直接设置对应的 layout 布局,我们可以在开发工具的布局预览界面直接看到显示效果:

<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:listitem="@layout/sample_list_item"
    tools:listheader="@layout/sample_list_header"
    tools:listfooter="@layout/sample_list_footer" />

tools:showIn

适用于被 <include> 标签引用的布局根 <view>

假设 TextView 在 activity_main 布局中被 <include> 引用了,此时如果通过 tools:showIn 指向 activity_main, 则此时在布局预览界面能看到 TextView 在 activity_main 中的显示效果。

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:text="@string/hello_world"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    tools:showIn="@layout/activity_main" />

tools:menu

适用于部分根 <view>

这个属性用来指定需要在 app bar 中显示的 menu 布局,可以使用逗号分隔符来指定多个 menu 布局。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:menu="menu1,menu2" />

不过目前在 toolbar 下测试并未有效,如果有小伙伴知道该属性具体如何使用的,欢迎在评论中留言哈。


资源筛减属性(Resource shrinking attributes)

该类型属性允许你启用严格关联检测

并且决定在项目构建的时候是否保留或丢弃指定的资源文件。

使用该属性需要在 build.gradle 中设置 shinkResourcestrue 来开启资源压缩功能。

开启资源压缩后,在代码中或资源文件中未被引用的资源会在构建过程中被移除。

android {
    ...
    buildTypes {
        release {
            shrinkResources true
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    'proguard-rules.pro'
        }
    }
}

tools:shrinkMode

适用于 <resources> 资源标签

该属性允许你指定构建工具是否使用 "safe mode" 安全模式 (该模式会保留所有明确引用的资源以及可能被 [Resources.getIdentifier()
](https://developer.android.google.cn/reference/android/content/res/Resources.html#getIdentifier(java.lang.String, java.lang.String, java.lang.String))动态引用的资源)

或是 "strict mode" 严格模式 (该模式只保留在代码或者资源文件中明确引用的资源)

默认情况下 shrinkMode="safe",如果需要使用严格模式,则在 <resources> 中设置 tools:shrinkMode="strict"

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:shrinkMode="strict" />

tools:keep

适用于 <resources> 资源标签

当开启了资源压缩(shrinking resource)功能时,这个属性允许你指定哪些资源需要被保留。

因为开启了资源压缩功能后,未被引用的资源文件会在构建过程中被移除,而部分使用 [Resources.getIdentifier()
](https://developer.android.google.cn/reference/android/content/res/Resources.html#getIdentifier(java.lang.String, java.lang.String, java.lang.String)) 进行引用的资源文件可能被误删。

此时我们可以使用该属性指定哪些资源需要保留,不能被移除:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@layout/used_1,@layout/used_2,@layout/*_3" />

tools:discard

适用于 <resources> 资源标签

当使用资源压缩功能移除没用的资源文件时,有些资源虽然被引用了,但移除对 app 不会产生任何影响,或者因为 Gradle plugin 错误地移除了关联的资源。

此时,我们可以通过这个属性来指定需要移除的资源:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:discard="@layout/unused_1" />
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,568评论 25 707
  • 第一部分 安卓开发中,在写布局代码的时候,AndroidStudio可以看到布局的预览效果。 但是有些效果则必须在...
    zivxia阅读 4,028评论 1 5
  • 第一部分安卓开发中,在写布局代码的时候,ide可以看到布局的预览效果。 但是有些效果则必须在运行之后才能看见,比如...
    o动感超人o阅读 794评论 0 50
  • 第一部分安卓开发中,在写布局代码的时候,ide可以看到布局的预览效果。 一般我们在这样做的时候都告诉自己,没关系,...
    o动感超人o阅读 803评论 0 51
  • 官方中文版原文链接 感谢社区中各位的大力支持,译者再次奉上一点点福利:阿里云产品券,享受所有官网优惠,并抽取幸运大...
    HetfieldJoe阅读 902评论 0 3