1.定義
Fragment中文解釋是碎片的意思,主要用在大屏幕設備上,例如平板電腦上,支持更加動態和靈活的UI設計。Fragment在你的應用中相當於是一個模塊化和可重用的組件,因為Fragment定義了它自己的布局,以及通過使用它自己的生命周期回調方法定義了它自己的行為,你可以將Fragment包含到多個Activity中。
2.特點
(1)Fragment可以作為Activity界面的一部分組成出現;
(2)可以在一個Activity中同時出現多個Fragment,並且一個Fragment也可以在多個Activity中使用;
(3)在Activity運行過程中,可以添加、移除或者替換Fragment;
(4)Fragment可以響應自己的輸入事件,並且有自己的生命周期,它們的生命周期會受宿主Activity的生命周期影響。
3.生命周期
Fragment必須是依存於Activity而存在的,因此Activity的生命周期會直接影響到Fragment的生命周期。
生命周期中涉及的方法如上圖所示,具體觸發條件如下所述。4.靜態加載
這是使用Fragment最簡單的一種方式,把Fragment當成普通的控件,直接寫在Activity的布局文件中,用布局文件調用Fragment。
(1)新建Fragment,重寫onCreateView決定Fragment布局
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_static, container, false); }(2)在宿主Activity中手動添加Fragment,就把它當做普通的控件一樣,在xml文件中使用。name屬性填寫fragment的包路徑,Activity通過findFragmentById()或者findFragmentByTag()獲取Fragment。
<fragment Android:name="ant.snail.com.fragmentactapp.StaticFragment" android:layout_width="wrap_content" android:layout_height="wrap_content" android:tag="newfrag" />
這樣在宿主Activity中就能看到Fragment了。
5.動態加載
上面的靜態加載是最基本的方法,下面解析下動態加載的原理。
(1)原理
動態加載,顧名思義是通過代碼的方式在Activity中加載Fragment。
通過撰寫代碼將Fragment添加到一個Activity layout中,這裡需要采用Fragment的事務處理(FragmentTransaction),有點類似數據庫的事務處理。
(2)具體實現
通過新建兩個Fragment,並在這兩個Fragment的Layout中添加了ImageView,用來放置圖片,而在宿主Activity中將這兩個Fragment動態切換,實現圖片的自由切換。代碼結構如下圖所示。
新建Fragment(Image1Fragment,Image2Fragment),並添加了兩個layout文件(fragment_image1,fragment_image2),其中部分代碼如下:
Image1Fragmet代碼:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // 獲取Fragment的View View view=inflater.inflate(R.layout.fragment_image1,container,false);
return view; }
fragment_image1.xml文件代碼如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center_horizontal" tools:context="ant.snail.com.fragmentactapp.Image1Fragment" > <!-- TODO: Update blank fragment layout --> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:gravity="center" > <TextView android:id="@+id/text1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我是jin兔1"/> <Button android:layout_marginLeft="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="傳遞數據到主窗口" android:id="@+id/btfr1" /> </LinearLayout> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/imageView1" android:src="@drawable/jin1"/> </LinearLayout>
宿主MainActivity的代碼如下,通過FragmentManager得到FragmentTransaction,然後通過replace()方法實現兩個Fragment之間的切換,最後實現了Commit()方法:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //獲取兩個按鈕的View bt1=(Button)findViewById(R.id.bt1); bt2=(Button)findViewById(R.id.bt2); bt1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //主Activity動態加載Fragment FragmentManager fragmentManager=getFragmentManager(); //處理Fragment事務 FragmentTransaction beginTransaction=fragmentManager.beginTransaction(); //獲取Image1Fragment實例 Image1Fragment image1Fragment=Image1Fragment.newInstance("Activity傳遞圖片1到Fragment中"); //替換操作 beginTransaction.replace(R.id.imageLayout,image1Fragment); //允許用戶通過按下BACK按鍵返回到前一個Fragment狀態 beginTransaction.addToBackStack(null); beginTransaction.commit(); } }); bt2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //主Activity動態加載Fragment FragmentManager fragmentManager=getFragmentManager(); //處理Fragment事務 FragmentTransaction beginTransaction=fragmentManager.beginTransaction(); //獲取Image1Fragment實例 Image2Fragment image2Fragment=Image2Fragment.newInstance("Activity傳遞圖片2到Fragment中"); //替換操作 beginTransaction.replace(R.id.imageLayout,image2Fragment); //允許用戶通過按下BACK按鍵返回到前一個Fragment狀態 beginTransaction.addToBackStack(null); beginTransaction.commit(); } }); }
其中NewInstance方法是在Fragment中實現的一個實例方法,用於將Fragment實例化,通過參數param1的傳遞能將Activity中的數據傳遞到Fragment中。通過setArguments()以及getArguments()實現數據從Activity向Fragment傳遞的目的,如下圖所示。
public static Image1Fragment newInstance(String param1) { Image1Fragment fragment = new Image1Fragment(); //在Activity中創建Bundle數據包,並調用Fragment的setArguments(Bundle bundle)方法 Bundle args = new Bundle(); args.putString(ARG_PARAM1, param1); fragment.setArguments(args); return fragment; }
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { //在Fragment中通過getArguments().getString()獲取Activity傳來的值 mParam1 = getArguments().getString(ARG_PARAM1); } }
6.Fragment與Activity通信
public interface OnFragmentInteractionListener { public void onFragmentInteraction(String uri); }
在Fragment的onAttach()方法中將Activity轉換為OnFragmentInteractionListener接口:
@Override public void onAttach(Activity activity) { super.onAttach(activity); try { mListener = (OnFragmentInteractionListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener"); } }
private OnFragmentInteractionListener mListener;
if (mListener != null) {
mListener.onFragmentInteraction("需要傳遞給Activity的值");
宿主Activity則需要實現此接口,並重寫onFragmentInteraction(String uri)方法,這樣就實現了數據從Fragment到Activity的傳遞:
public class MainActivity extends ActionBarActivity implements Image1Fragment.OnFragmentInteractionListener
@Override
public void onFragmentInteraction(String uri) {
TextView tv=(TextView)findViewById(R.id.tt);
tv.setText(uri);
}
7.效果截圖
本人致力於Web端與移動端的開發與研究,現主要從事GIS相關開發,如WebGIS、移動GIS開發等。更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11