碎片(Fragment)Android 3.0发布出来
简单理解
简单地将它理解为一个控件。
碎片的特点
1)在其内部维护了自身的生命周期;
2)只有一个宿主(Activity),离开了宿主就不能生存了;
3)用于显示页面的一部分内容;
为什么要引入Fragment?
1)因为Fragment拥有自己的生命周期,可以在其实例中完成这部分的显示与隐藏,因此使得操 作逻辑与Activity分离,降低了
程序之间的耦合性;
2)Fragment实际上是为了解决平板电脑屏幕过宽,左边出现菜单栏,右边出现内容栏的布局效 果的;
Fragment的使用方式
[ 1 ]Fragment的静态应用:
<1>创建一个类继承于Fragment;
public class FirstFragment extends Fragment{ }<2>编写Fragment的布局文件;
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#f07" android:gravity="center" > <Button android:id="@+id/mBtnClick" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我是Fragment里面的Button" /> </LinearLayout><3>重写Fragment中的onCreateView方法,通过inflateer来加载布局文件,三个参数分别是 布局id,根,false;
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view=inflater.inflate(R.layout.first_fragment,container,false); Log.e("B----------------","我被执行了......."); return view; }<4>在需要碎片的布局文件中,可以直接声明一个Fragment,定义name和id。
<?xml version="1.0" encoding="utf-8"?> <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"> <fragment android:layout_width="match_parent" android:layout_height="300dp" android:name="com.com.qf.fragment.FirstFragment" android:id="@+id/firstFragment" > </fragment> </LinearLayout>
Fragment中的控件的事件的处理:
1)可以在Activity中直接通过findViewById来找到并使用;
2)可以在onCreateView方法中通过view.findViewById()来找到控件并使用;
3)可以在Fragment中通过获取其上下文然后找到id并使用。
注意:
1)Fragment当空间来使用的时候要定义id,否则会报错;
2)Fragment是在Activity上的,所以在Activity中可以找到Fragment中的控件;
3)在Fragment中是不包含有宿主的上下文的,我们要是想要获取那个宿主的上下文的话用 getActivity方法;
生命周期的11个方法:
1)public void onAttach(Activity activity);这个方法在低版本和高版本都可以用
2)public void onCreate( Bundle savedInstanceState);用于创建Fragment
3)public void onStart();可见不能获取焦点
4)public void onResume();获取焦点,此时碎片是可以进行交互的
5)public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState);绑定
View到Fragment
6)public void onActivityCreated(Bundle savedInstanceState);当宿主创建完成的时候调用 用来处理碎片的逻辑
7)public void onPause();不能获取焦点
8)public void onStop();不可见的方法回调
9)public void onDestroyView();销毁宿主上的Fragment的View
10)public void onDestroy();回收Fragment占用的资源
11)public void onDetach();清除Activity中资源
[ 2 ]Fragment的动态应用:
//1、通过上下文获取Fragment的管理者 FragmentManager manager = getFragmentManager();//app包 // getSupportFragmentManager();//v4包 //2、开启事务 FragmentTransaction fragmentTransaction = manager.beginTransaction(); //3、添加Fragment到这个容器中 fragmentTransaction.replace(R.id.contentPanel,fragment); //4、提交事务 fragmentTransaction.commit();
.replace方法的作用实际上是先清除容器中的Fragment(remove),然后再添加当前的 Fragment(add)。
如果每次都是用.replace方法的话,就是每次都要将前一个Fragment删除,再将后一个Fragment 添加上,会造成每次都需
要重新CreateView,那么如果我们连续的切换Fragment的话就会出现卡顿的现 象,因此需要进行优化。
优化步骤:
1)判断当前对象是否已经添加到ViewTree里面,如果已经添加了,将当前显示的Fragment给 hide掉,然后在显示已经添
加了的Fragment;如果还没有添加,可以直接通过事务的add方法添加 Fragment。
private void addContent(Fragment from,Fragment to) { FragmentTransaction ft = getFragmentManager().beginTransaction(); if(!to.isAdded()){ //判定那个Fragment是否已经被加载到了那个任务栈里面 ft.add(R.id.contentPanel,to); }else{ ft.hide(from).show(to); } ft.commit(); }
注意:当我们添加进一个Fragment,再向container中添加Fragment的话,前一个Fragment并不 会被kill掉,只是没有显
示。
回退栈
栈的存储模式:先进后出的存储模式
弹出栈
ft.popBackStack( ); 弹出栈内栈顶的Fragment;
ft.popBackStack("abc",mod); 弹出栈名为abc的Fragment以上或包含Fragment对象及以上的对 象
mod=1( );Fragment以上的对象
mod=0;包含Fragment及以上的对象
ft.popBackStack(commitId,0);指的是弹出的是指定id以上或者包含Fragment对象及以上的对象
id:ft.commit的返回值
ft.popBackStackImmediate();实际上弹栈的操作书写后并没有立刻执行,而是放在了Fragment的 队列中,此时调用这个方法就可以立即执行弹栈;
ft.popBackStackImmediate(commitId,0);立即执行弹栈中指定id的对象
ft.popBackStackImmediate("",0);立即执行指定tag的对象做弹栈操作
事务
一系列指令的集合,这一系列的指令要么全部执行,要么都不执行。
传值
Fragment向Activity传递数据,或项另外一个不相关的Fragment传递对象
1)定义一个接口回调;
2)在接口回调中声明一个回调方法;
public interface MyCallBack{ public void click(Fragment fragment,String data); }3)将接口对象至空;
MyCallBack mMyCallBack=null;4)让Activity实现定义的接口;
public class FragmentToFragmentActivity extends AppCompatActivity implements FirstFragment.MyCallBack{ }5)在Fragment的onActivityCreate方法中获取当前实现接口的对象getActivity();
@Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mMyCallBack= (MyCallBack) getActivity(); getActivity().findViewById(R.id.mBtnClick).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String result=((TextView)getActivity().findViewById(R.id.text)).getText().toString(); Log.e("----------------",result); } }); }6)在需要回调的位置进行回调。
@Override public void click(Fragment fragment, String data) { FragmentTransaction ft = getFragmentManager().beginTransaction(); //第三个参数表示的是一个Tag Bundle mBundle=new Bundle(); mBundle.putString("key",data); fragment.setArguments(mBundle); ft.add(R.id.content,fragment,"second"); ft.commit(); }
Fragment向点击之后跳转的Fragment传值
public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mMyCallBack= (MyCallBack) getActivity(); getActivity().findViewById(R.id.mBtnClick).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Fragment mFragment=FragmentFactory.getFragment(1); final FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction(); Bundle mBundle=new Bundle(); mBundle.putString("key","传递过来了"); mFragment.setArguments(mBundle); ft.add(R.id.content,mFragment); ft.commit(); } }); }