- Android設計模式與最佳實踐
- (英)凱爾·繆
- 2822字
- 2021-02-07 09:26:39
2.4 創建卡片視圖
卡片視圖是最容易識別的Material Design組件之一。它旨在顯示單個主題的幾段內容,這些內容通常是圖形、文本、動作按鈕和圖標的組合。卡片是用統一的方式呈現選擇的好方法,所以使用卡片來展示三明治原料和相關信息(如價格或熱值)是一個不錯的選擇。我們將使用上一章中的工廠模式來實現。但是在了解如何修改代碼之前,讓我們先看看如何實現卡片視圖。
2.4.1 了解卡片視圖的屬性
如果你的最低目標SDK是21或更高版本,那么標準小部件中已經包含了CardView。否則,需要添加cardview支持庫;通過在build.gradle文件中添加以下代碼,可以輕松地添加。
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.4.0' compile 'com.android.support:cardview-v7:23.4.0' }
正如支持庫的名稱所示,卡片視圖只支持API 7以上的級別。
了解如何編輯build.gradle十分有用,但我們不需要手動編輯build.gradle文件,因為它可以通過File|Project Structure...(文件|項目結構...)菜單,選擇如圖2-7所示的項目來實現。

圖2-7
一些開發者使用+號代替支持庫的版本號,如com.android.support:cardview-v7:23.+。這是對支持庫未來的預期
。這樣寫通常沒什么問題,但是不能保證應用程序不會在以后發生崩潰。在開發過程中使用已編譯的SDK版本,然后在發布后定期更新應用程序,這樣做雖然更費時,但是更明智。
在將卡片視圖添加到布局之前,需要重建項目。首先,需要設置卡片的一些屬性。打開res/values/dimens.xml文件并添加以下三個新尺寸:
<dimen name="card_height">200dp</dimen> <dimen name="card_corner_radius">4dp</dimen> <dimen name="card_elevation">2dp</dimen>
現在,可以把卡片作為一個小部件加入主活動的XML文件中:
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="@dimen/card_height" android:layout_gravity="center" card_view:cardCornerRadius="@dimen/card_corner_radius" card_view:cardElevation="@dimen/card_elevation"> </android.support.v7.widget.CardView>
使用陰影,不僅讓界面擁有一個三維外觀,還可以圖形化顯示布局的層次結構,讓用戶明白哪些功能可用。
如果你花了一些時間查閱卡片視圖的屬性,就會注意到translationZ屬性,似乎這個屬性與elevation屬性有同樣的效果。但是,elevation屬性會設置卡片的絕對高度,而translationZ的設置是相對的,其值將從當前的高度中增加或減少。
我們已經創建了一個卡片視圖,可以參考Material Design指南填寫屬性,使用它顯示我們的三明治原料。
2.4.2 應用CardView參數
設計指南對字體、內邊距和比例等問題做了非常清晰的指導。一旦開始使用Coordinator-Layout,很多配置將自動設置。但現在,我們最好看一下這些參數是如何使用的。
這里,我們將創建一個視圖,包含一幅圖像、三個文本項和一個動作按鈕。卡片可以被視為容器對象,因此通常包含根布局。根布局可以直接放在卡片視圖內部,但是如果將卡片內容創建為單獨的XML布局,可以使代碼可讀性更強且更加靈活。
下一個練習至少需要一幅圖像。依據Material Design,拍攝的圖像應該清晰、明亮、簡單,并呈現出單一、清晰的主題。例如,如果我們想在菜單中添加咖啡,圖2-8中左邊的圖像更合適。

圖2-8
卡片的圖像寬高比需要為16∶9或1∶1。這里,我們將使用16∶9的圖像。理想情況下,我們應該生成適合不同屏幕密度的縮放版本,但由于這只是一個演示,我們可以偷懶,將原圖直接放入drawable文件夾即可。這種方法遠不是最佳實踐,但對于初步測試來說是可以的。
獲取并保存圖像后,下一步是為卡片創建一個布局。
(1)從項目資源管理器中,選擇New |XML |Layout XML File(新建|XML|XML布局文件),布局名為card_content.xml。它的根布局應該是垂直方向的線性布局,代碼應該如下所示。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/card_content" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> </LinearLayout>
(2)使用圖形編輯器或文本編輯器,創建的布局結構需要匹配如圖2-9所示的組件樹。

圖2-9
(3)現在,在主活動的布局文件中,把上述布局添加到卡片視圖中,如下所示。
<android.support.v7.widget.CardView android:id="@+id/card_view" android:layout_width="match_parent" android:layout_height="wrap_content"> <include android:id="@+id/card_content" layout="@layout/card_content" /> </android.support.v7.widget.CardView>
雖然elevation屬性值可以編輯,但是建議將卡片視圖的elevation屬性設置為2dp,除非它被選中或正在移動,這種情況下,建議將elevation屬性設置為8dp。
毫無疑問,強烈建議XML資源中的字符串不要使用硬編碼。不出意外,使用硬編碼會使得應用程序無法被翻譯成其他語言。但是,在布局設計的早期階段,使用一些占位符值有助于了解布局的外觀。稍后,我們將使用Java來控制卡片的內容,并根據用戶輸入修改內容,但現在,我們將選擇一些典型的值,以便輕松且快速地查看設置的效果。為了查看如何進行上述操作,請將以下屬性或等效屬性添加到values目錄下的strings.xml文件中。
<string name="filling">Cheddar Cheese</string> <string name="filling_description">A ripe and creamy cheddar from the south west</string> <string name="calories">237 kcal per slice</string> <string name="action">ADD</string> <string name="alternative_text">A picture of some cheddar cheese</string>
現在,使用這些占位符來評估我們所有的改動。我們剛剛創建的布局的預覽圖應如圖2-10所示。

圖2-10
要將其轉換為Material Design形式的組件,只需了解Material Design設計的一些格式和知識。
此布局的參數應該如下所示:
? 圖像的比例必須是16∶9;
? 標題文本應為24 sp;
? 描述性文字是16 sp;
? 文本右下角和左下角的邊距為16dp;
? 標題文本上方的邊距為24dp;
? 動作文本為24 sp,并且顏色從主色中選取。
通過屬性面板或者直接編輯XML,可以輕松地設置這些屬性。因為有一些事情沒有提及,所以單獨查看一下每個元素是很值得的。
首先,必須指出的是,這些值不應該在代碼中逐字描述(像下面的代碼片段中那樣)。例如,android:paddingstart="24dp",應該像android:paddingstart="@dimen/text_paddingstart"這樣進行編碼。在dimens.xml文件中定義text_paddingstart。此處這些值使用硬編碼,只是為了簡化說明。
頂部的圖像視圖代碼應如下所示。
<ImageView android:id="@+id/image_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:contentDescription="@string/alternative_text" android:src="@drawable/cheddar" />
代碼非常直觀,不過需要注意contentDescription屬性的使用。視力受損的用戶設置了可訪問性選項后,可以通過設備的語音合成器讀取圖像的描述(contentDescription屬性)來欣賞圖像。
以下是三個文本視圖。
<TextView android:id="@+id/text_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingEnd="24dp" android:paddingStart="24dp" android:paddingTop="24dp" android:text="@string/filling" android:textAppearance="? android:attr/textAppearanceLarge" android:textSize="24sp" /> <TextView android:id="@+id/text_description" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingEnd="24dp" android:paddingStart="24dp" android:text="@string/filling_description" android:textAppearance="? android:attr/textAppearanceMedium" android:textSize="14sp" /> <TextView android:id="@+id/text_calories" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end" android:paddingBottom="8dp" android:paddingStart="16dp" android:paddingEnd="16dp" android:paddingTop="16dp" android:text="@string/calories" android:textAppearance="? android:attr/textAppearanceMedium" android:textSize="14sp" />
這些代碼也很容易理解。真正需要指出的是,使用Start和End,而不是Left和Right來定義padding和gravity,因為這有助于在把文本翻譯成從右到左運行的語言時的布局適配。代碼中還包含了textAppearance屬性,因為直接設置了文本的大小,所以這個屬性可能看起來是多余的。但textAppearanceMedium等屬性非常有用,因為它們不僅會根據自定義主題自動應用文本顏色,還會根據用戶私人設置的全局文本大小調整其大小。
在底部會有一個動作按鈕,因為它使用的是文本視圖而不是按鈕,所以可能需要做一些解釋。XML如下所示。
<TextView android:id="@+id/text_add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end" android:clickable="true" android:paddingBottom="16dp" android:paddingEnd="40dp" android:paddingLeft="16dp" android:paddingRight="40dp" android:paddingStart="16dp" android:paddingTop="16dp" android:text="@string/action" android:textAppearance="? android:attr/textAppearanceLarge" android:textColor="@color/colorAccent" android:textSize="24sp" />
這里似乎應該使用按鈕(Button)小部件,但出于兩個原因我們選擇了文本視圖。首先,Android建議使用平面按鈕,在卡片視圖中只有文本視圖可見。其次,觸發操作的可觸摸區域需要大于文本本身,這可以通過像以前一樣設置padding屬性輕松實現。要使文本視圖可以像按鈕一樣工作,只需要添加一行android:clickable="true"。
現在,我們做好的卡片看起來應該如圖2-11所示。

圖2-11
卡片視圖的設計還有很多內容,不過對于我們所需遵循的原則,這是一個很好的介紹。下面看看如何將這些呈現對象的新方法反映到工廠模式代碼上。
2.4.3 更新工廠模式
設計模式的美妙之處在于它們可以輕松地適應我們想要做出的任何改變。如果想的話,我們可以保持工廠代碼不變,并使用單個字符串輸出將客戶端代碼直接定向到適宜的數據集。不過,適配略為復雜的原料對象,更符合模式的本質。
現在,上一章中的代碼結構思路有了回報。雖然我們需要編輯接口和具體示例,但可以將工廠類保留原樣,這很好地證明了模式的其中一個優勢。
依照用于創建卡片的四個條件,我們的新接口應該如下所示。
public interface Bread { String image(); String name(); String description(); int calories(); }
單個對象示例如下所示。
public class Baguette implements Bread { @Override public String image() { return "R.drawable.baguette"; } @Override public String name() { return "Baguette"; } @Override public String description() { return "Fresh and crunchy"; } @Override public int calories() { return 150; } }
隨著發展,對象將需要更多的屬性,比如價格,以及它們是素食還是堅果。隨著對象變得越來越復雜,我們將不得不使用更復雜的方式來管理數據。但原則上講,這里用的方法沒有任何問題。雖然它可能有些笨拙,但肯定更易閱讀和維護。工廠模式顯然非常有用,但它們只創建了單個對象。為了更真實地建模一個三明治,我們需要將ingredient對象組合到一起,并將整個集合視為一個sandwich對象。這時建造者模式就派上用場了。
- Maven Build Customization
- PostgreSQL技術內幕:事務處理深度探索
- Java Web開發技術教程
- 微信公眾平臺開發:從零基礎到ThinkPHP5高性能框架實踐
- Mastering Rust
- C語言程序設計上機指導與習題解答(第2版)
- Java面向對象程序設計
- App Inventor創意趣味編程進階
- 監控的藝術:云原生時代的監控框架
- Neo4j 3.x入門經典
- Java Web開發基礎與案例教程
- 軟件設計模式(Java版)
- Magento 2 Developer's Guide
- LibGDX Game Development By Example
- Expert Cube Development with SSAS Multidimensional Models