android tools属性引用
利用tools命名空间,android studio支持很多XML属性,当构建app时这些属性会被擦除,对APK的大小和运行时行为没有任何影响。请看官网。
tools属性大致可以分为三类:1,错误处理属性,这样就会影响到Lint的提示;2,资源shrink属性,影响到资源以何种方式shrink;3,布局编辑器设计时View属性。
1 错误处理属性
- tools:ignore
任何元素都可以使用这个属性,比如strings.xml里面的string元素,我们可以忽略掉MissingTranslation这个错误属性:
<string name="show_all_apps" tools:ignore="MissingTranslation">All</string>
再比如对于下面代码中的ImageView元素,如果我们没有添加tools:ignore这个属性,那么Lint会提示该ImageView缺少android:contentDescription属性,tools:ignore="contentDescription"可以忽略这个警告:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/divider"
tools:ignore="contentDescription" />
- tools:targetApi
任何元素都可以使用这个属性,它和java代码中的注解@TargetApi是一样的:它指定了当前元素支持API级别,属性值既可以是数字也可以是代码名字。
这样的话,即使指定的minSdkVersion
不支持当前元素,那么Lint也不会警告。比如设置的minSdkVersion=12
,但是要使用GridLayout
的话,就必须加上tools:targetApi="14"
:
<GridLayout android:layout_width="match_parent"
android:layout_height="match_parent"
tools:targetApi="ice_cream_sandwich"/>
- tools:locale
只有resources标签才能使用这个属性。resources默认的语言和区域是英语,会进行拼写检查,而这个属性过指定了resources的语言和区域,当然属性值必须是合法的locale qualifier。
比如你可以指定values/strings.xml
文件的默认语言是西班牙语而不是英语:
<resources xmlns:tools="http://schemas.android.com/tools" tools:locale="es">
2 资源压缩模式
当使用resource shrinking的时候下面的属性指定资源压缩的一些特性。
为了使用资源压缩,请将build.gradle
文件的shrinkResources
属性置为true
,(minifyEnabled
属性是code shrinking代码压缩):
android {
...
buildTypes {
release {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
- tools:shrinkMode
适用对象:<resources>
。指定构建的时候是使用safe mode还是strict mode。safe mode保留所有直接引用的资源和可能动态使用的资源,比如Resources.getIdentifier()方式调用的资源。strict mode只保留直接引用的资源。
默认的安全模式是shrinkMode="safe"
。如果要使用strict mode,可以用下面的代码:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:shrinkMode="strict" />
如果启用了strict mode,可以自定义要保留的资源,如果想要保留或舍弃的特定资源,在您的项目中创建一个包含 <resources> 标记的 XML 文件,并在 tools:keep 属性中指定每个要保留的资源,在tools:discard属性中指定每个要舍弃的资源。这两个属性都接受逗号分隔的资源名称列表。您可以使用星号字符作为通配符。例如:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
tools:discard="@layout/unused2" />
将该文件保存在项目资源中,例如,保存在 res/raw/keep.xml。构建不会将该文件打包到 APK 之中。
更多信息请查看:Shrink your resources。
- tools:keep
适用对象:<resources>
标签。这个属性能够保留特定的资源,比如Resources.getIdentifier())动态使用的资源。用法是可以创建res/raw/keep.xml
文件,内容如下:
<?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插件错误地推断这些资源是被引用的,那么也可以使用这个属性。用法如下:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:discard="@layout/unused_1" />
3 布局编辑器设计时View属性
- tools:替换android:
tools可以覆盖所有的android属性,相信这个是大家用过的最多的,就不说了。
- tools:parentTag
android studio2.2新加了这个属性可以指定merge标签的布局类型,比如:
<merge 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"
tools:parentTag="android.widget.LinearLayout">
</merge>
- tools:context
只有根View才能使用这个属性,它指定了当前布局默认是跟哪个Activity相关联,使得布局获取那个Activity的一些信息比如Activity使用的theme等等,而且当你使用quickfix(mac上的快捷键是alt+enter)给子View添加`onClick事件时,相应的方法代码会插入到这个Activity中。

- tools:itemCount
只有RecyclerView才能使用这个属性。我的android studio版本是3.0.1,布局编辑器中RecyclerView显示的默认个数是10个,这个属性可以改变RecyclerView显示的个数。
- tools:layout
只有fragment标签能用这个属性,在preview窗口中可以预览这个layout的样式。
- tools:listitem / tools:listheader / tools:listfooter
只有AdapterView才能使用这个属性,指定了列表的items、header和footer的布局,不过tools:listitem这个属性RecyclerView也能使用:
<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:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView 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"
tools:showIn="@layout/app_bar_main"
tools:itemCount="32">
</android.support.v7.widget.RecyclerView>
- tools:menu
适用对象:根<View>
。告诉IDE 在预览窗口中使用哪个菜单,这个菜单将显示在layout的根节点上(actionbar的位置)。

preview窗口很智能,如果布局和一个activity关联(通过tools:context指定)它将会自动查询这个activity的onCreateOptionsMenu方法,以显示菜单,而tools:menu属性则可以覆盖这种默认的行为。
属性的值是menu id,还可以有多个,不同的menu id之间用逗号隔开。
需要注意的是,主题为Theme.AppCompat时,这个属性不起作用。
- tools:actionBarNavMode
指定actionbar的显示模式,其值可以是:1. standard、2. tabs、3. list
<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主题才有效。参考
- tools:minValue / tools:maxValue
适用对象:NumberPicker
。预览NumberPicker的最大最小值但是不生效。NumberPicker的maxValue和minValue只能通过代码设置,如果想通过xml设置的话需要另想办法,这里有参考。为什么android studio的xml不支持设置这两个属性呢?我不懂,请大神留言告知。
<NumberPicker xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/numberPicker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:minValue="0"
tools:maxValue="10" />
- tools:openDrawer
适用对象:<DrawerLayout>
。让DrawerLayout打开一个方向。
Constant | Value | Description |
---|---|---|
end | 800005 | Push object to the end of its container, not changing its size. |
left | 3 | Push object to the left of its container, not changing its size. |
right | 5 | Push object to the right of its container, not changing its size. |
start | 800003 | Push object to the beginning of its container, not changing its size. |
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="start" />
- "@tools:sample/*" resources
适用对象:所有支持文本和图片的View。这个属性相当于给View加了个placeholder,比如:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="@tools:sample/lorem" />
下面的表格描述了所有能给View使用的placeholder:
Attribute value | Description of placeholder data |
---|---|
@tools:sample/full_names | Full names that are randomly generated from the combination of @tools:sample/first_names and @tools:sample/last_names. |
@tools:sample/first_names | Common first names. |
@tools:sample/last_names | Common last names. |
@tools:sample/cities | Names of cities from across the world. |
@tools:sample/us_zipcodes | Randomly generated US zipcodes. |
@tools:sample/us_phones | Randomly generated phone numbers with the following format: (800) 555-xxxx. |
@tools:sample/lorem/random | Placeholder text that is derived from Latin. |
@tools:sample/date/day_of_week | Randomized dates and times for the specified format. |
@tools:sample/date/ddmmyy | 同上 |
@tools:sample/date/mmddyy | 同上 |
@tools:sample/date/hhmm | 同上 |
@tools:sample/date/hhmmss | 同上 |
@tools:sample/avatars | Vector drawables that you can use as profile avatars. |
@tools:sample/backgrounds/scenic | Images that you can use as backgrounds. |
这些placeholder资源不会打进APK包里面,因此不用担心会增加app体积,只是方便在preview窗口查看预览效果。
下面举两个例子。
- 例子1 原文链接
比如下面的代码定义了一个RecyclerView,它的tools:listitem="@layout/item_part1"
:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/item_part1" />
再来看下item_part1.xml的代码:
//item_part1.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/avatar"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:contentDescription="@null"
app:layout_constraintDimensionRatio="h,1:1"
app:layout_constraintEnd_toStartOf="@id/name"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/name"
tools:src="@tools:sample/avatars"/>
<TextView
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:layout_constraintBottom_toTopOf="@+id/city"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="5"
app:layout_constraintStart_toEndOf="@id/avatar"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="@tools:sample/full_names"/>
<TextView
android:id="@+id/city"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:layout_constraintBottom_toTopOf="@id/description"
app:layout_constraintEnd_toStartOf="@id/date"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toEndOf="@id/avatar"
app:layout_constraintTop_toBottomOf="@+id/name"
tools:text="@tools:sample/cities"/>
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:gravity="end"
app:layout_constraintBaseline_toBaselineOf="@id/city"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/city"
tools:text="@tools:sample/date/ddmmyy"/>
<TextView
android:id="@+id/description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:ellipsize="end"
android:maxLines="3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/avatar"
app:layout_constraintTop_toBottomOf="@+id/city"
tools:text="@tools:sample/lorem/random"/>
</android.support.constraint.ConstraintLayout>
从上面的代码可以看到,RecyclerView的item包含5个元素:头像avatar、名字name、城市city、日期date和描述description。头像avatar使用的属性是tools:src="@tools:sample/avatars"
,名字name使用的属性是tools:text="@tools:sample/full_names"
,城市city使用的属性是tools:text="@tools:sample/cities"
,日期date使用的属性是tools:text="@tools:sample/date/ddmmyy"
,描述description使用的属性是tools:text="@tools:sample/lorem/random"
,最终的preview窗口如图所示:

例子1的 代码地址
- 例子2 原文链接


然后我们创建一个“names”文件,每一行加一个名字:
//ampledata/names
Mark Allison
Sir Reginald Fortescue Crumplington-Smythe
Pablo Diego José Francisco de Paula Juan Nepomuceno María de los Remedios Cipriano de la Santísima Trinidad Ruiz y Picasso
Millicent Marbles
然后我们把原来的placeholder属性tools:text="@tools:sample/full_names"
替换一下:
<TextView
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:layout_constraintBottom_toTopOf="@+id/city"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="5"
app:layout_constraintStart_toEndOf="@id/avatar"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="@sample/names" />
自定义完名字name,我们再来自定义头像avatar。在sampledata目录下创建avatars目录:

代码使用下面的方式调用:
<ImageView
android:id="@+id/avatar"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:contentDescription="@null"
app:layout_constraintDimensionRatio="h,1:1"
app:layout_constraintEnd_toStartOf="@id/name"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/name"
tools:src="@sample/avatars" />
再来看preview窗口,我们添加了四个头像的VectorDrawable但是preview窗口只显示了2个:




json文件内容如下:
{
"data": [
{
"city": "Hemel Hempstead, Hertfordshire, UK",
"avatar": "@sample/avatars"
},
{
"city": "Brokenwind, Aberdeenshire, UK",
"avatar": "@sample/avatars"
},
{
"city": "Málaga, España",
"avatar": "@sample/avatars"
},
{
"city": "Batchelors Bump, Essex, UK",
"avatar": "@sample/avatars"
}
]
}
然后我们的头像avatar和城市city就能使用这个json文件来引用:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/avatar"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:contentDescription="@null"
app:layout_constraintDimensionRatio="h,1:1"
app:layout_constraintEnd_toStartOf="@id/name"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/name"
tools:src="@sample/users.json/data/avatar"/>
<TextView
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:layout_constraintBottom_toTopOf="@+id/city"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="5"
app:layout_constraintStart_toEndOf="@id/avatar"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="@sample/names"/>
<TextView
android:id="@+id/city"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:layout_constraintBottom_toTopOf="@id/description"
app:layout_constraintEnd_toStartOf="@id/date"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toEndOf="@id/avatar"
app:layout_constraintTop_toBottomOf="@+id/name"
tools:text="@sample/users.json/data/city"/>
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:gravity="end"
app:layout_constraintBaseline_toBaselineOf="@id/city"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/city"
tools:text="@tools:sample/date/ddmmyy"/>
<TextView
android:id="@+id/description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:ellipsize="end"
android:maxLines="3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/avatar"
app:layout_constraintTop_toBottomOf="@+id/city"
tools:text="@tools:sample/lorem/random"/>
</android.support.constraint.ConstraintLayout>
最终的preview窗口:

例子2的 代码地址