转载的老板请注明出处: http://blog.csdn.net/cc_xz/article/details/61618922 万分感谢! 前言:
本篇为UI组件的第二篇,主要探讨关于Fragment的基本使用,包括简单的原理以及创建、修改、删除等操作。
在本篇文章中,你将了解到: 1.什么是Fragment。 2.Fragment的生命周期。 3.Fragment的基本使用。
什么是Fragment? 由于Android是一款开源的系统,在国内外不同的厂商研发出了很多不同的机型,甚至将Android应用到了平板中,但是这意味着不同厂商出产的手机、平板的屏幕大小不一,例如,组件排版安装5.0寸手机制作的程序,如果在4.7寸的手机上,视觉效果体验虽说会降低,但也不至于不可接受。但是如果放到6.0寸的手机,乃至平板上,用户的视觉体验会大幅度降低。 这就导致了Android研发的工作中有比较大的比重的分辨率匹配,而Fragment则是用来解决这一问题的。 这是因为,Fragment是依赖于Activity的,在Activity的布局中创建一个FrameLayout组件,就可以在上面根据不同的需要显示很多个Fragment(当然不能同时显示)。并且Fragment有自己的生命周期、自己的布局文件、独立的事件处理,极端的说,你甚至可以把一个Fragment当做一个Activity来使用。
Fragment的生命周期 前面说过,Fragment是依赖于Activity的,即必须先创建Activity,再创建Fragment,并且Fragment的生命周期细节上同Activity所有不同,但仍是可以对应参考的。先来看一下Google官方给出的Fragment与Activity生命周期对照表: 我们现在来简单解释一下Fragment多出来的生命周期: onAttach(): 当Fragment与Activity发生关联时调用该方法。 onCreateView(): 在Fragment中初始化Layout、初始化组件时使用。 onActivityCreated(): 当Activity的onCreate()返回时调用。 onDestoryView(): 与onCreateView想对应,当该Fragment的视图被移除时调用。 onDetach(): 与onAttach相对应,当Fragment与Activity关联被取消时调用。 另外,值得注意的是,除了onCreateView()外,如果你重写了其他方法,则必须调用spue使父类来实现该方法。
准备工作: 本案例中计划使用动态添加Fragment的方式,来分别在同一个FrameLayout组件中分别显示两个不同的Fragment,并且完成替换、删除、在Fragment中修改Activity的内容,以及在Activity中修改Fragment的内容等操作。 首先来看一下效果图:
接着开始进行一些初始化等准备工作,代码如下: 以下代码在activity_main中写入:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="30dp" android:layout_gravity="center_vertical" android:text="这里是MainActivity" android:textSize="18sp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:orientation="horizontal"> <Button android:id="@+id/ButtonShowFragmentNow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="显示FragmentNow" android:textAllCaps="false" /> <Button android:id="@+id/ButtonShowFragmentTwo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="显示FragmentTwo" android:textAllCaps="false" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:orientation="horizontal"> <Button android:id="@+id/ButtonAmendFragmentTwo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="修改FragmentTwo" android:textAllCaps="false" /> <Button android:id="@+id/ButtonReplaceFragmentNow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="替换" /> <Button android:id="@+id/ButtonDeleteFragmentNow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="删除FragmentNow" android:textAllCaps="false" /> </LinearLayout> <TextView android:id="@+id/TextView" android:layout_width="match_parent" android:layout_height="20dp" android:layout_gravity="center_horizontal" android:layout_marginBottom="5dp" android:text="这就是用来被Fragment修改的" android:textAllCaps="false" android:textSize="18sp" /> <FrameLayout android:id="@+id/FrameLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#D02090" /> </LinearLayout>值得注意的是,在FrameLayout中添加了背景颜色,如果没有显示Fragment,则显示背景颜色,如果添加了Fragment,则显示Fragment布局文件中定义的颜色。
以下代码在fragment_now中写入:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#9aff9a"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/ButtonFragmentNow" android:text="修改Activity" android:textAllCaps="false" android:layout_gravity="center"/> </LinearLayout>以下代码在fragment_two中写入:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#d1eeee" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/TextVIewFragmentTwo" android:text="注定被修改" android:layout_gravity="center" android:textSize="30sp"/> </LinearLayout>开始创建Fragment: 在上面的准备工作中,创建了一个FrameLayout组件,而Fragment就会显示在该组件中。另外创建了两个布局文件,这两个布局文件就分别对应两个不同的Fragment。以下首先来看代码思路:
1.首先定义FragmentNow以及FragmentTwo。。 2.接着初始化所需的组件,并设置Button的监听器 3.通过完整的代码显示FragmentNow。 4.通过简略的代码显示fragmentTwo。 5.设置Fragment直接的自由替换。 6.一些其他的应用说明。
以下代码分别在FragmentNow/Two中写入:
/* 代码执行1: * 1.在创建Fragment时,需要继承自v4.app.Fragment中的Fragment。 * 2.然后创建View对象,用户获取Fragment所需的Layout。 * 3.onCreateView是用于初始化Fragment的视图。 * 4.Amend()用于在Activity中调用该方法,来修改Fragment中的内容。*/ public class FragmentTwo extends Fragment { private View mView; private TextView mTextView; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mView = inflater.inflate(R.layout.fragment_two, null); return mView; } public void Amend(){ mTextView = (TextView) mView.findViewById(R.id.TextVIewFragmentTwo); mTextView.setText("这是FragmentTwo中已经被修改了的值"); } } public class FragmentNow extends Fragment { private View mView; private Button mButton; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mView = inflater.inflate(R.layout.fragment_now, null); mButton = (Button) mView.findViewById(R.id.ButtonFragmentNow); return mView; } /* 代码执行1: * 1.1.由于初始化视图必须在onCreateView()中完成,如果向Activity一样在onCreate()中调用Button是不可以的。 * 1.2.这是因为onCreate()在onCreateView()之前就被调用,如果此时在onCreate()中调用Button,会显示空指针。 * */ @Override public void onStart() { super.onStart(); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MainActivity mainActivity = (MainActivity) getActivity(); mainActivity.Amend(); } }); } }以下代码在MainActivity中写入:
/* 代码执行2: * 1.首先将两个Fragment类创建为对象。用于通过该对象来配合FrameLayout显示fragment。 * 2.然后获得各个Button的ID。 * 3.定义一个boolean类型的变量,用于替换时的循环。 * 4.注意别忘了在onCreate()中调用init()。*/ private void init() { mFragmentNow = new FragmentNow(); mFragmentTwo = new FragmentTwo(); mButtonShowFragmentNow = (Button) findViewById(R.id.ButtonShowFragmentNow); mButtonShowFragmentTwo = (Button) findViewById(R.id.ButtonShowFragmentTwo); mButtonAmendFragmentTwo = (Button) findViewById(R.id.ButtonAmendFragmentTwo); mButtonReplaceFragmentNow = (Button) findViewById(R.id.ButtonReplaceFragmentNow); mButtonDeleteFragmentNow = (Button) findViewById(R.id.ButtonDeleteFragmentNow); mBoolean = true; }以下代码在MainActivity的onCreate()中写入:
mButtonShowFragmentNow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /* 代码执行3: * 1.1.首先通过Fragment管理器创建一个Fragment对象, * 1.2.通过getSupportFragmentManager来返回同Activity进行关联并交互的Fragment对象。 * 2.再将已经创建好的Fragment放置到Fragment事务队列中。等待Activity的处理。 * 3.告知该Fragment事务它的显示位置(在哪个组件上显示),而Fragment所需的逻辑代码在哪个类中(通过对象引用)。 * 4.这时将Fragment正式提交到Fragment队列中,使Activity进行处理。*/ FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.replace(R.id.FrameLayout, mFragmentNow); fragmentTransaction.commit(); } });以下代码在MainActivity的onCreate()中写入:
mButtonShowFragmentTwo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /* 代码执行4: * 1.使用精简的方式创建Fragment。并且不使用.add,因为使用.add创建当用户连续点击后,程序将结束运行。 * */ getSupportFragmentManager().beginTransaction() .replace(R.id.FrameLayout, mFragmentTwo).commit(); } });以下代码在MainActivity的onCreate()中写入:
mButtonReplaceFragmentNow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /* 代码执行5: * 1.替换Activity。由于只有一个Fragment显示位置,所以只能同时显示一个。 * 2.每次替换完成后,则修改mBoolean的值,防止陷入死循环。 * 3.但以上方式会存在一点瑕疵:当当前显示的是mFragment1(默认为真,第一次替换mFragment1)时,第一次点击将(无效果),需要点击两次,反之同理。 * */ if (mBoolean) { getSupportFragmentManager().beginTransaction() .replace(R.id.FrameLayout, mFragmentNow).commit(); mBoolean = false; } else { getSupportFragmentManager().beginTransaction() .replace(R.id.FrameLayout, mFragmentTwo).commit(); mBoolean = true; } } });以下代码在MainActivity的onCreate()中写入:
mButtonAmendFragmentTwo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /* 代码执行6: * 1.在Activity中通过Fragment对象调用其中的方法。*/ mFragmentTwo.Amend(); } }); mButtonDeleteFragmentNow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /* 代码执行6: * 1.如果你希望删除Fragment,则使用remove方法即可,通过将Fragment对象作为参数。。*/ getSupportFragmentManager().beginTransaction() .remove(mFragmentNow).commit(); } });以下代码在MainActivity中写入:
/* 代码执行6: * 1.同理,在Activity中创建公共方法,用于Fragment中调用。*/ public void Amend() { TextView textView = (TextView) findViewById(R.id.TextView); textView.setText("你看吧,Activity中的TextView已经被修改了。"); }至此,Fragment中的基本使用你已经学会了,其实Fragment还有一种静态添加的方式,不过个人认为此种方式使用不够灵活,且也非常简单,便没有在文章中写出,感兴趣的话可以查看相关文章。 现在再来看一下效果图,你的效果是否一致?
用于操作Fragment的其他方法: 比较常用的操作Fragment的方法在前面的案例中已经有说明了,不过还有一些没有使用到的需要唠叨两句。
.add() 该方法是用于创建Fragment的,但是当你创建过一次Fragment后,再点击一次,则会抛出异常,不能创建第二次。所以Demo中就没有使用这种方式。
.replace() replace()其实是先删除,再创建,如果不考虑Fragment中的临时数据的话,可以使用这种方式来创建Fragment。
.hide() 这个方法仅仅是将Fragment隐藏起来,但并不是将其销毁。
.show() 同样的,是将隐藏起来的Fragment显示出来。
后记:
至此本篇结束,不过仅仅是介绍了Fragment最基本的使用,要知道Fragment在实际使用的比例是非常大的,所以也会用比较多的篇幅来说明Fragment。
Demo下载传送门:http://download.csdn.net/detail/cc_xz/9778577