Android Fragment綜合理解

兩種方法添加fragment到android layout中

一、在activity的layout文件中聲明fragment

      你可以像爲View一樣, 爲fragment指定layout屬性(sdk3.0以後).
      例子是一個有2個fragment的activity:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
     <fragment android:name="com.example.news.ArticleListFragment"
            android:id="@+id/list"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
     <fragment android:name="com.example.news.ArticleReaderFragment"
            android:id="@+id/viewer"
            android:layout_weight="2"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
  </LinearLayout>

<fragment> 中的 android:name 屬性指定了在layout中實例化的Fragment類. 

       當系統創建這個activity layout時, 它實例化每一個在layout中指定的fragment,並調用每一個上的onCreateView()方法,來獲取每一個fragment的layout. 系統將從fragment返回的 View 直接插入到<fragment>元素所在的地方. 

注意: 每一個fragment都需要一個唯一的標識, 如果activity重啓,系統可以用來恢復fragment(並且你也可以用來捕獲fragment來處理事務,例如移除它.) 

有3種方法來爲一個fragment提供一個標識:
  • 爲 android:id 屬性提供一個唯一ID.
  • 爲 android:tag 屬性提供一個唯一字符串.
  • 如果以上2個你都沒有提供, 系統使用容器view的ID.

二、使用FragmentManager將fragment添加到一個已存在的ViewGroup.


       當activity運行的任何時候, 都可以將fragment添加到activity layout.只需簡單的指定一個需要放置fragment的ViewGroup.爲了在你的activity中操作fragment事務(例如添加,移除,或代替一個fragment),必須使用來自 FragmentTransaction 的API.

可以按如下方法,從你的Activity取得一個 FragmentTransaction 的實例:

FragmentManager fragmentManager = getFragmentManager(); 

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();


然後你可以使用 add() 方法添加一個fragment, 指定要添加的fragment, 和要插入的view.

ExampleFragment fragment = new ExampleFragment();

fragmentTransaction.add(R.id.fragment_container, fragment); 

fragmentTransaction.commit();

      add()的第一個參數是fragment要放入的ViewGroup, 由resource ID指定, 第二個參數是需要添加的fragment.一旦用FragmentTransaction做了改變,爲了使改變生效,必須調用commit(). 

補充:

FragmentManage:

FragmentManager能夠實現管理activity中fragment. 通過調用activity的getFragmentManager()取得它的實例.

FragmentManager可以做如下一些事情:
1、使用findFragmentById() (用於在activity layout中提供一個UI的fragment)或findFragmentByTag()
   (適用於有或沒有UI的fragment)獲取activity中存在的fragment
2、將fragment從後臺堆棧中彈出, 使用 popBackStack() (模擬用戶按下BACK 命令).
3、使用addOnBackStackChangeListener()註冊一個監聽後臺堆棧變化的listener.
 

FragmentTransaction:

      FragmentTransaction對fragment進行添加,移除,替換,以及執行其他動作。
從 FragmentManager 獲得一個FragmentTransaction的實例 :

FragmentManager fragmentManager = getFragmentManager(); 
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

每一個事務都是同時要執行的一套變化.可以在一個給定的事務中設置你想執行的所有變化,使用諸如 add(), remove(), 和 replace().然後, 要給activity應用事務, 必須調用 commit().

在調用commit()之前, 你可能想調用 addToBackStack(),將事務添加到一個fragment事務的back stack. 這個back stack由activity管理, 並允許用戶通過按下 BACK 按鍵返回到前一個fragment狀態.

舉個例子, 這裏是如何將一個fragment替換爲另一個, 並在後臺堆棧中保留之前的狀態
// Create new fragment and transaction  
Fragment newFragment = new ExampleFragment(); 
FragmentTransaction transaction = getFragmentManager().beginTransaction();  

// Replace whatever is in the fragment_container view with this fragment,  
// and add the transaction to the back stack  
transaction.replace(R.id.fragment_container, newFragment); 
transaction.addToBackStack(null);  
// Commit the transaction  
transaction.commit();
在這個例子中, newFragment 替換了當前layout容器中的由R.id.fragment_container標識的fragment.通過調用 addToBackStack(), replace事務被保存到back stack, 因此用戶可以回退事務,並通過按下BACK按鍵帶回前一個fragment.

如果添加多個變化到事務(例如add()或remove())並調用addToBackStack(), 然後在你調用commit()之前的所有應用的變化會被作爲一個單個事務添加到後臺堆棧, BACK按鍵會將它們一起回退.

添加變化到 FragmentTransaction的順序不重要, 除以下例外:
  • 必須最後調用 commit().
  • 如果添加多個fragment到同一個容器, 那麼添加的順序決定了它們在view hierarchy中顯示的順序.
當執行一個移除fragment的事務時, 如果沒有調用 addToBackStack(), 那麼當事務提交後, 那個fragment會被銷燬,並且用戶不能導航回到它. 有鑑於此, 當移除一個fragment時,如果調用了 addToBackStack(), 那麼fragment會被停止, 如果用戶導航回來,它將會被恢復.

提示: 對於每一個fragment事務, 你可以應用一個事務動畫, 通過在提交事務之前調用setTransition()實現.

調用 commit() 並不立即執行事務.恰恰相反, 它將事務安排排期, 一旦準備好, 就在activity的UI線程上運行(主線程).如果有必要, 無論如何, 你可以從你的UI線程調用 executePendingTransactions() 來立即執行由commit()提交的事務. 但這麼做通常不必要, 除非事務是其他線程中的job的一個從屬.

警告: 你只能在activity保存它的狀態(當用戶離開activity)之前使用commit()提交事務.

如果你試圖在那個點之後提交, 會拋出一個異常.這是因爲如果activity需要被恢復, 提交之後的狀態可能會丟失.對於你覺得可以丟失提交的狀況, 使用 commitAllowingStateLoss().

 


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