Android tools & sample data: Make preview great again

在 Android 界面開發過程中我們經常需要查看頁面效果。在遠古時期使用 eclipse 開發的時候預覽是一件讓人頭疼的事,代碼和預覽界面不能同時出現,需要切換 tab,好在 Android Studio 提供的編輯界面可以讓我們同時看到代碼和預覽圖,省去我們開會切換的時間。(這是當年驅使我把 eclipse 換成 Android Studio 的主要原因之一)

但是預覽界面提供的預覽比較弱,只能看一些簡單的效果,稍微複雜的效果就需要運行起來才能看到,當工程變得複雜之後,構建一次 app 的時間會比較長,如果編寫複雜界面,需要調整好幾次的時候,花在構建上的時間可能都要很久,這會在一定程度上影響開發效率。相對於原生,react native 和 flutter 在這方面優勢就很突出,只需要 reload 一下馬上就能看到更新,不用每次去重新構建。雖然原生也有 instant run 的功能,但是開啓之後可能會造成很多莫名其妙問題,所以大部分時候都會關掉 instant run 保平安。

android tools 屬性

tools: 替換 android:

tools 屬性能幫助我們增強預覽效果。比如 tools:text 能夠幫助我們預覽文本,它的效果跟 android:text 一樣,但是在實際運行中並不起作用。eg. 我們在編寫 RecyclerView item 的時候需要預覽效果,但是因爲每個 item 的數據都不同,我們不能寫死 android:text。如果我們想要預覽文本效果,我們可以在 xml 使用 android:text , 在提交代碼的時候刪掉,但是這樣會比較麻煩,也可能會忘記,這時候我們就可以使用 tools:text 來代替 android:text,預覽效果完全相同,並且我們即使不刪除代碼也不會對運行效果造成影響,可以放心大膽的 push 代碼。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-gaZxH1ML-1583573217857)(https://i.loli.net/2020/03/05/rHomafPRENxXe4y.png)]

實際上大部分 android:xxx 的屬性都能替換成 tools:xxx,這樣我們就能在預覽的時候看到顯示效果,並且不用擔心打包的時候不小心把測試數據帶上去。

<androidx.constraintlayout.widget.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="match_parent">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="ContentDescription"
        tools:src="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        app:layout_constraintStart_toEndOf="@+id/imageView"
        app:layout_constraintTop_toTopOf="@+id/imageView"
        tools:text="Jon Snow"
        tools:textColor="#000"
        tools:textSize="20sp" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        app:layout_constraintStart_toStartOf="@+id/textView2"
        app:layout_constraintTop_toBottomOf="@+id/textView2"
        tools:text="I know nothing"
        tools:textColor="#666"
        tools:textSize="14sp" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="24dp"
        app:layout_constraintBottom_toBottomOf="@+id/imageView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@+id/imageView"
        tools:text="3/8/2020"
        tools:textColor="#666"
        tools:textSize="14sp" />
</androidx.constraintlayout.widget.ConstraintLayout>

Screen Shot 2020-03-05 at 00.39.46.png

tools:listitem

listitem 可能幫助我們預覽 RecyclerView 的樣式。通常情況下我們在 xml 中加入 RecyclerView 控件,as 會生成一個默認的預覽樣式.默認的樣式很簡單,我們不能看到實際的效果,需要運行代碼才能看到。使用tools:listitem 可以幫助我們實現在編輯的時候預覽 RecyclerView 的效果。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.main.MainFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:listitem="@layout/test_item" />
</androidx.constraintlayout.widget.ConstraintLayout>

Screen Shot 2020-03-06 at 00.08.51.png

除了 tools:listitem,Android 還提供了另外的屬性幫助我們更好的預覽 RecyclerView。 tools:itemCount 可以設置預覽個數,搭配 layoutManagerspanCount 我們還能預覽 GridLayoutManager 下的樣式。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.main.MainFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:itemCount="10"
        tools:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
        tools:listitem="@layout/test_avatar_item"
        tools:spanCount="3" />
</androidx.constraintlayout.widget.ConstraintLayout>

Screen Shot 2020-03-06 at 00.21.39.png

其他屬性

除了上面介紹的屬性之外,tools 還有很多別的作用,比如 tools:ignoretools:contexttools:showIn等,具體可以參考官方文檔

sample data

使用 tools 屬性後我們能夠在一定程度上增強我們的預覽效果,但是效果比較一般,比如預覽 RecyclerView 的數據時,我們雖然可以使用 tools:listitemtools:itemCount 設置預覽數據,但是每個 item 都一樣,數據看上去很假,跟實際使用的時候有一些出入。sample data 的出現能夠很好的幫我解決這個問題,真正的實現 make preview great again。我們可以使用 as 內置的 sample data,也可以自定義數據,數據會體現在預覽界面上,讓我們的預覽更接近實際運行效果。

as 內置 sample data

Android Studio 內置了一些 sample data,我們可以直接使用。

item.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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/imageView"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginBottom="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="ContentDescription"
        tools:src="@tools:sample/avatars" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        app:layout_constraintStart_toEndOf="@+id/imageView"
        app:layout_constraintTop_toTopOf="@+id/imageView"
        tools:text="@tools:sample/full_names"
        tools:textColor="#000"
        tools:textSize="20sp" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        app:layout_constraintStart_toStartOf="@+id/textView2"
        app:layout_constraintTop_toBottomOf="@+id/textView2"
        tools:text="@tools:sample/us_phones"
        tools:textColor="#666"
        tools:textSize="14sp" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="24dp"
        app:layout_constraintBottom_toBottomOf="@+id/imageView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@+id/imageView"
        tools:text="@tools:sample/date/mmddyy"
        tools:textColor="#666"
        tools:textSize="14sp" />


</androidx.constraintlayout.widget.ConstraintLayout>

layout.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.main.MainFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:itemCount="10"
        tools:listitem="@layout/test_sample_data_item" />
</androidx.constraintlayout.widget.ConstraintLayout>

Screen Shot 2020-03-07 at 16.53.09.png

我們看一下預覽效果是不是比之前的好一些呢,每個 item 都有不同的數據,而且我們也不需要引入額外的測試數據。

除了上面用到的 avatar, name 之類的,sample data 還有很多類型,基本上能滿足我們的日程需求,具體含義可以參考官方文檔

Screen Shot 2020-03-07 at 15.25.19.png

自定義 sample data

如果 Android Studio 提供的 sample data 還不能滿足你的需求,比如內置的姓名只有英文,你一定要預覽中文名字,這時候可以自定義數據。

我們可以通過 new -> Sample Data directory 來創建數據目錄。在 sampledata 下創建文本文件

mynames:

亞托克斯
阿狸
阿卡麗
阿利斯塔
阿木木
艾尼維亞
安妮
艾希
奧瑞利安·索爾
阿茲爾
巴德
布里茨
布蘭德

mynicknames

暗裔劍魔
九尾妖狐
暗影之拳
牛頭酋長
殤之木乃伊
冰晶鳳凰
黑暗之女
寒冰射手
鑄星龍王
沙漠皇帝
星界遊神
蒸汽機器人
復仇焰魂

在 xml 中使用 tools:text="@sample/mynicknames" 即可。

Screen Shot 2020-03-07 at 15.57.19.png

除了上面這種簡單文本的定義,我們還可以使用 json 來定義數據。

loldata.json:

{
  "comment": "lol data - loldata.json",
  "data": [
    {
      "name": "亞托克斯",
      "nickname": "暗裔劍魔"
    },
    {
      "name": "阿狸",
      "nickname": "九尾妖狐"
    },
    {
      "name": "阿卡麗",
      "nickname": "暗影之拳"
    },
    {
      "name": "阿利斯塔",
      "nickname": "牛頭酋長"
    },
    {
      "name": "阿木木",
      "nickname": "殤之木乃伊"
    },
    {
      "name": "艾尼維亞",
      "nickname": "冰晶鳳凰"
    }
  ]
}

在 xml 中使用 tools:text="@sample/loldata.json/data/name" 即可

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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/imageView"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginBottom="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="ContentDescription"
        tools:src="@sample/myimg" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        app:layout_constraintStart_toEndOf="@+id/imageView"
        app:layout_constraintTop_toTopOf="@+id/imageView"
        tools:text="@sample/loldata.json/data/name"
        tools:textColor="#000"
        tools:textSize="20sp" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        app:layout_constraintStart_toStartOf="@+id/textView2"
        app:layout_constraintTop_toBottomOf="@+id/textView2"
        tools:text="@sample/loldata.json/data/nickname"
        tools:textColor="#666"
        tools:textSize="14sp" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="24dp"
        app:layout_constraintBottom_toBottomOf="@+id/imageView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@+id/imageView"
        tools:text="@tools:sample/date/mmddyy"
        tools:textColor="#666"
        tools:textSize="14sp" />


</androidx.constraintlayout.widget.ConstraintLayout>

Screen Shot 2020-03-07 at 16.41.42.png

效果是不是還不錯呢

再說點什麼

google 一直在改進編輯界面的功能和體驗,特別是 ConstraintLayout 推出之後,編輯和預覽的功能更加強大,現在 Google 在各個大會上演示 ConstraintLayout 功能的時候基本都使用拖拽,特別是 ConstraintLayout 2.0 推出 MotionLayout 之後,編輯的功能變得更加強大,能夠預覽各種炫酷的動畫。這些都能很好幫助開發者節省開發時間, make preview great again!

代碼

https://github.com/LyCharlie/SampleDataDemo

參考文獻

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章