[譯]精通 Android 中的 tools 命名空間

原文:Mastering tools namespace on Android
作者:Alexandru Simonescu
譯者:lovexiaov

你可能注意到了 tools 命名空間會出現在許多 Google 提供的樣例布局 XML 文件中尺栖。此命名空間在開發(fā)階段很有用而且不會影響用戶體驗裙品。它包含了幫助我們在 Android Studio 設計視圖中渲染布局的一套方便的屬性前普。

有時這些巧妙的屬性會節(jié)約我們的構建時間羽资。我并不是說會加快構建速度亚情,而是構建相關的 UI 改變會減少渠牲。

<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"/>

tools 命名空間的 URI 是 http://schemas.android.com/tools畦粮,通常使用 tools 前綴綁定,但你也可以使用任何其他前綴霎桅。

該命名空間中的所有屬性都不會影響運行時或 apk 的大小,它們會在 Gradle 打包應用時被剝離出去讨永。

你可以使用 Android Studio 提供的快捷鍵快速添加 tools 命名空間滔驶。只需輸入 toolsNS 然后按下 TAB 鍵。

Quick add Tools namespace

值得一提的是截止到寫這篇文章時卿闹,Android Studio 并沒有太多對此 xml 語法補全支持揭糕,不過別擔心,即使 AS 沒有語法提示比原,你仍然可以覆寫 tools 屬性插佛。最簡單的使用方式是:首先書寫基于 android: 命名空間的屬性,然后使用 CMD + D 復制這行量窘,并替換它的前綴(為 tools)雇寇。

Duplicate and replace namespace

開始使用

當我剛做 Android 開發(fā)時,曾使用 android:text="" 屬性結合一些硬編碼的假文本在 預覽窗口 中查看 TextView 或 EditText 如何顯示蚌铜。但是 Lint 工具會檢查出硬編碼字符串的問題锨侯,最后我只能去定義 strings(來消除此問題),然而這樣做對用戶沒有任何意義冬殃,還使我的 .apk 中包含了沒用的資源囚痴。

(解決上述問題的)技巧是使用 tools:text"@string" 來在預覽窗口中查看預填充了數據的視圖。你會得到類似如下的 xml 代碼:

<TextView
    tools:text="Mastering ToolsNs"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />

使用以上代碼片段审葬,在設計時你會看到 TextView 中的文字深滚,而在運行時將不會有該屬性存在奕谭。

運行時和設計時的不同屬性

需要注意的是你可以同時使用 androidtools 命名空間。tools 命名空間將會用在設計階段而前者會用在運行時痴荐。

有時你希望在運行時開啟某些特性在設計預覽時關閉血柳。Android 文檔展示了 ListView 的例子:

<ListView
    android:id="@+id/listView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:fastScrollAlwaysVisible="true"
    tools:fastScrollAlwaysVisible=""/>

這里你可以看到:在運行時開啟了 fastScrollAlwaysVisible 功能,而在設計時關閉了它生兆。

其實你可以覆蓋所有已存在與 android 命名空間中的屬性难捌,但無法覆蓋自定義屬性。

在XML 中指定目標 API 版本

你可以在 XML 中執(zhí)行 API 級別鸦难,就想在 Java 中使用 @TargetApi 一樣根吁。API 版本可以通過一個整形或它的代號指定。這將避免 Lint 上報版本特定 XML 屬性的問題合蔽。

<TextView
    tools:text="Mastering ToolsNs"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    tools:layout_height="match_parent"
    tools:targetApi="M"
    />

告知 Lint 你的字符串是正確的

由于 Android Studio / Lint 默認語言是英語击敌,如果你有其他語言的字符串資源,它將會顯示如下的排版警告拴事。

Language typos warnings

告知 Lint 你本地化資源的技巧:

<resources xmlns:tools="http://schemas.android.com/tools" 
    tools:locale="es"/>

這樣就不會顯示排版警告了愚争。

在 fragment 和自定義視圖上預覽布局

我發(fā)現這(tools 命名空間)在使用 Fragment 和自定義視圖時非常有用。通過 tools:layout="@layout/your_layout" 屬性你可以設置在預覽窗口中顯示一個布局挤聘。

<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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity"
    >

    <fragment
        android:name="com.alexsimo.mastertoolsnamespace.BooksFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:layout="@layout/fragment_books"
        />

</LinearLayout>

上述代碼使用了 tools:layout 屬性來預覽 BooksFragment 布局轰枝,而不用將工程運行在設備或模擬器上。

我們來看一下視圖結構:

activity_main:

<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity"
    >

    <fragment
        android:name="com.alexsimo.mastertoolsnamespace.BooksFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:layout="@layout/fragment_book"
        />

</LinearLayout>

fragment_book:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
    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:id="@+id/list"
    android:name="com.alexsimo.mastertoolsnamespace.BooksFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    app:layoutManager="LinearLayoutManager"
    tools:context="com.alexsimo.mastertoolsnamespace.BooksFragment"
    tools:listitem="@layout/fragment_book_list_item"
    />

fragment_book_list_item:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:orientation="horizontal"
              xmlns:tools="http://schemas.android.com/tools"
    >

  <ImageView
      android:layout_width="150dp"
      android:layout_height="150dp"
      android:id="@+id/imageView"
      tools:src="@android:drawable/ic_media_play"
      />
  <LinearLayout
      android:orientation="vertical"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      >
    <TextView
        android:id="@+id/id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/text_margin"
        android:textAppearance="?attr/textAppearanceListItem"
        tools:text="My book title"
        />
    <TextView
        android:id="@+id/content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/text_margin"
        android:textAppearance="?attr/textAppearanceListItem"
        tools:text="My book description"
        />
  </LinearLayout>

</LinearLayout>

打開 activity_main 的預覽窗口组去,你將會看到如下界面:

預覽列表項布局

如果你比較細心鞍陨,你會看到上面 xml 代碼片段中的 tools:listitem="" 一行。這在預覽列表時會顯示你自定義的列表項而不是默認的 @android:layout/list_content"从隆。

還有更多相關的屬性诚撵,但是 RecyclerView 沒有 header 或 footer 屬性(這兩個屬性只能用在 ListView 上)。這兩個屬性分別是 tools:listheadertools:listfooter键闺。

帶父容器上下文的視圖

假如你有一個自定義視圖或可重用的布局會通過 <include> 標簽被用在許多地方寿烟。當設計該視圖時,預覽它在想要包含它的父容器中如何顯示將會很有幫助辛燥。

在上面的 fragment_book_list_item 中筛武,如果我們添加 tools:showIn="@layout/activity_main" 屬性,將可以預覽該列表條目如何顯示在 activity_main 中挎塌。這沒有多大意義徘六,只是為了演示這個概念。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:orientation="horizontal"
              xmlns:tools="http://schemas.android.com/tools"
              tools:showIn="@layout/activity_main"
    >
    <!-- Remaining views removed -->
</LinearLayout>

預覽界面將類似于這樣:

該特性也依賴于 Android Studio 的版本榴都。截止到寫此文之時待锈,我使用的是 Android Studio v2.1。

關聯 XML 到一個 activity

我很確定你已經知道該屬性了嘴高,當我們使用 Android Studio 引導創(chuàng)建一個 Activity 時竿音,在默認生成的 XML 文件中你會找到該屬性 tools:context=".MainActivity"和屎。如你所知,單個 xml 布局可以被用在多個 ActivityFragment 中春瞬,使用此屬性眶俩,你就告訴了 Android Studio 那個 .java Activity 類與之相關聯。

這將幫助布局修改這猜測 Activity 的主題快鱼,因為主題曾被定義在 AndroidManifest.xml 文件中。

忽略 Lint 警告

你應該謹慎使用此屬性纲岭,因為忽略 Lint 警告不是一個好主意抹竹。如果 Lint 上報問題,你應該行動起來并修復錯誤和警告止潮。但有時 Lint 給出的是錯誤警告窃判,我們明確知道(或許不知道)我們在做什么。這種情況下你可以使用 tools:ignore=""喇闸。

想想一下我們有一個圖標找不到它對應的像素密度文件夾袄琳,我們可能會使用 tools:ignore="IconMissingDensityFolder" 忽略 Lint 警告。你可以在 Android 官方文檔 中閱讀更多關于 Lint 的內容燃乍。

帶菜單預覽布局

默認情況下唆樊,定義在 Activity.onCreateOptionsMenu() 中的菜單會被渲染到預覽窗口。但你可以使用 tools:menu="comma separated menu IDs" 覆蓋此菜單刻蟹。我個人不會使用該屬性逗旁,但它可能會對你有用。

設置 Toolbar 導航模式

此屬性很簡單舆瘪!使用 tools:actionBarNavMode="standard|list|tabs" 你可以設置 ActivityBar 的導航模式片效。

收縮資源

Android tools 命名空間中有許多關于收縮資源的屬性,比如 tools:shrinkMode="strict|safe"英古,tools:keep="@layout|layout_wildcard"淀衣,tools:discard="@layout/unused" 等,但我不準備在此討論它們召调,因為本文不是討論收縮資源的膨桥,如果你感興趣,可以在 Android Studio 官方文檔中了解更多信息唠叛。

引用:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末国撵,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子玻墅,更是在濱河造成了極大的恐慌介牙,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件澳厢,死亡現場離奇詭異环础,居然都是意外死亡囚似,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門线得,熙熙樓的掌柜王于貴愁眉苦臉地迎上來饶唤,“玉大人,你說我怎么就攤上這事贯钩∧伎瘢” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵角雷,是天一觀的道長祸穷。 經常有香客問我,道長勺三,這世上最難降的妖魔是什么雷滚? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮吗坚,結果婚禮上祈远,老公的妹妹穿的比我還像新娘。我一直安慰自己商源,他們只是感情好车份,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著牡彻,像睡著了一般躬充。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上讨便,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天充甚,我揣著相機與錄音,去河邊找鬼霸褒。 笑死伴找,一個胖子當著我的面吹牛,可吹牛的內容都是我干的废菱。 我是一名探鬼主播技矮,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼殊轴!你這毒婦竟也來了衰倦?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤旁理,失蹤者是張志新(化名)和其女友劉穎樊零,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡驻襟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年夺艰,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沉衣。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡郁副,死狀恐怖,靈堂內的尸體忽然破棺而出豌习,到底是詐尸還是另有隱情存谎,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布肥隆,位于F島的核電站既荚,受9級特大地震影響,放射性物質發(fā)生泄漏巷屿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一墩虹、第九天 我趴在偏房一處隱蔽的房頂上張望嘱巾。 院中可真熱鬧,春花似錦诫钓、人聲如沸旬昭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽问拘。三九已至,卻和暖如春惧所,著一層夾襖步出監(jiān)牢的瞬間骤坐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工下愈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留纽绍,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓势似,卻偏偏與公主長得像拌夏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子履因,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內容