1.Fragment的设计哲学
Android在3.0中引入了Fragments的概念,主要目的是用在大屏幕设备上,支持更加动态和灵活的UI设计,例如平板电脑上,它的屏幕比手机大很多,会存在许多需要交互的UI组件,这时我们就需要用到Fragment了。从下图中我们可以看到Fragment的实际应用。
Fragment在你的应用中应当是一个模块化和可重用的组件,因为Fragment定义了它自己的布局,以及通过使用它自己的生命周期回调方法定义了它自己的行为,你可以将Fragment包含到多个Activity中。
2.Fragment的知识概要
(1) Fragment可以作为Activity界面的一部分组成出现;
(2) 可以在一个Activity中同时出现多个Fragment,并且一个Fragment也可以在多个Activity中使用;
(3) 在Activity运行过程中,可以添加、移除或替换Fragment;
(4) Fragment可以响应自己的输入事件,并且有自己的生命周期,它们的生命周期会受宿主Activity的生命周期影响
onCreatView()方法:
Fragment第一次绘制它的用户界面的时候,系统会调用此方法,为了绘制Fragment的UI,此方法必须返回一个View(Fragment要显示的视图),如果不显示UI,返回null即可。
3.Fragment的加载
3.1. 静态加载
在Activity的layout文件中声明Fragment,需要特别注意的是<fragment>中的android:name属性(name属性的值是Fragment所在类的包名)指定了在layout中实例化的Fragment类。标识Fragment的方法:
android:id属性提供一个唯一的ID;
android:tag属性提供一个唯一字符串;
静态加载实例:以androidstdio为运行环境。
图2为整个实例的运行界面与工程目录中主要代码的之间的对应关系。
对页面布局的重点描述:
MainActivity.java为主窗口,其布局为main.xml,点击主窗口里的“静态加载”后跳到了窗口MainActivity2.java(盛放fragment的activity),其布局为main2.xml文件,main2.xml里有如下代码:
该代码是用于声明Fragment的。MyFragment.java是上面代码声明Fragment的实现类,fragment.xml文件为MyFragment.java的布局,MyFragment.java的重要代码:
为了绘制fragment的UI,在调用onCreateView方法时,需要将fragment的布局文件fragment.xml转化为一个View对象。
还有个重点是:就是按钮“改变”的点击效果,“改变”按钮控件是放置布局fragment.xml里的,但其的点击事件是在MainActivity.java中实现的,主要目的是为了说明Activity可以获取到寄宿在它里面的fragment的布局的控件,并可以操作其控件的属性。
3.2. 动态加载
撰写代码将Fragment添加到一个Avtivity中,add():添加一个Fragment(指定要添加的的Fragment和插入的view),与此类似的还有remove()、替换replace()。
处理Fragment事务:根据用户的交互情况,对Fragment进行添加、移除、替换,以及执行其它动作,提交给Activity的每一套变化被称作一个事务。
//获取管理者
FragmentManager fragmentManager = getFragmentManager();
/创建事务 FragmentTransaction beginTransaction = fragmentManager.beginTransaction();
每一个事务都是同时执行一套变化,可以在一个事务中可以设置你所有想执行的变化,包括add()、remove()、replace()、然后提交给activity,必须调用commit方法。如果用户通过按下back键返回到前一个Fragment状态,调用commit之前可以加入addToBackStack()方法。
动态加载实例:
效果图:
MainActivity.java //点击动态加载时,所触发的事件 //要添加的Fragment MyFragment2 fragment2=newMyFragment2(); //获得Fragment的管理器 FragmentTransaction beginTransaction = fragmentManager.beginTransaction(); //往MainActivity.java的布局main.xml里id名为frame的控件中添加Fragment //返回键的效果 |
4 .Fragment的生命周期
观察生命周期的步骤:启动Fragment——>屏幕锁屏——>屏幕解锁——>
切换到其他的Fragment——>回到桌面——>回到应用——>退出Fragment
每一步会调用的方法:
(1) 启动Fragment:Fragment1---onAttach() Fragment1---onCreate()
Fragment1---onCreateView() Fragment1---onActivityCreated()
Fragment1---onStart() Fragment1---onResume()
(2) 屏幕锁屏:Fragment1---onPause() Fragment1---onStop()
(3) 屏幕解锁:Fragment1---onStart() Fragment1---onResume()
(4) 切换到其他的Fragment:Fragment1---onPause() Fragment1---onStop()
Fragment1---onDestroyView() Fragment1---onDestroy()
Fragment1---onDetach() Fragment2---onAttach()
Fragment2---onCreate() Fragment2---onCreateView()
Fragment2---onActivityCreated() Fragment2---onStart()
Fragment2---onResume()
(5) 回到桌面:Fragment2---onPause() Fragment2---onStop()
(6) 回到应用:Fragment2---onStart() Fragment2---onResume()
(7) 退出Fragment:Fragment2---onPause() Fragment2---onStop()
Fragment2---onDestroyView() Fragment2---onDestroy()
Fragment2---onDetach()
onCreateView:每次创建都会绘制Fragment的View组件时回调该方法;
onAttach: 当Fragment被添加到Activity时候会回调这个方法,并且只调用一次;
onCreate:创建Fragment时会回调,只会调用一次;
onActivityCreated:当Fragment所在的Activty启动完成后调用;
onStart : 启动Fragment;
onResume : 恢复Fragment时会被回调,调用onStart()方法后面一定会调用onResume()方法;
onPause: 暂停Fragment;
onStop :停止Fragment;
onDestroyView(): 销毁Fragment所包含的View组件时;
onDestroy:销毁Fragment时会被回调;
onDetach : Fragment从Activity中删除时会回调该方法,并且这个方法只会调用一次;
实例:
点击生命周期后的效果图:
MainActivity.java //点击生命周期 |
MainActivity3.java public class MainActivity3extendsActivity { //一开始显示的是MyFragment3 //点击按钮可以切换到MyFragment4, |
5. Fragment的传值通信
Activity-----Fragment:在Activity中创建Bundle数据包,并调用Fragment的setArguments(Bundle bundle)方法。
Fragment-----Activity:需要在Fragment中定义一个内部回调接口再让包含该Fragment的Activity实现该回调接口,这样Fragment可调用该回调方法将数据传递给Activity。
点击传值通信的效果图:
MainActivity4.java public class MainActivity4 extends Activity implements MyFragment5.MyListener { private EditText editext; private Button send; @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.main4); editext = (EditText) findViewById(R.id.editText); send = (Button) findViewById(R.id.send); send.setOnClickListener(new OnClickListener() { @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override public void onClick(View v) { // TODO Auto-generated method stub String text = editext.getText().toString(); MyFragment5 fragment5 = new MyFragment5(); Bundle bundle = new Bundle(); bundle.putString("name", text); fragment5.setArguments(bundle); FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction beginTransaction = fragmentManager .beginTransaction(); beginTransaction.add(R.id.layout, fragment5, "fragment5"); beginTransaction.commit(); Toast.makeText(MainActivity4.this, "向Fragment发送数据" + text, Toast.LENGTH_SHORT).show(); } }); //Fragment静态传值 FragmentManager fragmentManager = getFragmentManager(); Fragment findFragmentById = fragmentManager.findFragmentById(R.id.frag); MyFragment frag=(MyFragment) findFragmentById; frag.setAaa("fragment静态传值"); } @Override public void thank(String code) { // TODO Auto-generated method stub Toast.makeText(MainActivity4.this, "已成功接收到" + code + ",客气了!", Toast.LENGTH_SHORT).show(); } } |
MyFragment5.java public class MyFragment5 extends Fragment { private String code="Thank you,Activity!"; public MyListener listener; public interface MyListener { public void thank(String code); } @Override public void onAttach(Activity activity) { // TODO Auto-generated method stub listener=(MyListener) activity; super.onAttach(activity); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub View view = inflater.inflate(R.layout.fragment2, container, false); TextView tv = (TextView) view.findViewById(R.id.text); String text=getArguments().get("name")+""; tv.setText(text); Toast.makeText(getActivity(), "已成功接收到"+text, Toast.LENGTH_SHORT).show(); Toast.makeText(getActivity(), "向Activity发送"+code, Toast.LENGTH_SHORT).show(); listener.thank(code); return view; } } |
Main4.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <EditText android:id="@+id/editText" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="发送" /> <!--用于静态传值的--> <fragment android:id="@+id/frag" android:name="com.imooc.fragment.MyFragment" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> |