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的生命周期重走一遍了。