码个蛋(codeegg)第 769 次推文

作者: 水月沐风

原文: https://juejin.im/post/5d500b1a6fb9a06b1417d5c9

前言

日常开发过程中,我们都会遇到这样一种场景:我们写出的 UI 效果在对接数据之前需要提前进行预览,进而调整 UI 细节和排版问题。我们一般的做法是什么样的?

如果存在像 TextView 或者 ImageView 这种基础控件,你是不是还在通过诸如

androandroid应用运维(自从用了AndroidTools我再也没加过班)(1)id:text="xxx"androandroid应用运维(自从用了AndroidTools我再也没加过班)(2)id:src="http://img.studyofnet.com@drawable/xxx"的方式来测试和预览UI效果?当然你肯定也会遇到这些“脏数据”给你带来的困扰:测试的时候某些地方出现了本不该出现的数据,事后可能一拍脑门才发现,原来是布局中控件预览数据没有清除导致的。

如果是 RecyclerView,在后台接口尚能测试的情况下,你是否又要自己生成“假数据”并手写 Adapter 呢?这时候你不禁会问:有没有一种方法,既能够做到布局时预览数据方便排版,又能够在对接真实数据运行后动态替换和移除这些无关数据呢?

铛铛铛铛!Android 的 Tools attributes应运而生。

老规矩,我们先来看一个效果:

android应用运维(自从用了AndroidTools我再也没加过班)(3)

What?你在耍我吗?这么简单的列表拿出来干嘛?哈哈,客观不要着急。这个并不难实现,倘若我说这里并没有写一行 Java 或者 Kotlin 代码就实现了此效果,而只是在布局页面预览,你敢信吗?上图只是冰山一角,下面这张图才是全貌:

android应用运维(自从用了AndroidTools我再也没加过班)(4)

下面会带大家一步步实现上述功能,首先,让我们从头说起。

认识 Tools attributes

Tools attributes 即以 tools开始的命名空间,举个我们最常见到的例子:

<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="android应用运维(自从用了AndroidTools我再也没加过班)(5)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(6).com/apk/res/android" xmlns:tools="android应用运维(自从用了AndroidTools我再也没加过班)(7)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(8).com/tools" xmlns:android应用运维(自从用了AndroidTools我再也没加过班)(9)app="android应用运维(自从用了AndroidTools我再也没加过班)(10)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(11).com/apk/res-auto" androandroid应用运维(自从用了AndroidTools我再也没加过班)(12)id:layout_width="match_parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(13)id:layout_height="match_parent" tools:context=".MainActivity"></android.support.constraint.ConstraintLayout>

大家肯定平时都会见到 tools:context=".XXXActivity" 这个系统默认为我们生成的配置。一般来说,只有根视图才能使用这个属性,它指定了当前布局默认是与哪个 Activity 相关联,使得布局能够获取到绑定 Activity 的一些信息,比如 Theme 等等,而且当你在布局中给子 View 添加 onClick事件时,相应的方法代码会插入到这个 Activity 中。Android studio 支持很多在 XML 文件中以 tools 为命名空间的属性,当构建 android应用运维(自从用了AndroidTools我再也没加过班)(14)App 时这些属性会被擦除,对 APK 的大小和运行时行为没有任何影响,这也就是我们文章最初想要的结果。

细说 Tools attributes

在具体介绍 Tools attributes 之前,我们需要先了解如何引入 Tools 的命名空间并使用,很简单,只需要在 XML 布局文件的根元素中添加即可:

<RootTag xmlns:android="android应用运维(自从用了AndroidTools我再也没加过班)(15)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(16).com/apk/res/android" xmlns:tools="android应用运维(自从用了AndroidTools我再也没加过班)(17)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(18).com/tools" >

这些工具属性大概可以分为以下三类:

1. Error handling attributes

即错误和警告处理属性。

这类属性常被用来规避被 lint检查出的一些错误提示以及警告。下面让我们看一些常见的例子:

1.1 tools:ignore

主要用来忽略一些 lint 产生的警告信息,并支持一些属性,例如:

<resources xmlns:tools="android应用运维(自从用了AndroidTools我再也没加过班)(19)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(20).com/tools"> <string name="android应用运维(自从用了AndroidTools我再也没加过班)(21)app_name">ConstraintSample</string> <string name="header_image_string" tools:ignore="Mandroid应用运维(自从用了AndroidTools我再也没加过班)(22)issingTranslation">header image</string></resources>

这个对于 Android studio 升级到 3.0 以上的小伙伴来说应该是很常见了,如果我们项目中涉及到国际化支持,那么编译器就会提示我们为每一种语言做适配,不能“厚此薄彼”,如果我们某些 string 只需要支持一种语言,只需要像上面那样添加 tools:ignore="Mandroid应用运维(自从用了AndroidTools我再也没加过班)(23)issingTranslation即可。

相似的例子还可以在使用 ImageView 的时候看到:

<ImageView androandroid应用运维(自从用了AndroidTools我再也没加过班)(24)id:layout_width="wrap_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(25)id:layout_height="wrap_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(26)id:src="http://img.studyofnet.com@drawable/ic_person_off" tools:ignore="contentDescription" />

1.2 tools:targetApi

这个属性的功能和 Java 代码中的注解 @TargetApi是一样的:它指定了当前控件或元素支持的 API 级别,属性值可以是 API Code 名或者 API 常数值,它支持一切属性。如:我们都知道,androandroid应用运维(自从用了AndroidTools我再也没加过班)(27)id:elevation属性是在 API 21 版本以上才支持的,所以我们可以通过以下代码规避 lint的警告:

<Button androandroid应用运维(自从用了AndroidTools我再也没加过班)(28)id:layout_width="wrap_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(29)id:layout_height="wrap_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(30)id:elevation="4dp" tools:targetApi="lollipop"/>

1.3 tools:locale

这个属性主要用在 <resource>标签内,用来指定当前资源中默认为哪种语言和区域,进而规避语言拼写的检测,比如你可以指定 values/strings.xml文件的默认语言是西班牙语而不是英语:

<resources xmlns:tools="android应用运维(自从用了AndroidTools我再也没加过班)(31)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(32).com/tools" tools:locale="es">

2. Resource shrinking attributes

即资源压缩属性。下面简单说明一下。

我们可以通过 tools:shrinkMode 和 tools:keep 属性来分别指定资源压缩的模式和需要保留的不被压缩的资源 ,还可以通过 tools:discard属性来指定需要保留的资源,与 keep功能类似:

<?xml version="1.0" encoding="utf-8"?><resources xmlns:tools="android应用运维(自从用了AndroidTools我再也没加过班)(33)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(34).com/tools" tools:shrinkMode="strict" tools:keep="@layout/activity_video*,@layout/dialog_update_v2" tools:discard="@layout/unused_layout,@drawable/unused_selector" />

下面就到本篇文章的重头戏了,注意,前方高能来袭!

3. Design-time View Attributes

这就是我们先前效果图中的重要功臣了,即:布局设计时的控件属性。这类属性主要作用于 View 控件,如上文所说的 tools:context 就是“成员”之一,下面我们来介绍其他重要成员。

在此之前,我们需要先揭开 tools 命名空间的另一层神秘面纱:tools:可以替换任何以 androandroid应用运维(自从用了AndroidTools我再也没加过班)(35)id:为前缀的属性,并为其设置样例数据(sample data)。当然,正如我们前面所说,tools 属性只能在布局编辑期间有效,android应用运维(自从用了AndroidTools我再也没加过班)(36)App真正运行后就毫无意义了,所以,我们就可以像下面这样来在运行前预览布局效果:

android应用运维(自从用了AndroidTools我再也没加过班)(37)

上图对应的布局文件为:

Card_item_layout.xml

<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android应用运维(自从用了AndroidTools我再也没加过班)(38)app="android应用运维(自从用了AndroidTools我再也没加过班)(39)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(40).com/apk/res-auto" xmlns:tools="android应用运维(自从用了AndroidTools我再也没加过班)(41)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(42).com/tools" xmlns:android="android应用运维(自从用了AndroidTools我再也没加过班)(43)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(44).com/apk/res/android" androandroid应用运维(自从用了AndroidTools我再也没加过班)(45)id:background="@androandroid应用运维(自从用了AndroidTools我再也没加过班)(46)id:color/white" androandroid应用运维(自从用了AndroidTools我再也没加过班)(47)id:clickable="true" androandroid应用运维(自从用了AndroidTools我再也没加过班)(48)id:focusable="true" androandroid应用运维(自从用了AndroidTools我再也没加过班)(49)id:foreground="?attr/selectableItemBackground" androandroid应用运维(自从用了AndroidTools我再也没加过班)(50)id:layout_width="match_parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(51)id:layout_height="wrap_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(52)id:layout_marginStart="2dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(53)id:layout_marginEnd="2dp" tools:targetApi="m" tools:ignore="UnusedAttribute"> <ImageView android:id="@ id/card_item_avatar" androandroid应用运维(自从用了AndroidTools我再也没加过班)(54)id:layout_width="38dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(55)id:layout_height="38dp" android应用运维(自从用了AndroidTools我再也没加过班)(56)app:layout_constraintStart_toStartOf="parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(57)id:layout_marginStart="16dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(58)id:layout_marginTop="16dp" android应用运维(自从用了AndroidTools我再也没加过班)(59)app:layout_constraintTop_toTopOf="parent" android应用运维(自从用了AndroidTools我再也没加过班)(60)app:layout_constraintBottom_toBottomOf="parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(61)id:layout_marginBottom="16dp" android应用运维(自从用了AndroidTools我再也没加过班)(62)app:layout_constraintVertical_bias="0.0" tools:ignore="ContentDescription" tools:srcCompat="@drawable/user_other"/> <TextView android:id="@ id/card_item_username" androandroid应用运维(自从用了AndroidTools我再也没加过班)(63)id:layout_width="wrap_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(64)id:layout_height="wrap_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(65)id:layout_marginTop="16dp" android应用运维(自从用了AndroidTools我再也没加过班)(66)app:layout_constraintTop_toTopOf="parent" android应用运维(自从用了AndroidTools我再也没加过班)(67)app:layout_constraintStart_toStartOf="@ id/card_item_title" android应用运维(自从用了AndroidTools我再也没加过班)(68)app:layout_constraintEnd_toEndOf="@ id/card_item_title" android应用运维(自从用了AndroidTools我再也没加过班)(69)app:layout_constraintHorizontal_bias="0.0" androandroid应用运维(自从用了AndroidTools我再也没加过班)(70)id:textSize="12sp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(71)id:textColor="@color/username_text_color" androandroid应用运维(自从用了AndroidTools我再也没加过班)(72)id:layout_marginEnd="16dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(73)id:paddingEnd="16dp" tools:text="水月沐风" /> <TextView android:id="@ id/card_item_title" androandroid应用运维(自从用了AndroidTools我再也没加过班)(74)id:layout_width="wrap_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(75)id:layout_height="wrap_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(76)id:textSize="16sp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(77)id:textColor="@color/title_text_color" android应用运维(自从用了AndroidTools我再也没加过班)(78)app:layout_constraintStart_toEndOf="@ id/card_item_avatar" androandroid应用运维(自从用了AndroidTools我再也没加过班)(79)id:layout_marginStart="12dp" android应用运维(自从用了AndroidTools我再也没加过班)(80)app:layout_constraintTop_toBottomOf="@ id/card_item_username" androandroid应用运维(自从用了AndroidTools我再也没加过班)(81)id:layout_marginTop="8dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(82)id:maxLines="1" tools:text="今天上海的夜色真美!"/> <TextView android:id="@ id/card_item_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(83)id:layout_width="0dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(84)id:layout_height="wrap_content" android应用运维(自从用了AndroidTools我再也没加过班)(85)app:layout_constraintStart_toStartOf="parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(86)id:layout_marginTop="24dp" android应用运维(自从用了AndroidTools我再也没加过班)(87)app:layout_constraintTop_toBottomOf="@ id/card_item_avatar" android应用运维(自从用了AndroidTools我再也没加过班)(88)app:layout_constraintBottom_toBottomOf="parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(89)id:layout_marginBottom="16dp" android应用运维(自从用了AndroidTools我再也没加过班)(90)app:layout_constraintVertical_bias="1.0" androandroid应用运维(自从用了AndroidTools我再也没加过班)(91)id:maxLines="3" androandroid应用运维(自从用了AndroidTools我再也没加过班)(92)id:ellipsize="end" androandroid应用运维(自从用了AndroidTools我再也没加过班)(93)id:textColor="@color/content_text_color" androandroid应用运维(自从用了AndroidTools我再也没加过班)(94)id:textStyle="normal" android应用运维(自从用了AndroidTools我再也没加过班)(95)app:layout_constraintEnd_toEndOf="@ id/card_item_bottom_border" androandroid应用运维(自从用了AndroidTools我再也没加过班)(96)id:layout_marginEnd="16dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(97)id:layout_marginStart="16dp" android应用运维(自从用了AndroidTools我再也没加过班)(98)app:layout_constraintHorizontal_bias="0.0" tools:text="人生若只如初见,何事秋风悲画扇..."/> <ImageView android:id="@ id/card_item_poster" androandroid应用运维(自从用了AndroidTools我再也没加过班)(99)id:layout_width="0dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(100)id:layout_height="200dp" android应用运维(自从用了AndroidTools我再也没加过班)(101)app:layout_constraintStart_toStartOf="parent" android应用运维(自从用了AndroidTools我再也没加过班)(102)app:layout_constraintTop_toBottomOf="@ id/card_item_content" android应用运维(自从用了AndroidTools我再也没加过班)(103)app:layout_constraintEnd_toEndOf="parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(104)id:layout_marginEnd="16dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(105)id:scaleType="centerCrop" androandroid应用运维(自从用了AndroidTools我再也没加过班)(106)id:layout_marginTop="8dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(107)id:layout_marginStart="16dp" android应用运维(自从用了AndroidTools我再也没加过班)(108)app:layout_constraintBottom_toBottomOf="parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(109)id:layout_marginBottom="16dp" android应用运维(自从用了AndroidTools我再也没加过班)(110)app:layout_constraintVertical_bias="0.0" tools:ignore="ContentDescription" androandroid应用运维(自从用了AndroidTools我再也没加过班)(111)id:vandroid应用运维(自从用了AndroidTools我再也没加过班)(112)isibility="vandroid应用运维(自从用了AndroidTools我再也没加过班)(113)isible" tools:src="http://img.studyofnet.com@drawable/shanghai_night"/> <View android:id="@ id/card_item_bottom_border" androandroid应用运维(自从用了AndroidTools我再也没加过班)(114)id:layout_width="0dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(115)id:layout_height="2dp" android应用运维(自从用了AndroidTools我再也没加过班)(116)app:layout_constraintTop_toBottomOf="@ id/card_item_poster" androandroid应用运维(自从用了AndroidTools我再也没加过班)(117)id:background="#ffededfe" android应用运维(自从用了AndroidTools我再也没加过班)(118)app:layout_constraintEnd_toEndOf="parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(119)id:layout_marginTop="16dp" android应用运维(自从用了AndroidTools我再也没加过班)(120)app:layout_constraintStart_toStartOf="parent"/> <TextView androandroid应用运维(自从用了AndroidTools我再也没加过班)(121)id:layout_width="wrap_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(122)id:layout_height="wrap_content" android:id="@ id/card_item_date" androandroid应用运维(自从用了AndroidTools我再也没加过班)(123)id:layout_marginTop="16dp" android应用运维(自从用了AndroidTools我再也没加过班)(124)app:layout_constraintTop_toTopOf="parent" android应用运维(自从用了AndroidTools我再也没加过班)(125)app:layout_constraintEnd_toEndOf="parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(126)id:layout_marginEnd="16dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(127)id:textColor="@color/date_text_color" androandroid应用运维(自从用了AndroidTools我再也没加过班)(128)id:textSize="12sp" tools:text="2019-08-10"/></android.support.constraint.ConstraintLayout>

通过上面代码我们可以发现:通过 对 TextView使用tools:text属性代替androandroid应用运维(自从用了AndroidTools我再也没加过班)(129)id:text就可以实现文本具体效果的预览,然而这项设置并不会对我们 android应用运维(自从用了AndroidTools我再也没加过班)(130)App 实际运行效果产生影响。

同理,通过将 tools:src作用于ImageView也可以达到预览图片的效果。

此外,我们还可以对其他以 androandroid应用运维(自从用了AndroidTools我再也没加过班)(131)id:为前缀的属性进行预览而不影响实际运行的效果,例如:上面布局代码中的底部分割线<View>,我们想将其在 android应用运维(自从用了AndroidTools我再也没加过班)(132)App 实际运行的时候隐藏掉,但我们还是需要知道它的预览效果和所占高度:

<View android:id="@ id/card_item_bottom_border" androandroid应用运维(自从用了AndroidTools我再也没加过班)(133)id:layout_width="0dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(134)id:layout_height="2dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(135)id:vandroid应用运维(自从用了AndroidTools我再也没加过班)(136)isibility="gone" tools:vandroid应用运维(自从用了AndroidTools我再也没加过班)(137)isibility="vandroid应用运维(自从用了AndroidTools我再也没加过班)(138)isible" tools:layout_height="8dp" android应用运维(自从用了AndroidTools我再也没加过班)(139)app:layout_constraintTop_toBottomOf="@ id/card_item_poster" androandroid应用运维(自从用了AndroidTools我再也没加过班)(140)id:background="#ffededfe" android应用运维(自从用了AndroidTools我再也没加过班)(141)app:layout_constraintEnd_toEndOf="parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(142)id:layout_marginTop="16dp" android应用运维(自从用了AndroidTools我再也没加过班)(143)app:layout_constraintStart_toStartOf="parent"/>

如上所示,通过 tools:vandroid应用运维(自从用了AndroidTools我再也没加过班)(144)isibility 和 tools:layout_height 就可以仅在布局预览情况下改变 View 的状态和高度。虽然上述情况比较少用,但是希望大家也能够知道,tools: 可以替代所有 androandroid应用运维(自从用了AndroidTools我再也没加过班)(145)id: 修饰的属性。

下面再列举一些其他会常用到的属性。

  • tools:layout

    这个属性只能用于 fragment控件中,

    如果我们的 activity布局文件中声明了 <fragment>控件,我们就可以通过 tools:layout=”@layout/fragment_main”来在当前 activity布局中预览 fragment中的布局效果。

  • tools:showIn

    这个属性就比较好玩了,它可以指定其他布局文件像 <include>组件一样在当前布局文件中使用和预览 <include>控件的实际效果。

    例如,我们 card_item_layout.xml 作为 showIn的对象给 show_in_layout.xml 布局使用,然后我就可以看到 show_in_layout.xml 中如下效果:

android应用运维(自从用了AndroidTools我再也没加过班)(146)

  • tools:menu

    这个属性可以给当前布局预览器的 Toolbar 添加多个菜单项,但仅限于布局文件的根节点元素。如:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="android应用运维(自从用了AndroidTools我再也没加过班)(147)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(148).com/apk/res/android" xmlns:tools="android应用运维(自从用了AndroidTools我再也没加过班)(149)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(150).com/tools" androandroid应用运维(自从用了AndroidTools我再也没加过班)(151)id:orientation="vertical" androandroid应用运维(自从用了AndroidTools我再也没加过班)(152)id:layout_width="match_parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(153)id:layout_height="match_parent" tools:menu="menu1,menu2" />

  • tools:maxValue | tools:minValue

    这两个属性仅用于 <NumberPicker>,可以在预览时指定其最大值和最小值:

    <NumberPicker xmlns:android="android应用运维(自从用了AndroidTools我再也没加过班)(154)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(155).com/apk/res/android" xmlns:tools="android应用运维(自从用了AndroidTools我再也没加过班)(156)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(157).com/tools" android:id="@ id/numberPicker" androandroid应用运维(自从用了AndroidTools我再也没加过班)(158)id:layout_width="match_parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(159)id:layout_height="wrap_content" tools:minValue="0" tools:maxValue="10" />

  • tools:landroid应用运维(自从用了AndroidTools我再也没加过班)(160)istitem | tools:landroid应用运维(自从用了AndroidTools我再也没加过班)(161)istheader | tools:landroid应用运维(自从用了AndroidTools我再也没加过班)(162)istfooter | tools:landroid应用运维(自从用了AndroidTools我再也没加过班)(163)istCount

    下面来讲一下列表相关组件的 tools 属性。

    上面四个属性仅用于 <AdapterView>及其子类(如:Landroid应用运维(自从用了AndroidTools我再也没加过班)(164)istView和 RecyclerView)。然而,它们内部仍有一些使用限制:tools:landroid应用运维(自从用了AndroidTools我再也没加过班)(165)istCount仅用于 RecyclerView;tools:landroid应用运维(自从用了AndroidTools我再也没加过班)(166)istheader和 tools:landroid应用运维(自从用了AndroidTools我再也没加过班)(167)istfooter仅限于 Landroid应用运维(自从用了AndroidTools我再也没加过班)(168)istView;至于 tools:landroid应用运维(自从用了AndroidTools我再也没加过班)(169)istitem属性二者皆可用。之前的效果图就是借助于此属性:

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="android应用运维(自从用了AndroidTools我再也没加过班)(170)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(171).com/apk/res/android" xmlns:tools="android应用运维(自从用了AndroidTools我再也没加过班)(172)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(173).com/tools" xmlns:android应用运维(自从用了AndroidTools我再也没加过班)(174)app="android应用运维(自从用了AndroidTools我再也没加过班)(175)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(176).com/apk/res-auto" androandroid应用运维(自从用了AndroidTools我再也没加过班)(177)id:layout_width="match_parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(178)id:layout_height="match_parent" tools:context=".MainActivity" androandroid应用运维(自从用了AndroidTools我再也没加过班)(179)id:background="#ffEBEBEF"> <android.support.v7.widget.Toolbar android:id="@ id/toolbar" androandroid应用运维(自从用了AndroidTools我再也没加过班)(180)id:layout_width="0dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(181)id:layout_height="wrap_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(182)id:background="?attr/colorPrimary" androandroid应用运维(自从用了AndroidTools我再也没加过班)(183)id:theme="?attr/actionBarTheme" androandroid应用运维(自从用了AndroidTools我再也没加过班)(184)id:minHeight="?attr/actionBarSize" android应用运维(自从用了AndroidTools我再也没加过班)(185)app:layout_constraintStart_toStartOf="parent" android应用运维(自从用了AndroidTools我再也没加过班)(186)app:layout_constraintEnd_toEndOf="parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(187)id:elevation="1dp" android应用运维(自从用了AndroidTools我再也没加过班)(188)app:title="@string/android应用运维(自从用了AndroidTools我再也没加过班)(189)app_name" android应用运维(自从用了AndroidTools我再也没加过班)(190)app:layout_constraintTop_toTopOf="parent" android应用运维(自从用了AndroidTools我再也没加过班)(191)app:layout_constraintHorizontal_bias="0.0"/> <android.support.v7.widget.RecyclerView androandroid应用运维(自从用了AndroidTools我再也没加过班)(192)id:layout_width="match_parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(193)id:layout_height="wrap_content" android应用运维(自从用了AndroidTools我再也没加过班)(194)app:layout_constraintStart_toStartOf="parent" android应用运维(自从用了AndroidTools我再也没加过班)(195)app:layout_constraintEnd_toEndOf="parent" android应用运维(自从用了AndroidTools我再也没加过班)(196)app:layout_constraintBottom_toBottomOf="parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(197)id:scrollbars="vertical" android应用运维(自从用了AndroidTools我再也没加过班)(198)app:layout_constraintTop_toBottomOf="@ id/toolbar" android应用运维(自从用了AndroidTools我再也没加过班)(199)app:layout_constraintHorizontal_bias="0.0" android应用运维(自从用了AndroidTools我再也没加过班)(200)app:layout_constraintVertical_bias="0.0" tools:landroid应用运维(自从用了AndroidTools我再也没加过班)(201)istitem="@layout/card_item_layout"/></android.support.constraint.ConstraintLayout>

sample data

即 样本数据功能,可以通过 @tools:sample 来使用该属性,也属于 design-time view attributes。但它并非只是一个属性那么简单,更应该算是一个“工具利器”,所以会将其单独拿出来详细介绍。这个工具是本年度 Google 大会上 Android 开发团队特别介绍的一个新推属性。它有什么用呢?用处大了!先前的布局预览使用的数据都是我们直接在布局控件中注明或者在 strings.xml文件中给出的,这一就会产生一些脏数据,不利于我们后期的处理。而有了 sample data,我们就可以对布局预览器中的 **“样本数据”**进行集中保存和管理了。

一、sample data 的使用

Android studio已为我们提供了以下样本数据,我可以直接拿来使用:

Attribute valueDescription of placeholder data
@tools:sample/full_namesFull names that are randomly generated from android应用运维(自从用了AndroidTools我再也没加过班)(202)the combination of@tools:sample/first_namesand@tools:sample/last_names.
@tools:sample/first_namesCommon first names.
@tools:sample/last_namesCommon last names.
@tools:sample/citiesNames of cities from across android应用运维(自从用了AndroidTools我再也没加过班)(203)the world.
@tools:sample/us_zipcodesRandomly generated US zipcodes.
@tools:sample/us_phonesRandomly generated phone numbers with android应用运维(自从用了AndroidTools我再也没加过班)(204)the following format: (800) 555-xxxx.
@tools:sample/loremPlaceholder text that android应用运维(自从用了AndroidTools我再也没加过班)(205)is derived from Latin.
@tools:sample/date/day_of_weekRandomized dates and times for android应用运维(自从用了AndroidTools我再也没加过班)(206)the specified format.
@tools:sample/date/ddmmyy
@tools:sample/date/mmddyy
@tools:sample/date/hhmm
@tools:sample/date/hhmmss
@tools:sample/avatarsVector drawables that you can use as profile avatars.
@tools:sample/backgrounds/scenicImages that you can use as backgrounds.

上述表格中不仅有常用文本数据和日期等数据,还提供了一些图片样本数据,那么该如何使用呢?很简单,只需要切换到布局预览界面,并拖动一个 ImageView到面板上,然后 Android studio 就会弹出如下界面:

android应用运维(自从用了AndroidTools我再也没加过班)(207)

然后选择 avatars或者 background/scenic数据源就可以了。当然你也可以通过 xml代码形式来设置:

<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="android应用运维(自从用了AndroidTools我再也没加过班)(208)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(209).com/apk/res/android" xmlns:android应用运维(自从用了AndroidTools我再也没加过班)(210)app="android应用运维(自从用了AndroidTools我再也没加过班)(211)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(212).com/apk/res-auto" androandroid应用运维(自从用了AndroidTools我再也没加过班)(213)id:background="@androandroid应用运维(自从用了AndroidTools我再也没加过班)(214)id:color/white" xmlns:tools="android应用运维(自从用了AndroidTools我再也没加过班)(215)http://schemas.androidandroid应用运维(自从用了AndroidTools我再也没加过班)(216).com/tools" androandroid应用运维(自从用了AndroidTools我再也没加过班)(217)id:layout_width="match_parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(218)id:layout_height="match_parent"> <ImageView androandroid应用运维(自从用了AndroidTools我再也没加过班)(219)id:layout_width="36dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(220)id:layout_height="36dp" android:id="@ id/imageView" androandroid应用运维(自从用了AndroidTools我再也没加过班)(221)id:layout_marginTop="16dp" android应用运维(自从用了AndroidTools我再也没加过班)(222)app:layout_constraintTop_toTopOf="parent" android应用运维(自从用了AndroidTools我再也没加过班)(223)app:layout_constraintStart_toStartOf="parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(224)id:layout_marginStart="16dp" tools:srcCompat="@tools:sample/avatars"/> <TextView androandroid应用运维(自从用了AndroidTools我再也没加过班)(225)id:layout_width="0dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(226)id:layout_height="wrap_content" android:id="@ id/textView" android应用运维(自从用了AndroidTools我再也没加过班)(227)app:layout_constraintStart_toEndOf="@ id/imageView" androandroid应用运维(自从用了AndroidTools我再也没加过班)(228)id:layout_marginStart="8dp" android应用运维(自从用了AndroidTools我再也没加过班)(229)app:layout_constraintEnd_toEndOf="parent" androandroid应用运维(自从用了AndroidTools我再也没加过班)(230)id:layout_marginEnd="16dp" android应用运维(自从用了AndroidTools我再也没加过班)(231)app:layout_constraintTop_toTopOf="parent" tools:text="@tools:sample/lorem/random" tools:maxLines="8" androandroid应用运维(自从用了AndroidTools我再也没加过班)(232)id:ellipsize="end" androandroid应用运维(自从用了AndroidTools我再也没加过班)(233)id:textSize="14sp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(234)id:textColor="@color/title_color" androandroid应用运维(自从用了AndroidTools我再也没加过班)(235)id:layout_marginTop="16dp" android应用运维(自从用了AndroidTools我再也没加过班)(236)app:layout_constraintHorizontal_bias="0.0"/></android.support.constraint.ConstraintLayout>

同样地,TextView也可以通过 @tools:sample/lorem/random来添加样本数据,如此一来,效果如下:

android应用运维(自从用了AndroidTools我再也没加过班)(237)

哈哈,还不错吧。那么问题来了,如果我们想要用自己的样本数据源呢?

二、自定义 sample data

如果我们想要是用自己定制化的样例数据,该如何做呢?其实很简单,只需要在 android应用运维(自从用了AndroidTools我再也没加过班)(238)app目录下创建 sample data directory就可以了:

android应用运维(自从用了AndroidTools我再也没加过班)(239)

接下来,我们就可以在里面定制我们自己的数据了,在刚建好的 sampledata目录下新建一个 txt格式的数据文件,如 users,然后在里面创建如下数据:

android应用运维(自从用了AndroidTools我再也没加过班)(240)

如此这般,同理创建我们的其他数据: titles、descriptions,然后在上述 card_item_layout.xml布局文件中替换并使用自己的数据源:

<TextView android:id="@ id/card_item_username" androandroid应用运维(自从用了AndroidTools我再也没加过班)(241)id:layout_width="wrap_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(242)id:layout_height="wrap_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(243)id:layout_marginTop="16dp" android应用运维(自从用了AndroidTools我再也没加过班)(244)app:layout_constraintTop_toTopOf="parent" android应用运维(自从用了AndroidTools我再也没加过班)(245)app:layout_constraintStart_toStartOf="@ id/card_item_title" android应用运维(自从用了AndroidTools我再也没加过班)(246)app:layout_constraintEnd_toEndOf="@ id/card_item_title" android应用运维(自从用了AndroidTools我再也没加过班)(247)app:layout_constraintHorizontal_bias="0.0" androandroid应用运维(自从用了AndroidTools我再也没加过班)(248)id:textSize="12sp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(249)id:textColor="#8989ae" androandroid应用运维(自从用了AndroidTools我再也没加过班)(250)id:layout_marginEnd="16dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(251)id:paddingEnd="16dp" tools:text="@sample/users" />

这里仅以其中一个 TextView举例说明,其他同理。

什么?你以为到这里就讲完了?哈哈,少年,看你骨骼惊奇,再教你一招来上天入地:通过自定义 Json 格式的 数据来为控件绑定数据:

android应用运维(自从用了AndroidTools我再也没加过班)(252)

打完收工,还是上面的例子,来看看如何通过 json数据来绑定:

<TextView android:id="@ id/card_item_username" androandroid应用运维(自从用了AndroidTools我再也没加过班)(253)id:layout_width="wrap_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(254)id:layout_height="wrap_content" androandroid应用运维(自从用了AndroidTools我再也没加过班)(255)id:layout_marginTop="16dp" android应用运维(自从用了AndroidTools我再也没加过班)(256)app:layout_constraintTop_toTopOf="parent" android应用运维(自从用了AndroidTools我再也没加过班)(257)app:layout_constraintStart_toStartOf="@ id/card_item_title" android应用运维(自从用了AndroidTools我再也没加过班)(258)app:layout_constraintEnd_toEndOf="@ id/card_item_title" android应用运维(自从用了AndroidTools我再也没加过班)(259)app:layout_constraintHorizontal_bias="0.0" androandroid应用运维(自从用了AndroidTools我再也没加过班)(260)id:textSize="12sp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(261)id:textColor="#8989ae" androandroid应用运维(自从用了AndroidTools我再也没加过班)(262)id:layout_marginEnd="16dp" androandroid应用运维(自从用了AndroidTools我再也没加过班)(263)id:paddingEnd="16dp" tools:text="@sample/sample.json/data/username" />

以上操作的时候 Android studio 都会自动提示 sampledata路径下的数据文件,Json 格式亦会提示到具体字段。

最后

从 Google Android 官方的进一步动向来看,后续Android更新过程中,布局编辑器将更加强大。

从 Tools attributes 到 ConstraintLayout1.1 再到即将到来的 ConstraintLayout2.0 中的 MotionLayout,可以预见:Android 将在 UI 渲染和动画实现方面进一步解放我们的双手。

,