android中xml tools属性详解

       Android Studio在tools命名空间中支持一些XML属性来开关设计时功能和编译时行为。当构建应用时,编译工具会删除这些属性从而不会影响apk大小和运行行为。为了使用这些属性,将tools命名空间添加到每个XML文件的根元素,使用方式如下:

1
2
<RootTag xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" >

错误处理属性

       tools属性可以分为两种:一种是影响Lint提示的,一种是关于xml布局设计的。下面介绍Lint相关的属性,帮着过滤lint警告消息。

tools:ignore

目标: 任何元素
使用: Lint

       ignore属性是告诉Lint忽略xml中的某些警告,这个属性接收逗号分隔的lint问题ID列表。

       假设我们有这样的一个ImageView:

1
2
3
4
5
6
7
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_main"
android:layout_marginTop="@dimen/margin_main"
android:scaleType="center"
android:src="@drawable/divider" />

       Lint会提示该ImageView缺少android:contentDescription属性。我们可以使用tools:ignore来忽略这个警告:

1
2
3
4
5
6
7
8
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_main"
android:layout_marginTop="@dimen/margin_main"
android:scaleType="center"
android:src="@drawable/divider"
tools:ignore="contentDescription" />

tools:targetApi

目标: 任何元素
使用: Lint

       这个属性功能与Java代码中的@TargetApi注解相同:对元素指定支持的API级别。它告知tools,元素只用于指定的或更高的API级别。如果元素或它的属性在指定的minSdkVersion API级别不适用,它将停止lint产生警告。 假设minSdkLevel 15,而你使用了api21中的控件比如RippleDrawable:

1
2
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/accent_color" />

则Lint会提示警告。为了不显示这个警告,可以:

1
2
3
4
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:color="@color/accent_color"
tools:targetApi="LOLLIPOP" />

tools:locale(本地语言)属性

目标: <resources>
使用: Lint, Android Studio编辑器

       通知tools给定<resources>元素的默认语言/区域是什么,来避免拼写检查器的警告。该值必须是有效的区域设置限定符。

       默认情况下res/values/strings.xml中的字符串会执行拼写检查,如果不是英语,会提示拼写错误,会显示如下的排版警告:

Language typos warnings

       可在values/strings.xml文件中添加指定默认字符串语言来告诉studio本地语言是西班牙语而不是英语,就不会有提示了。

1
2
3
4
5
6
7
8
<resources
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:locale="es">

<!-- Your strings go here -->

</resources>

ps:关于忽略Lint的属性,并不影响编译。

设计时视图属性

       以下属性定义了布局特性,这些特性只在Android Studio布局预览时可见。

tools: instead of android

目标: <View>
使用: Android Studio布局编辑器

       在布局预览中,使用前置tools:插入例子数据代替带属性android:。在开发期希望开到布局预览可以使用这个属性。

       例如,安卓开发中,在写布局代码的时候,ide可以看到布局的预览效果。但是有些效果则必须在运行之后才能看见,比如这种情况:TextView在xml中没有设置任何字符,而是在activity中设置了text。因此为了在ide中预览效果,你必须在xml中为TextView控件设置android:text属性。

1
2
3
4
5
6
7
<TextView
android:id="@+id/text_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Title"
android:layout_margin="@dimen/main_margin"
android:text="I am a title" />

       一般我们在这样做的时候都告诉自己,没关系,等写完代码我就把这些东西一并删了。但是你可能会忘,以至于在最终产品中也会有这样的代码。

       以上的情况是可以避免的,我们使用tools命名空间以及其属性来解决这个问题。

1
xmlns:tools="http://schemas.android.com/tools"

       tools可以告诉Android Studio,哪些属性在运行的时候是被忽略的,只在设计布局的时候有效。比如我们要让android:text属性只在布局预览中有效可以这样:

1
2
3
4
5
6
7
<TextView
android:id="@+id/text_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Title"
android:layout_margin="@dimen/main_margin"
tools:text="I am a title" />

        tools可以覆盖android的所有标准属性(无法覆盖自定义属性),将android:换成tools:即可。同时在运行的时候就连tools:本身都是被忽略的,不会被带进apk中。

tools:context

目标: 任何根<View>
使用: Lint, Android Studio布局编辑器

       这个属性声明布局默认关联的Activity。这使得需要知晓Activity的功能在编辑器或布局预览可用。context属性其实正式的称呼是activity属性,有了这个属性,ide就知道在预览布局的时候该采用什么样的主题。同时它还可以在android studio的java代码中帮助找到相关的文件(Go to Related files)

Go to Related files

       该属性的值是activity的完整包名。

1
2
3
4
5
6
7
8
9
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.android.example.MainActivity">
</LinearLayout>

tools:layout

目标: <fragment>
使用: Android Studio布局编辑器

       这个属性声明哪个布局在布局预览时画到fragment中。

       例如:tools:layout告诉ide,Fragment在程序预览的时候该显示成什么样。

1
2
3
4
5
6
7
8
9
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/item_list"
android:name="com.example.fragmenttwopanel.ItemListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
tools:layout="@android:layout/list_content" />

tools的layout属性

tools:listitem / tools:listheader / tools:listfooter

目标: <AdapterView> (<ListView>的子类)
使用: Android Studio布局编辑器

       这个属性指定在布局预览中显示列表的项,头部和尾部的布局。

       顾名思义就是在ListView ExpandableListView等的预览效果中添加头部、尾部以及子item的预览布局。

1
2
3
4
5
6
7
<GridView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:listheader="@layout/list_header"
tools:listitem="@layout/list_item"
tools:listfooter="@layout/list_footer" />

       注意: 这个属性在Android Studio 2.2对ListView不工作,但在2.3中解决了(问题215172),RecyclerView 没有 header 或 footer 属性,无法使用。

tools:showIn

目的: 布局中的任何根<View>引用<include>
使用: Android Studio布局编辑器

       允许指定一个布局就像include那样,这样可以预览这个文件就像他嵌入到父布局中。

       该属性设置于一个被其他布局<include>的布局的根元素上。这让您可以指向包含此布局的其中一个布局,在设计时这个被包含的布局会带着周围的外部布局被渲染。这将允许您“在上下文中”查看和编辑这个布局。需要 Studio 0.5.8 或更高版本。例如:

1
2
3
4
5
6
<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" />

       现在布局预览显示这个TextView布局。

tools:menu

目的: 任何根<View>
使用: Android Studio布局编辑器

       告诉IDE 在预览窗口中使用哪个菜单,这个菜单将显示在layout的根节点上(actionbar的位置)。

tools的menu属性

       其实预览窗口非常智能,如果布局和一个activity关联(指上面所讲的用tools:context关联)它将会自动查询相关activity的onCreateOptionsMenu方法中的代码,以显示菜单。而menu属性则可以覆盖这种默认的行为。

       你还可以为menu属性定义多个菜单资源,不同的菜单资源之间用逗号隔开。

1
tools:menu="menu_main,menu_edit"

       如果你不希望在预览图中显示菜单则:

1
tools:menu=""

       最后需要注意,当主题为Theme.AppCompat时,这个属性不起作用。

tools:actionBarNavMode

       这个属性告诉ide app bar(Material中对actionbar的称呼)的显示模式,其值可以是

  • standard
  • tabs
  • list
1
2
3
4
5
6
<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:actionBarNavMode="tabs" />

       同样的,当主题是Theme.AppCompat (r21+, at least) 或者Theme.Material,或者使用了布局包含Toolbar的方式。该属性也不起作用,只有holo主题才有效。

资源压缩属性

       以下属性允许启用严格引用检查,并声明在使用资源缩减时是保留还是丢弃某些资源。

       为了启动资源压缩,在build.gradle文件中设置shrinkResources为true。

1
2
3
4
5
6
7
8
9
10
11
android {
...
buildTypes {
release {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}

tools:shrinkMode

目标: <resources>
使用: 带资源压缩的构建工具

       这个属性允许你指定构建工具是否使用“安全模式”或“严格模式”。

       模式使用安全模式(shrinkMode=”safe”)。为了使用严格模式,添加shrinkMode=”strict”到<resources>标签,如下所示:

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

       当启用严格模式,需要使用tools:keep来保持那些真实需要但被删除的资源,使用tools:discard来明确删除更多资源。

tools:keep

目标: <resources>
使用: 带资源压缩的构建工具

       当使用资源压缩来删除无用资源时,这个属性允许保持指定资源。

       为了使用它,在资源目录创建一个带<resources>标签的xml文件,由tools:keep属性指定每个要保持的资源并以逗号分隔。

1
2
3
<?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>
使用: 带资源压缩的构建工具

       当使用资源压缩来删除无用资源时,这个资源允许手动指定要丢弃的资源。

       为了使用它,在资源目录创建一个带<resources>标签的xml文件,由tools:discard属性指定每个要丢弃的资源并以逗号分隔。

1
2
3
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:discard="@layout/unused_1" />

参考资料:
lihenair [译]Android Tools属性
lovexiaov [译]精通 Android 中的 tools 命名空间

Fork me on GitHub