下面会带大家一步步实现上述功能,首先,让我们从头说起。
Tools attributes
即以 tools
开始的命名空间,举个我们最常见到的例子:
<android.support.constraint.ConstraintLayout
xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:tools=“http://schemas.android.com/tools”
xmlns:app=“http://schemas.android.com/apk/res-auto”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=“.MainActivity”>
</android.support.constraint.ConstraintLayout>
大家肯定平时都会见到 tools:context=".XXXActivity
这个系统默认为我们生成的配置。一般来说,只有根视图才能使用这个属性,它指定了当前布局默认是与哪个 Activity
相关联,使得布局能够获取到绑定 Activity
的一些信息,比如 Theme 等等,而且当你在布局中给子 View 添加 onClick
事件时,相应的方法代码会插入到这个 Activity 中。
Android studio 支持很多在 XML
文件中以 tools
为命名空间的属性,当构建 App 时这些属性会被擦除,对 APK 的大小和运行时行为没有任何影响,这也就是我们文章最初想要的结果。
在具体介绍 Tools attributes
之前,我们需要先了解如何引入 Tools
的命名空间并使用,很简单,只需要在 XML 布局文件的根元素中添加即可:
<RootTag xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:tools=“http://schemas.android.com/tools” >
这些工具属性大概可以分为以下三类:
1、Error handling attributes
即错误和警告处理属性。这类属性常被用来规避被 lint
检查出的一些错误提示以及警告。下面让我们看一些常见的例子:
- tools:ignore
主要用来忽略一些 lint 产生的警告信息,并支持一些属性,例如:
ConstraintSample
header image
这个对于 Android studio 升级到 3.0 以上的小伙伴来说应该是很常见了,如果我们项目中涉及到国际化支持,那么编译器就会提示我们为每一种语言做适配,不能“厚此薄彼”,如果我们某些 string
只需要支持一种语言,只需要像上面那样添加 tools:ignore="MissingTranslation
即可。相似的例子还可以在使用 ImageView
的时候看到:
<ImageView
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:src=“@drawable/ic_person_off”
tools:ignore=“contentDescription” />
- tools:targetApi
这个属性的功能和 Java 代码中的注解 @TargetApi
是一样的:它指定了当前控件或元素支持的 API 级别,属性值可以是 API Code
名或者 API常数值,它支持一切属性。如:我们都知道,android:elevation
属性是在 API 21
版本以上才支持的,所以我们可以通过以下代码规避 lint
的警告:
<Button
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:elevation=“4dp”
tools:targetApi=“lollipop”/>
- tools:locale
这个属性主要用在 <resource>
标签内,用来指定当前资源中默认为哪种语言和区域,进而规避语言拼写的检测,比如你可以指定values/strings.xml
文件的默认语言是西班牙语而不是英语:
<resources xmlns:tools=“http://schemas.android.com/tools”
tools:locale=“es”>
2、Resource shrinking attributes
即资源压缩属性。关于此类属性的用法我们已经在之前的一篇文章带你领略Android混淆的魅力
一文中做过详细讲解,下面再简单说明一下。
我们可以通过 tools:shrinkMode
和 tools:keep
属性来分别指定资源压缩的模式和需要保留的不被压缩的资源 ,还可以通过 tools:discard
属性来指定需要保留的资源,与 keep
功能类似:
<resources xmlns:tools=“http://schemas.android.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:
可以替换任何以 android:
为前缀的属性,并为其设置样例数据(sample data
)。当然,正如我们前面所说,tools
属性只能在布局编辑期间有效,App真正运行后就毫无意义了,所以,我们就可以像下面这样来在运行前预览布局效果:
上图对应的布局文件为:
Card_item_layout.xml:
<android.support.constraint.ConstraintLayout
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
xmlns:android=“http://schemas.android.com/apk/res/android”
android:background=“@android:color/white”
android:clickable=“true”
android:focusable=“true”
android:foreground=“?attr/selectableItemBackground”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:layout_marginStart=“2dp”
android:layout_marginEnd=“2dp”
tools:targetApi=“m”
tools:ignore=“UnusedAttribute”>
<ImageView
android:id=“@+id/card_item_avatar”
android:layout_width=“38dp”
android:layout_height=“38dp”
app:layout_constraintStart_toStartOf=“parent”
android:layout_marginStart=“16dp”
android:layout_marginTop=“16dp”
app:layout_constraintTop_toTopOf=“parent”
app:layout_constraintBottom_toBottomOf=“parent”
android:layout_marginBottom=“16dp”
app:layout_constraintVertical_bias=“0.0”
tools:ignore=“ContentDescription”
tools:srcCompat=“@drawable/user_other”/>
<TextView
android:id=“@+id/card_item_username”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:layout_marginTop=“16dp”
app:layout_constraintTop_toTopOf=“parent”
app:layout_constraintStart_toStartOf=“@+id/card_item_title”
app:layout_constraintEnd_toEndOf=“@+id/card_item_title”
app:layout_constraintHorizontal_bias=“0.0”
android:textSize=“12sp”
android:textColor=“@color/username_text_color”
android:layout_marginEnd=“16dp”
android:paddingEnd=“16dp”
tools:text=“水月沐风” />
<TextView
android:id=“@+id/card_item_title”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:textSize=“16sp”
android:textColor=“@color/title_text_color”
app:layout_constraintStart_toEndOf=“@+id/card_item_avatar”
android:layout_marginStart=“12dp”
app:layout_constraintTop_toBottomOf=“@+id/card_item_username”
android:layout_marginTop=“8dp”
android:maxLines=“1”
tools:text=“今天上海的夜色真美!”/>
<TextView
android:id=“@+id/card_item_content”
android:layout_width=“0dp”
android:layout_height=“wrap_content”
app:layout_constraintStart_toStartOf=“parent”
android:layout_marginTop=“24dp”
app:layout_constraintTop_toBottomOf=“@+id/card_item_avatar”
app:layout_constraintBottom_toBottomOf=“parent”
android:layout_marginBottom=“16dp”
app:layout_constraintVertical_bias=“1.0”
android:maxLines=“3”
android:ellipsize=“end”
android:textColor=“@color/content_text_color”
android:textStyle=“normal”
app:layout_constraintEnd_toEndOf=“@+id/card_item_bottom_border”
android:layout_marginEnd=“16dp”
android:layout_marginStart=“16dp”
app:layout_constraintHorizontal_bias=“0.0”
tools:text=“人生若只如初见,何事秋风悲画扇…”/>
<ImageView
android:id=“@+id/card_item_poster”
android:layout_width=“0dp”
android:layout_height=“200dp”
app:layout_constraintStart_toStartOf=“parent”
app:layout_constraintTop_toBottomOf=“@+id/card_item_content”
app:layout_constraintEnd_toEndOf=“parent”
android:layout_marginEnd=“16dp”
android:scaleType=“centerCrop”
android:layout_marginTop=“8dp”
android:layout_marginStart=“16dp”
app:layout_constraintBottom_toBottomOf=“parent”
android:layout_marginBottom=“16dp”
app:layout_constraintVertical_bias=“0.0”
tools:ignore=“ContentDescription”
android:visibility=“visible”
tools:src=“@drawable/shanghai_night”/>
<View
android:id=“@+id/card_item_bottom_border”
android:layout_width=“0dp”
android:layout_height=“2dp”
app:layout_constraintTop_toBottomOf=“@+id/card_item_poster”
android:background=“#ffededfe”
app:layout_constraintEnd_toEndOf=“parent”
android:layout_marginTop=“16dp”
app:layout_constraintStart_toStartOf=“parent”/>
<TextView
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:id=“@+id/card_item_date”
android:layout_marginTop=“16dp”
app:layout_constraintTop_toTopOf=“parent”
app:layout_constraintEnd_toEndOf=“parent”
android:layout_marginEnd=“16dp”
android:textColor=“@color/date_text_color”
android:textSize=“12sp”
tools:text=“2019-08-10”/>
</android.support.constraint.ConstraintLayout>
通过上面代码我们可以发现:通过 对 TextView 使用 tools:text
属性代替 android:text
就可以实现文本具体效果的预览,然而这项设置并不会对我们 App 实际运行效果产生影响。同理,通过将 tools:src
作用于 ImageView 也可以达到预览图片的效果。此外。我们还可以对其他以 android:
为前缀的属性进行预览而不影响实际运行的效果,例如:上面布局代码中的底部分割线 <View>
,我们想将其在 App 实际运行的时候隐藏掉,但我们还是需要知道它的预览效果和所占高度:
<View
android:id=“@+id/card_item_bottom_border”
android:layout_width=“0dp”
android:layout_height=“2dp”
android:visibility=“gone”
tools:visibility=“visible”
tools:layout_height=“8dp”
app:layout_constraintTop_toBottomOf=“@+id/card_item_poster”
android:background=“#ffededfe”
app:layout_constraintEnd_toEndOf=“parent”
android:layout_marginTop=“16dp”
app:layout_constraintStart_toStartOf=“parent”/>
如上所示,通过 tools:visibility
和 tools:layout_height
就可以仅在布局预览情况下改变 View 的状态和高度。虽然上述情况比较少用,但是希望大家也能够知道,tools:
可以替代所有 android:
修饰的属性。下面再列举一些其他会常用到的属性。
- 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
中如下效果:
- tools:menu
这个属性可以给当前布局预览器的 Toolbar 添加多个菜单项,但仅限于布局文件的根节点元素。如:
<?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” />
- tools:maxValue | tools:minValue
这两个属性仅用于 <NumberPicker>
,可以在预览时指定其最大值和最小值:
<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:listitem | tools:listheader | tools:listfooter | tools:listCount
下面来讲一下列表相关组件的 tools
属性。上面四个属性仅用于 <AdapterView>
及其子类(如:ListView 和 RecyclerView)。然而,它们内部仍有一些使用限制:tools:listCount
仅用于RecyclerView
;tools:listheader
和 tools:listfooter
仅限于 ListView;至于 tools:listitem
属性二者皆可用。之前的效果图就是借助于此属性:
activity_main.xml:
<android.support.constraint.ConstraintLayout
xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:tools=“http://schemas.android.com/tools”
xmlns:app=“http://schemas.android.com/apk/res-auto”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=“.MainActivity”
android:background=“#ffEBEBEF”>
<android.support.v7.widget.Toolbar
android:id=“@+id/toolbar”
android:layout_width=“0dp”
android:layout_height=“wrap_content”
android:background=“?attr/colorPrimary”
android:theme=“?attr/actionBarTheme”
android:minHeight=“?attr/actionBarSize”
最后
我坚信,坚持学习,每天进步一点,滴水穿石,我们离成功都很近!
以下是总结出来的字节经典面试题目,包含:计算机网络,Kotlin,数据结构与算法,Framework源码,微信小程序,NDK音视频开发,计算机网络等。
字节高级Android经典面试题和答案
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
ty"
android:background=“#ffEBEBEF”>
<android.support.v7.widget.Toolbar
android:id=“@+id/toolbar”
android:layout_width=“0dp”
android:layout_height=“wrap_content”
android:background=“?attr/colorPrimary”
android:theme=“?attr/actionBarTheme”
android:minHeight=“?attr/actionBarSize”
最后
我坚信,坚持学习,每天进步一点,滴水穿石,我们离成功都很近!
以下是总结出来的字节经典面试题目,包含:计算机网络,Kotlin,数据结构与算法,Framework源码,微信小程序,NDK音视频开发,计算机网络等。
字节高级Android经典面试题和答案
[外链图片转存中…(img-WAB1BDbV-1715098636521)]
[外链图片转存中…(img-AbqVsk6Y-1715098636522)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!