1.什么是Fragment?
Fragment(碎片)是一种可以嵌入在Activity中的UI片段,它能够:1.让合理和充分地利用大屏幕的空间,兼顾手机和平板(试想一下,对于同一份源代码,编译出的app同时能够在手机和平板上面运行,而不会出现控件或者图片过度拉伸的问题,这样岂不是很酷?对程序员来说也是福利啊);2.Fragment更轻量级,用Activity托管它,在视图的切换过程中,不用销毁Activity,只需要切换掉Activity托管的Fragment即可,这样可以提升软件运行的效率。
2.托管Fragment
(1)添加Fragment到activity布局中去。
(2)在Activity代码中添加Fragment。
第一种方法就是在Activity的XML布局文件中添加Fragment布局代码,这样就相当于将Fragment和Activity绑定,且在Activity的生命周期中不能切换Fragment试图。
第二种方法较第一种方法就更加灵活,可以在Activity活动生命周期内添加或者移除Fragment来完成某种具体的任务,但是在实现方面就比较复杂。
下面来介绍一下第二种托管方式:
(1)新建一个Fragment的布局文件(fragment_crime.xml)
(2)新建Fragment逻辑类()
(3)新建托管Activity类()
(4)新建托管Activity的布局文件()
3.Fragment之间通信
Fragment是由activity托管的,activity托管的fragment之间的通信只能通过activity来完成。
(1)从Fragment中启动另一个Activity
和Activity中启动Activity一样,用显示Intent
Intent intent = new Intent(getActivity(), SecondActivity.class); intent.putExtra("data_id", "data_value"); startActivity(intent); //这个startActivity()是FragmentActivity类中的函数,而不是Activity类中的startActivity(),getActivity()是获得托管该fragment的actvity
(2)从Fragment中启动Activity时附加信息(这个信息会用在另一个fragment中)
a.和Activity中启动Activity一样,用显示Intent附加消息.
首先,在FirstFragment.java中,传入参数:
Intent intent = new Intent(getActivity(), NewActivity.class); intent.putString("date_id", "data_value");//键是"data_id", 传递的值是"data_value" startActivity(intent);
然后,在SecondFragment.java中,取出参数:
一般是在onCreate()函数中
1 @Override 2 public void onCreate(){ 3 ... 5 String str = (String) getActivity().getSerializable("data_id"); 6 }//data_id是获得相应值的键(键值对形式存储)
b.使用Fragment argument.
使用Fragment argument的时候,有个公共静态自定义函数是必不可少的,他实现了Fragment的创建和参数(Bundle args)的绑定
例子如下:
1 public static SecondFragment newInstance(int crimeId){ 2 Bundle args = new Bundle(); 3 args.putSerializable("data_id", crimeId); 4 CrimeFragment fragment = new CrimeFragment(); 5 fragment.setArguments(args); 6 return fragment; 7 }
下面来说一下详细的实现过程(我要从FirstActivity托管的FirstFragment中启动SecondActivity托管的SecondFragment,并且在SecondFragment中使用FirstFragment中传过去的参数)
首先在SecondFragment中(SecondFragment.java)
实现一个公共静态自定义函数:
1 public static SecondFragment newInstance(int crimeId){ 2 Bundle args = new Bundle(); 3 args.putSerializable("data_id", crimeId); 4 CrimeFragment fragment = new CrimeFragment(); 5 fragment.setArguments(args); 6 return fragment; 7 }
然后在SecondActivityt中(SecondActivity.java):
createFragment()函数中,在返回这个Fragment之前,我们就将附带的参数从Intent中取出,添加到Fragment中,用SecondFragment.newInstance(crimeId)取代new CrimeFragment();
1 @Override 2 protected Fragment createFragment() { 3 // TODO Auto-generated method stub 4 //return new CrimeFragment(); 5 int crimeId = (int) getIntent().getSerializableExtra("data_id"); 6 return SecondFragment.newInstance(crimeId); 7 }
最后在SecondFragment中(SecondFragment.java)
一般是在onCreate()函数中获得附带的参数值,因为这个fragment一产生我们就要从该fragment中获得传过来的值,来进行接下来的操作。
在onCreate()函数中,获得fragment附带的值
1 @Override 2 public void onCreate(){ 3 ... 5 String str = (String) getArguments().getSerializable("data_id"); 6 }//EXTRA_CRIME_ID是获得相应值的键(键值对形式存储)
c.Fragment返回结果到Fragment(进一步实现Fragment返回结果到另一个Fragment)
前面a或者b都实现了从FirstFragment启动SecondFragment,并且传递参数过去,在这里要实现的就是当SecondFragment销毁的时候,能够返回参数到FirstFragment中
步骤如下:
(1)在FirstFragment中启动SecondFragment的事物提交前时设置目标fragment:
public void setTargetFragment(Fragment fragment, int requestCode)
该方法给该Fragment对象设置一个可选的目标。例如,如果该Fragment对象使用由另一个Fragment对象启动的,并且在想要把一个给定的结果返回给第一个Fragment对象时,就可以使用这个方法。
参数
fragment 该参数给Fragment对象指定一个接受结果的目标Fragment对象。
requestCode 可选的请求编码,为返回到onActivityResult(int, int, Intent)方法提供便利。
(2)在SecondFragment中实现一个回调目标函数(这是一个自定义函数,在有事件触发时调用它,如点击事件)
private void setResult(int resultCode)
1 private void sendResut(int resultCode){ 2 if (getTargetFragment() == null) {//判断是否有设置目标fragment 3 return; 4 } 5 Intent i = new Intent(); 6 i.putExtra("return_data_id", mDate);//用Intent传递返回值 7 8 getTargetFragment() 9 .onActivityResult(getTargetRequestCode(), resultCode, i); 10 //回调目标(FirstFragment)的onActivityResult函数 11 }
(3)在FirstFragment中重写onActivityResult(int requestCode, int resultCode, Intent data)函数
1 @Override 2 public void onActivityResult(int requestCode, int resultCode, Intent data) { 3 4 super.onActivityResult(requestCode, resultCode, data); 5 if (resultCode != Activity.RESULT_OK) { 6 return; 7 } 8 if (requestCode == REQUEST_DATE) { 9 //获取Intent中的值。 10 } 11 }
通过这三步,就能将SecondFragment中的值传递到FirstFragment。