自從用了Android Tools,我再也沒加過班 [復制鏈接]

2019-10-16 09:43
xdingdang 閱讀:514 評論:0 贊:0
Tag:  Android Tools

前言

日常開發過程中,我們都會遇到這樣一種場景:我們寫出的 UI 效果在對接數據之前需要提前進行預覽,進而調整 UI 細節和排版問題。我們一般的做法是什么樣的?

如果存在像 TextView 或者 ImageView 這種基礎控件,你是不是還在通過諸如

android:text="xxx"android:src="@drawable/xxx"的方式來測試和預覽UI效果?當然你肯定也會遇到這些“臟數據”給你帶來的困擾:測試的時候某些地方出現了本不該出現的數據,事后可能一拍腦門才發現,原來是布局中控件預覽數據沒有清除導致的。

如果是 RecyclerView,在后臺接口尚能測試的情況下,你是否又要自己生成“假數據”并手寫 Adapter 呢?這時候你不禁會問:有沒有一種方法,既能夠做到布局時預覽數據方便排版,又能夠在對接真實數據運行后動態替換和移除這些無關數據呢?

鐺鐺鐺鐺!Android 的 Tools attributes應運而生。

老規矩,我們先來看一個效果:

自從用了Android Tools,我再也沒加過班

What?你在耍我嗎?這么簡單的列表拿出來干嘛?哈哈,客觀不要著急。這個并不難實現,倘若我說這里并沒有寫一行 Java 或者 Kotlin 代碼就實現了此效果,而只是在布局頁面預覽,你敢信嗎?上圖只是冰山一角,下面這張圖才是全貌:

自從用了Android Tools,我再也沒加過班

下面會帶大家一步步實現上述功能,首先,讓我們從頭說起。

認識 Tools attributes

Tools attributes 即以 tools開始的命名空間,舉個我們最常見到的例子:

<?xml version="1.0" encoding="utf-8"?><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 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檢查出的一些錯誤提示以及警告。下面讓我們看一些常見的例子:

1.1 tools:ignore

主要用來忽略一些 lint 產生的警告信息,并支持一些屬性,例如:

<resources xmlns:tools="http://schemas.android.com/tools"> <string name="app_name">ConstraintSample</string> <string name="header_image_string" tools:ignore="MissingTranslation">header image</string></resources>

這個對于 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" />

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

1.3 tools:locale

這個屬性主要用在 <resource>標簽內,用來指定當前資源中默認為哪種語言和區域,進而規避語言拼寫的檢測,比如你可以指定 values/strings.xml文件的默認語言是西班牙語而不是英語:

<resources xmlns:tools="http://schemas.android.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="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


<?xml version="1.0" encoding="utf-8"?><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 中如下效果:

自從用了Android Tools,我再也沒加過班
  • 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:

<?xml version="1.0" encoding="utf-8"?><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" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" android:elevation="1dp" app:title="@string/app_name" app:layout_constraintTop_toTopOf="parent" app:layout_constraintHorizontal_bias="0.0"/> <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:scrollbars="vertical" app:layout_constraintTop_toBottomOf="@+id/toolbar" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintVertical_bias="0.0" tools:listitem="@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 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 the world.
@tools:sample/us_zipcodesRandomly generated US zipcodes.
@tools:sample/us_phonesRandomly generated phone numbers with the following format: (800) 555-xxxx.
@tools:sample/loremPlaceholder text that is derived from Latin.
@tools:sample/date/day_of_weekRandomized 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/avatarsVector drawables that you can use as profile avatars.
@tools:sample/backgrounds/scenicImages that you can use as backgrounds.

上述表格中不僅有常用文本數據和日期等數據,還提供了一些圖片樣本數據,那么該如何使用呢?很簡單,只需要切換到布局預覽界面,并拖動一個 ImageView到面板上,然后 Android studio 就會彈出如下界面:

自從用了Android Tools,我再也沒加過班

然后選擇 avatars或者 background/scenic數據源就可以了。當然你也可以通過 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" android:background="@android:color/white" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent">
<ImageView android:layout_width="36dp" android:layout_height="36dp" android:id="@+id/imageView" android:layout_marginTop="16dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="16dp" tools:srcCompat="@tools:sample/avatars"/> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:id="@+id/textView" app:layout_constraintStart_toEndOf="@+id/imageView" android:layout_marginStart="8dp" app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="16dp" app:layout_constraintTop_toTopOf="parent" tools:text="@tools:sample/lorem/random" tools:maxLines="8" android:ellipsize="end" android:textSize="14sp" android:textColor="@color/title_color" android:layout_marginTop="16dp" app:layout_constraintHorizontal_bias="0.0"/></android.support.constraint.ConstraintLayout>

同樣地,TextView也可以通過 @tools:sample/lorem/random來添加樣本數據,如此一來,效果如下:

自從用了Android Tools,我再也沒加過班

哈哈,還不錯吧。那么問題來了,如果我們想要用自己的樣本數據源呢?

二、自定義 sample data

如果我們想要是用自己定制化的樣例數據,該如何做呢?其實很簡單,只需要在 app目錄下創建 sample data directory就可以了:

自從用了Android Tools,我再也沒加過班

接下來,我們就可以在里面定制我們自己的數據了,在剛建好的 sampledata目錄下新建一個 txt格式的數據文件,如 users,然后在里面創建如下數據:

自從用了Android Tools,我再也沒加過班

如此這般,同理創建我們的其他數據: titles、descriptions,然后在上述 card_item_layout.xml布局文件中替換并使用自己的數據源:

<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="#8989ae" android:layout_marginEnd="16dp" android:paddingEnd="16dp" tools:text="@sample/users" />

這里僅以其中一個 TextView舉例說明,其他同理。

什么?你以為到這里就講完了?哈哈,少年,看你骨骼驚奇,再教你一招來上天入地:通過自定義 Json 格式的 數據來為控件綁定數據:

自從用了Android Tools,我再也沒加過班

打完收工,還是上面的例子,來看看如何通過 json數據來綁定:

<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="#8989ae" android:layout_marginEnd="16dp" android: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 渲染和動畫實現方面進一步解放我們的雙手。


我來說兩句
您需要登錄后才可以評論 登錄 | 立即注冊
facelist
所有評論(0)
領先的中文移動開發者社區
18620764416
7*24全天服務
意見反饋:[email protected]

掃一掃關注我們

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粵ICP備15117877號 )

龙江福彩p62开奖 孤胆车神电脑版怎么赚钱 盛达彩票苹果 自媒体影视片段赚钱 皮皮麻将app 男生做淘宝模特赚钱吗 赚钱实战 为什么比特币能赚钱吗 美人捕鱼下载 原油能赚钱吗 亚上彩游戏 这个生意还可以 我们赚钱赚多了 新昆山麻将翘百搭 戏精赚钱套路 什么加微信赚钱 五常森林龙江麻将 越凡文化聊天赚钱