Android Studio 單刷《第一行代碼》系列 05 —— Fragment 基礎


前情提要(Previously)

本系列將使用 Android Studio 將《第一行代碼》(書中講解案例使用Eclipse)刷一遍,旨在為想入坑 Android 開發,並選擇 Android Studio 作為開發 IDE 的同學開路。
PS:其實我就是現學現賣,希望我能堅持刷完。

在前面已經學習了 Android 四大組件中的 Activity,這次來學習一下Activity 中的 Fragment。

系列目錄在此:

摘要(Abstract)

Fragment 的簡介、簡單使用、動態加載。

Fragment 是什么

先來看看 API Guides 里是怎么說的。
*
A Fragment represents a behavior or a portion of user interface in an Activity. You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section of an activity, which has its own lifecycle, receives its own input events, and which you can add or remove while the activity is running (sort of like a "sub activity" that you can reuse in different activities).
A fragment must always be embedded in an activity and the fragment's lifecycle is directly affected by the host activity's lifecycle.
*

  • Fragment 必須嵌入在 Activity 中使用。
  • Fragment 的生命周期 是受 Activity 影響的。
  • 可以在一個 Activity 中使用多個 Fragment。
  • Fragment 可以在多個 Activity 中重用。

說了這么多,也沒說 Fragment 到底是什么,只好繼續往下看。

Design Philosophy(設計理念)

Android introduced fragments in Android 3.0 (API level 11), primarily to support more dynamic and flexible UI designs on large screens, such as tablets. Because a tablet's screen is much larger than that of a handset, there's more room to combine and interchange UI components. Fragments allow such designs without the need for you to manage complex changes to the view hierarchy. By dividing the layout of an activity into fragments, you become able to modify the activity's appearance at runtime and preserve those changes in a back stack that's managed by the activity.

  • Android3.0 里出現的。
  • 為了更加合理和充分地利用大屏幕的空間。

其實就是為了更好的同時支持手機和平板(我是這么認為的)。看下面這個來自 Android API Guides 中的圖就明白了。

fragments

Fragment 簡單使用

練習開始,新建一個 FragmentTest 的項目,在一個 Activity 中添加兩個 Fragment,並列顯示。

  • 新建一個左側布局 left_fragment.xml,放一個 Button 在里面,代碼如下:

  <Button
      android:id="@+id/button"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_gravity="center_horizontal"
      android:text="Button" />
  • 同樣的新建一個右側布局 right_fragment.xml,放一個 TextView 在里面,代碼省略。

  • 新建 LeftFragment 類,繼承自 Fragment,重寫 onCreateView() 方法,在這個方法中通過 LayoutInflater 將布局動態加載進來,代碼如下:

public class LeftFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.left_fragment,container,false);
return view;
}
}

  • 同樣新建 RightFragment 類,代碼省略。

  • 修改 activity_main.xml,刪掉默認的 TextView 添加 Fragment,代碼如下:

<fragment
    android:id="@+id/left_fragment"
    android:name="com.addict.fragmenttest.LeftFragment"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"></fragment>

<fragment
    android:id="@+id/right_fragment"
    android:name="com.addict.fragmenttest.RightFragment"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"></fragment>

這樣最簡單的 Fragment 示例就寫好了,運行一下程序看看吧。

動態添加 Fragment

  • 新建一個 another_right_fragment.xml,放一個 TextView 在里面,設定布局的顏色、TextView 的內容,代碼如下:

  <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_gravity="center_horizontal"
      android:text="this is another right fragment."
      android:textSize="20sp" />
  • 同樣新建一個 AnotherRightFragment 類,代碼省略。

  • 修改 activity_main.xml 的代碼,將右側的 Fragment 放在 FrameLayout 中,代碼如下:

<fragment
    android:id="@+id/left_fragment"
    android:name="com.addict.fragmenttest.LeftFragment"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"></fragment>

<FrameLayout
    android:id="@+id/right_layout"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1">

    <fragment
        android:id="@+id/right_fragment"
        android:name="com.addict.fragmenttest.RightFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></fragment>
</FrameLayout>
  • 修改 MainActivity 中的代碼,在點擊 Button 是動態添加 Fragment,代碼如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button button = (Button) findViewById(R.id.button);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            AnotherRightFragment fragment = new AnotherRightFragment();
            FragmentManager fragmentManager = getFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.replace(R.id.right_layout, fragment);
            transaction.commit();
        }
    });
}

這樣就完成了,運行一下看看吧。小結一下動態添加 Fragment:

  1. 創建待添加的 Fragment 的實例。
  2. 獲取 FragmentManager,通過 getFragmentManager() 方法。
  3. 開啟事務。
  4. 向容器內加入 Fragment,使用 replace() 方法,參數為需要傳入的容器 id、待添加的 Fragment 實例。
  5. 提交事務。

利用返回棧管理 Fragment

運行之前的程序,點擊 Button 動態添加 Fragment 后,按下 Back 鍵我們發現程序直接退出了。那么能不能做到按 Back 鍵回到上一個 Fragment 呢?

超簡單,在這句代碼 transaction.commit(); 前再加一句代碼 transaction.addToBackStack(null); 就可以了,試試看吧。

2015-03-21 更正

按照上面寫的加上這句代碼 transaction.addToBackStack(null); 之后,我發現按下 Back 仍然沒有返回上一個 Fragment,還是直接退出程序了。Google Baidu 查了好久也沒弄明白原因。

寫了個解決辦法,在 MainActivity 中重寫了 onPressed() 方法,代碼如下:

@Override
// 按下 Back 按鈕時觸發
public void onBackPressed(){
    FragmentManager fragmentManager = getFragmentManager();
    // 判斷 BackStack 中是否有 FragmentTransaction
    if(fragmentManager.getBackStackEntryCount() > 0){
        // FragmentTransaction 出棧,恢復前一個 Fragment
        fragmentManager.popBackStack();
        return;
    }
    super.onBackPressed();
}

其它(Miscellaneous)

盡管我試圖在本文中盡量完整的進行描述,但受限於篇幅和我的個人水平,本文難免有所遺漏,歡迎在評論中指出。
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!

關於作者(About Me)

addict
原文鏈接:http://www.cnblogs.com/DebugLife/p/4355669.html

本文謝絕轉載,如需轉載需征得作者本人同意,謝謝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM