1.Fragment的初衷:爲了讓界面能夠在平板上更好地展現,Android在3.0版本引入了Fragment(碎片)功能,它很是相似於Activity,能夠像Activity同樣包含佈局。Fragment一般是嵌套在Activity中使用的。須要注意,Fragment是在3.0版本引入的,若是你使用的是3.0以前的系統,須要先導入android-support-v4的jar包才能使用Fragment功能。android
靜態生成微信
1.Fragment的layout.xml配置文件fragment1:全部的Activity中能使用的佈局在fragment中都能使用,其使用方式也同樣如:ide
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="match_parent" 3 android:layout_height="match_parent" 4 android:background="#ffff00" > 5 6 <TextView 7 android:layout_width="wrap_content" 8 android:layout_height="wrap_content" 9 android:text="This is fragment 2" 10 android:textColor="#000000" 11 android:textSize="25sp" /> 12 <ImagView 13 <ListView 14 . 15 . 16 . 17 18 </LinearLayout>
2.建立Fragment類Fragment1:繼承自Fragment並重寫onCreateView()方法佈局
1 public class Fragment1 extends Fragment { 2 3 @Override 4 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 5 //R.layout.fragment1:fragment的layout.xml配置文件 6 return inflater.inflate(R.layout.fragment1, container, false); 7 } 8 }
3.在Main_Activity中的layout配置文件中加入Fragment1引用:使用android:name前綴來引用具體的Fragment:spa
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:baselineAligned="false" > <fragment android:id="@+id/fragment1" android:name="com.example.fragmentdemo.Fragment1" android:layout_width="0dip" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout>
4.運行Main_Activity則能夠看到在fragment1佈局文件中的UI控件:自動生成code
1 public class MainActivity extends Activity { 2 3 @Override 4 protected void onCreate(Bundle savedInstanceState) { 5 super.onCreate(savedInstanceState); 6 setContentView(R.layout.activity_main); 7 } 8 9 }
動態生成:Fragment真正的強大之處在於能夠動態地添加到Activity當中,所以這也是你必需要掌握的東西。當你學會了在程序運行時向Activity添加Fragment,程序的界面就能夠定製的更加多樣化。xml
1.獲取到FragmentManager,在Activity中能夠直接經過getFragmentManager獲得。對象
2.開啓一個事務,經過調用beginTransaction方法開啓。blog
3.向容器內加入Fragment,通常使用replace方法實現,須要傳入容器的id和Fragment的實例。繼承
4.提交事務,調用commit方法提交。
如上例:將其中對Fragment的引用都刪除,只保留最外層的LinearLayout,並給它添加一個id,由於咱們要動態添加Fragment,不用在XML裏添加了
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:id="@+id/main_layout" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:baselineAligned="false" > 6 </LinearLayout>
打開MainActivity,修改其中的代碼:
1 public class MainActivity extends Activity { 2 3 @Override 4 protected void onCreate(Bundle savedInstanceState) { 5 super.onCreate(savedInstanceState); 6 setContentView(R.layout.activity_main);
//獲取屏幕對象引用 7 Display display = getWindowManager().getDefaultDisplay();
//根據屏幕的寬,高添加不一樣的fragment 8 if (display.getWidth() > display.getHeight()) { 9 Fragment1 fragment1 = new Fragment1(); 10 getFragmentManager().beginTransaction().replace(R.id.main_layout, fragment1).commit(); 11 } else { 12 Fragment2 fragment2 = new Fragment2(); 13 getFragmentManager().beginTransaction().replace(R.id.main_layout, fragment2).commit(); 14 } 15 } 17 }
Fragment的生命週期:與Activity的生命週期很類似
Fragment之間進行通訊:在同一個Activity中通常有多個Fragment,Fragment之間的通訊通常經過getActivity()來獲得相關聯的Activity對象,
經過Activity對象中的findViewById()方法找到其它控件,進而達到Fragment交互。通常經過Fragment的生命週期來控制
1 public class Fragment2 extends Fragment { 2 3 @Override 4 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 5 return inflater.inflate(R.layout.fragment2, container, false); 6 } 8 @Override 9 public void onActivityCreated(Bundle savedInstanceState) { 10 super.onActivityCreated(savedInstanceState); 11 Button button = (Button) getActivity().findViewById(R.id.button); 12 button.setOnClickListener(new OnClickListener() { 13 @Override 14 public void onClick(View v) {
//經過fragment2中的按鈕事件來觸發拿到fragment1中的textView 15 TextView textView = (TextView) getActivity().findViewById(R.id.fragment1_text); 16 Toast.makeText(getActivity(), textView.getText(), Toast.LENGTH_LONG).show(); 17 } 18 }); 19 } 21 }
Fragment碎片替代ActivityGroup:實現導航(QQ,微信,,,,)
1.整個Activity佈局爲一個fragment,及四個由ImagView,TextView組成的相似按鈕的控件組成。
2.Activity中的主要代碼邏輯:
1 public class MainActivity extends Activity implements OnClickListener { 2 @Override 3 protected void onCreate(Bundle savedInstanceState) { 4 super.onCreate(savedInstanceState); 5 requestWindowFeature(Window.FEATURE_NO_TITLE); 6 setContentView(R.layout.activity_main); 7 // 初始化佈局元素 8 initViews(); 9 fragmentManager = getFragmentManager(); 10 // 第一次啓動時選中第0個tab 11 setTabSelection(0); 12 } 13 @Override 14 public void onClick(View v) { 15 switch (v.getId()) { 16 case R.id.message_layout: 17 // 當點擊了消息tab時,選中第1個tab 18 setTabSelection(0); 19 break; 20 case R.id.contacts_layout: 21 // 當點擊了聯繫人tab時,選中第2個tab 22 setTabSelection(1); 23 break; 24 case R.id.news_layout: 25 // 當點擊了動態tab時,選中第3個tab 26 setTabSelection(2); 27 break; 28 case R.id.setting_layout: 29 // 當點擊了設置tab時,選中第4個tab 30 setTabSelection(3); 31 break; 32 default: 33 break; 34 } 35 } 36 private void setTabSelection(int index) { 37 // 每次選中以前先清楚掉上次的選中狀態 38 clearSelection(); 39 // 開啓一個Fragment事務 40 FragmentTransaction transaction = fragmentManager.beginTransaction(); 41 // 先隱藏掉全部的Fragment,以防止有多個Fragment顯示在界面上的狀況 42 hideFragments(transaction); 43 switch (index) { 44 case 0: 45 // 當點擊了消息tab時,改變控件的圖片和文字顏色 46 messageImage.setImageResource(R.drawable.message_selected); 47 messageText.setTextColor(Color.WHITE); 48 if (messageFragment == null) { 49 // 若是MessageFragment爲空,則建立一個並添加到界面上 50 messageFragment = new MessageFragment(); 51 transaction.add(R.id.content, messageFragment); 52 } else { 53 // 若是MessageFragment不爲空,則直接將它顯示出來 54 transaction.show(messageFragment); 55 } 56 break; 57 case 1: 58 // 當點擊了聯繫人tab時,改變控件的圖片和文字顏色 59 contactsImage.setImageResource(R.drawable.contacts_selected); 60 contactsText.setTextColor(Color.WHITE); 61 if (contactsFragment == null) { 62 // 若是ContactsFragment爲空,則建立一個並添加到界面上 63 contactsFragment = new ContactsFragment(); 64 transaction.add(R.id.content, contactsFragment); 65 } else { 66 // 若是ContactsFragment不爲空,則直接將它顯示出來 67 transaction.show(contactsFragment); 68 } 69 break; 70 case 2: 71 // 當點擊了動態tab時,改變控件的圖片和文字顏色 72 newsImage.setImageResource(R.drawable.news_selected); 73 newsText.setTextColor(Color.WHITE); 74 if (newsFragment == null) { 75 // 若是NewsFragment爲空,則建立一個並添加到界面上 76 newsFragment = new NewsFragment(); 77 transaction.add(R.id.content, newsFragment); 78 } else { 79 // 若是NewsFragment不爲空,則直接將它顯示出來 80 transaction.show(newsFragment); 81 } 82 break; 83 case 3: 84 default: 85 // 當點擊了設置tab時,改變控件的圖片和文字顏色 86 settingImage.setImageResource(R.drawable.setting_selected); 87 settingText.setTextColor(Color.WHITE); 88 if (settingFragment == null) { 89 // 若是SettingFragment爲空,則建立一個並添加到界面上 90 settingFragment = new SettingFragment(); 91 transaction.add(R.id.content, settingFragment); 92 } else { 93 // 若是SettingFragment不爲空,則直接將它顯示出來 94 transaction.show(settingFragment); 95 } 96 break; 97 } 98 transaction.commit(); 99 } 100 101 /** 102 * 清除掉全部的選中狀態。 103 */ 104 private void clearSelection() { 105 messageImage.setImageResource(R.drawable.message_unselected); 106 messageText.setTextColor(Color.parseColor("#82858b")); 107 contactsImage.setImageResource(R.drawable.contacts_unselected); 108 contactsText.setTextColor(Color.parseColor("#82858b")); 109 newsImage.setImageResource(R.drawable.news_unselected); 110 newsText.setTextColor(Color.parseColor("#82858b")); 111 settingImage.setImageResource(R.drawable.setting_unselected); 112 settingText.setTextColor(Color.parseColor("#82858b")); 113 } 114 115 /** 116 * 將全部的Fragment都置爲隱藏狀態。 117 * 118 * @param transaction 119 * 用於對Fragment執行操做的事務 120 */ 121 private void hideFragments(FragmentTransaction transaction) { 122 if (messageFragment != null) { 123 transaction.hide(messageFragment); 124 } 125 if (contactsFragment != null) { 126 transaction.hide(contactsFragment); 127 } 128 if (newsFragment != null) { 129 transaction.hide(newsFragment); 130 } 131 if (settingFragment != null) { 132 transaction.hide(settingFragment); 133 } 134 } 135 }
主要邏輯功能實現:首先第一步是調用clearSelection()方法來清理掉以前的選中狀態,而後開啓一個Fragment事務,並隱藏掉全部的Fragment,以防止有多個Fragment顯示在界面上。接下來根據傳入的index參數判斷出選中的是哪個Tab項,並改變該Tab項的圖標和文字顏色,而後將相應的Fragment添加到界面上。這裏注意一個細節,咱們添加Fragment的時候並無使用replace()方法,而是會先判斷一下該Fragment是否爲空,若是是空的則調用add()方法添加一個進來,若是不是空的則直接調用show()方法顯示出來便可。那麼爲何沒有使用replace()方法呢?這是由於replace()方法會將被替換掉的那個Fragment完全地移除掉,該Fragment的生命週期就結束了。當再次點擊剛纔那個Tab項的時候,就會讓該Fragment的生命週期從新開始,onCreate()、onCreateView()等方法都會從新執行一遍。這顯然不是咱們想要的,也和ActivityGroup的工做原理不符,所以最好的解決方案就是使用hide()和show()方法來隱藏和顯示Fragment,這就不會讓Fragment的生命週期重走一遍了。