Android用戶界面設計:使用片段

來源: RockUX  發布時間: 2011-06-07 16:32  閱讀: 5740 次  推薦: 2   原文鏈接   [收藏]  

  Android 3.0引入的新的片斷(Fragment)API,讓我們更容易地創建動態用戶界面。在這個教程中,我們學習如何將一個兩屏的ListView轉換成WebView流,以適應大屏幕的單屏流設計,比如在平板設備中。

  這篇文章的節奏將比我們的入門教程更快一些。如果你對基本的Android控件或概念不熟悉你可能需要復習這個網站上我們其它的一些教程,甚至是Android API參考。最終的開源代碼可以在Google code上下載到。

  片段簡介

  在我們開始之間,讓我們在更高的層次上定義一下什么是片段。通常來說,片段是一大塊用戶界面,它具有自己的生存周期。如果它聽起來像一個Activity,那是因為它確實很像一個Activity。然而,片段與Activity不同,片段必須存在于Activity之內。片段不須要在它每次初始化的時候與同一個Activity配對,這使它具有一些靈活性。與Activity一樣,片段也無需包含任何用戶界面。

  步驟0:開始

  這個教程假設你讀過我們的列表視圖教程,你可以下載那個教程的代碼,并完成一些任務,然后開始,也可以直接下載這個教程的代碼直接開始。

  步驟1:重新設計界面

  下圖示意了我上在列表視圖教程中所提到的文章閱讀應用,我們還沒有考慮并使用片段:
  這個流程在相對小屏幕上運行得很不錯。然而,在大屏幕上,比如Motorola Xoom平板的10寸屏幕上,在列表視圖上卻浪費了很多空間。WebView看起來正常,但是有點枯燥。

  這就是要引入片段的地方:在大屏幕上,我們可以提供更有效的用戶界面,如果我們可以在同一屏上顯示ListView和WebView。當用戶點擊左邊“面板”的列表視圖中的某一項時,右邊的WebView更新顯示相應的內容。這種工作流程經常用于email或文檔或RSS閱讀器。下圖就是重新設計之后的界面示意圖:

  步驟2:轉換為基于片段的設計

  現在我們知道了新的流程應該如何設計,我們也知道當前的兩個活動必須轉換成片段。我們將分幾步來完成這個轉換。第一步保持界面樣子不變,只是使用片段修改每個界面內容。一個片段將包含當前的ListView,另一個包含WebView。然后我們再轉到單個屏幕的實現,修改ListView和WebView之間的消息傳遞。

  首先,將你的程序的項目構建目標改變Android 3.0。在Eclipse中,右鍵點擊項目并選擇“屬性”。點擊Android部分并選中Android 3.0。我們不使用任何Google API,所以Android開源項目版本足夠了。然后點擊“確定”按鈕。

現在你就可以訪問新的API了,包括片段API。

  注意:在將來的教程中,我們將討論如何使用新的兼容層來使得像片段API這樣的技術在更早版本的Android設備上也能工作。但是現在它只能運行在Android 3.0設備上。

  步驟3:創建片段類

  創建兩個Java類來代表兩個片段:ListView界面和WebView界面。將它們命名為TutListFragment和TutViewerFragment。TutListFragment將繼承ListFragment類,TutViewerFragment只是繼承Fragment類。

在TutListFragment類中,我們需要重寫兩個方法: onListItemClick()和onCreate()。這些方法的內容看起來應該很熟悉,它與之前我們講過的TutListActivity類的代碼一致。這個代碼很快就要修改,但是現在暫時不需要,下面是當前TutListFragment類的代碼:

 
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
String[] links
= getResources().getStringArray(R.array.tut_links);

String content
= links[position];
Intent showContent
= new Intent(getActivity().getApplicationContext(),
TutViewerActivity.
class);
showContent.setData(Uri.parse(content));
startActivity(showContent);
}

@Override

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(ArrayAdapter.createFromResource(getActivity()
.getApplicationContext(), R.array.tut_titles,
R.layout.list_item));
}

  TutViewerFragment類更簡單一些。我們基于當前片段運行在同一個活動下并且直接從Fragment類內問部獲取目標數據的事實。添加一個重寫onCreateView()方法。這個方法的代碼應該看起來像這樣:

 
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Intent launchingIntent
= getActivity().getIntent();
String content
= launchingIntent.getData().toString();

WebView viewer
= (WebView) inflater.inflate(R.layout.tut_view, container, false);
viewer.loadUrl(content);


return viewer;
}

  直接訪問活動實例的能力非常有用,但是在后面會引起一個問題。如果這個片段存在于帶有列表片段的界面上會怎么樣呢?在那樣的情況下,就會沒有啟動目標來獲取URL。類似的在TutListFragment中,只要當用戶點擊一個列表項時我們都直接啟動一個新的Activity。如果TutViewFragment在同一個活動中存在什么怎么樣呢?如果這樣的話,啟動一個新的活動就沒有意義了。我們將在這個教程的后面回過頭來解決這個問題。

  步驟4:添加片段布局資源

  現在創建一個新的名為“tutlist_fragment.xml”的布局文件來表示包含文章列表的片段。片段布局資源使用你創建的Fragment類的標簽和引用。

 
<?xml version="1.0" encoding="utf-8"?>
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.mamlambo.tutorial.tutlist.TutListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/tutlist_fragment">
</fragment>

  接下來,創建一個類似的布局文件,叫做tutview_fragment.xml:

 
<?xml version="1.0" encoding="utf-8"?>
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.mamlambo.tutorial.tutlist.TutViewerFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/tutview_fragment">
</fragment>

  步驟5:更新Activity類

  TutListActivity和TutViewerActivity類必須修改。TutListActivity類只有一個方法,onCreate(),現在需要修改它來加載你在前一步創建的合適的片段布局資源,如下:

 
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.tutlist_fragment);
}

  TutListActivity應該繼承Activity類,而不是ListActivity類。

  TutViewerActivity類也需要類似的修改,它的onCreate()方法現在看起來像這樣:

 
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tutview_fragment);
}

  步驟6:檢查你的進度

  嘗試現在運行程序。你會發現它和以前一樣。沒什么值得興奮的,不是么?然而,整個用戶界面現在使用片段來運行了。這使你需要做的下一步修改更加平滑,我們添加一個新的布局來組合兩個片段以在一個界面上顯示。然而可能你也注意到了,片段之間的通信的處理和我們文章之間的通信一樣。事實上,我們每個片段對應的活動保持不變。當一個活動包含并管理兩個片段時,這將不符合需求。首先讓我們來修復它。

  步驟7:改變TutListFragment通信

  像你在步驟3中學到的一樣,從TutListFragment對象直接啟動一個活動不再有效了。WebView UI可能與列表是同一個活動的一部分——總之那就是我們對于大屏幕的計劃。在那種情況下,我們只想在第二個片段中更新WebView的URL。

  做這些修改,我們需要做幾件事情。首先,我們讓片段不依賴于它們所在的活動。要做到這一點,在TutListFragment類中添加一個偵聽器,如下:

 
public interface OnTutSelectedListener {
public void onTutSelected(Uri tutUri);
}

  然后通過更新onListItemClickListener()方法來觸發它,如下:

 
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
String[] links = getResources().getStringArray(R.array.tut_links);

String content = links[position];
tutSelectedListener.onTutSelected(Uri.parse(content));
}

  接下來讓TutListActivity類實現OnTutSelectedListener接口,如下:

 
public class TutListActivity extends Activity implements
TutListFragment.OnTutSelectedListener {
...
@Override

public void onTutSelected(Uri tutUri) {
Intent showContent
= new Intent(getApplicationContext(),
TutViewerActivity.
class);
showContent.setData(tutUri);
startActivity(showContent);
}

  現在我們分離了片段的功能,這些功能用于處理用戶界面,作為控制器的活動,向下一個活動傳遞數據。我們后面要修改onTutSelected()方法來決定是否啟動一個新的活動實例或者更新現有的片段實例。

  步驟8:改變TutViewerFragment通信

  現在讓我們把注意力轉到TutViewerFragment類上,它的代碼也需要修改。片段不再查詢啟動目標來找出加載哪個URL,而是等待被通知要加載哪個URL。在樣,我們可以直接修改WebView而不需要每次加載都重新創建片段。

  首先,修改TutViewerFragment類,讓它包含一個叫做updateUrl()的方法:

 
public void updateUrl(String newUrl) {
if (viewer != null) {
viewer.loadUrl(newUrl);
}
}

  其次,刪除所有onCreateView()方法下的功能,除了inflate()的調用。在TutViewerActivity類中,添加這些功能檢索Intent然后調用updateUrl()方法,如下:

 
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tutview_fragment);

Intent launchingIntent
= getIntent();
String content
= launchingIntent.getData().toString();

TutViewerFragment viewer
= (TutViewerFragment) getFragmentManager()
.findFragmentById(R.id.tutview_fragment);

viewer.updateUrl(content);
}

  此時此刻,程序的行為還是沒有變化。然而通過進一步的代碼,片段現在可以共存在同一個活動中或者分開。

  步驟9:添加雙片段布局

  現在讓我們來創建帶有兩個片段的布局,以供特定情況使用。在layout-land目錄(你可能需要自己創建),粘貼一份tutlist_fragment.xml。它將對橫屏和豎屏提供不同的布局。豎屏模式將保持不變。編輯這個文件如下:

 
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android
="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<fragment
android:name
="com.mamlambo.tutorial.tutlist.TutListFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:id="@+id/tutlist_fragment"
android:layout_weight="45">
</fragment>
<fragment
android:name
="com.mamlambo.tutorial.tutlist.TutViewerFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:id="@+id/tutview_fragment"
android:layout_weight="55">
</fragment>
</LinearLayout>

  這將界面分隔成水平地兩個片段(左右結構)。

  步驟10:添加動態選項

  現在我們可以為程序添加一些簡單的邏輯,可以在啟動一個新的活動(雙屏模式)和更新存在的片段(單屏模式)之間切換。

  為了達到這個目的,更新TutListActivity類的onTutSelected()方法如下:

 
@Override
public void onTutSelected(String tutUrl) {
TutViewerFragment viewer
= (TutViewerFragment) getFragmentManager()
.findFragmentById(R.id.tutview_fragment);


if (viewer == null || !viewer.isInLayout()) {
Intent showContent
= new Intent(getApplicationContext(),
TutViewerActivity.
class);
showContent.setData(Uri.parse(tutUrl));
startActivity(showContent);
}
else {
viewer.updateUrl(tutUrl);
}
}

  我們所做的就是獲取片段并檢查它是否是現存的布局的一部分。如果不是,查看器活動啟動,否則更新已存在的片段。

  步驟11:運行最新的使用片段的程序

  到此,程序將有兩種模式:豎屏保持不變,橫屏顯示列表位于WebView的左側。現在可以做幾個改進,但是只是做微調,優化。比如,如果你在豎屏WebView模式下并旋轉屏幕,結果還是只有WebView界面。你必須點擊返回以獲得雙面視圖。程序修正不在這個教程講述的范圍,但是你可以發現,如果使用適當的布局并且加上一些活動邏輯,你可以對于不同的屏幕和設備做到非常強大和靈活。

  總結

  片段API幫助組織用戶界面組件,以使它們可以實現跨活動重用。這樣,程序可以在相對少的代碼量下,動態地適應它的流程和用戶界面。你也能看到基于片段構建的代碼更容易重新組織。更值得高興的是,通過Google提供的兼容庫,現在任何程序都可以使用片段了,它甚至兼容到Android 1.6。現在就使用片段來為每一個屏幕大小和形狀創建你的程序用戶界面吧!

2
0
 
標簽:Android
 
 

文章列表

arrow
arrow
    全站熱搜

    大師兄 發表在 痞客邦 留言(0) 人氣()