有些布局可能在手机上看起来很漂亮,但是拿到屏幕比较大的横屏平板上面,有些控件可能会遭到拉伸,严重影响用户体验,作为一个合格的开发人员我们应该兼顾这两种情况,所以在Android3.0之后,Android引入了碎片的概念,它可以让界面更好的在平板上展示。在Android3.0之前的版本需要引入需要先导入android-support-v4的jar包才能使用Fragment功能。
1.碎片是什么?
碎片(Fragment)是一种可以嵌套在活动当中的UI片段,它能使程序更加合理地利用大屏幕控件,所有在平板程序中应用广泛。它和活动类似,可以包含布局、有自己的生存周期。我们可以把Fragment理解成一个迷你型的活动,但是这个迷你型的活动也有可能和普通的活动一样大。
何种情况才会应用Fragment呢。就比如Android版的CSDN博客,我想把我的博文在APP中显示出来如果不利用Fragment的话,在手机上应该是这样显示的(如下图),Activity01用于显示文章的标题列表,点击一个标题进入Activity02活动中查看具体的内容,这个时候如果在Activity01中标题的内容长短不一,极有可能使其显示不美观。
Activity01 Activity02
利用Fragment的话界面应该是这样的,我们把上面Activity01、Activity02两个活动都当做是Fragment,然后把这个两个Fragment放入到一个活动中去。
2.碎片的简单用法
我们新建两个FragmentLeftActivity、FragmentRightActivity碎片,让它们在MainActivity活动中一左一右。
在继承Fragment时细心的我们能发现,会有两个不同包下的Fragment给我们引用,建议用"android.app.Fragment",因为包"android.support.v4.app.Fragment"主要是为了兼容低版本,这里我们用的是Android4.0以上了,所以用"android.app.Fragment"。
FragmentLeftActivity.java
package com.example.fragmenttest;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class FragmentLeftActivity extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.left_layout, container, false);
return view;
}
}
package com.example.fragmenttest;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class FragmentRightActivity extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.right_layout, container, false);
return view;
}
}
right_layout.xml
MainActivity.java
package com.example.fragmenttest;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
activity_main.xml
图2.1
3.动态添加碎片
在2中我们在活动中的xml布局文件中添加了两个碎片,但是实际程序中这样静态地添加是很不实用的。所以我们还可以动态地向活动中添加Fragment。
替换xml中的的Fragment
AnotherRightFragment fragment = new AnotherRightFragment(); //1.创建待操作的碎片实例
FragmentManager fragmentManager = getFragmentManager(); //2.获取到FragmentManager,在活动中可以直接调用getFragmentManager()方法得到
FragmentTransaction transaction = fragmentManager. beginTransaction(); //3.开启一个事务,通过调用beginTransaction()方法开启
transaction.replace(R.id.right_layout, fragment); //4.向容器内加入碎片,一般使用replace()方法实现,需要传入容器的id和待添加碎片的实例
transaction.commit(); //5.提交事务,调用commit()方法实现
4.碎片和活动之间的通信
1) 碎片使用活动中的方法
在每个碎片中都可以通过调用getActivity()方法获取和当前碎片相关联的活动,比如碎片在MainActivity活动中显示:
MainActivity activity = (MainActivity) getActivity();
有了实例之后,调用便不成问题了。另外当碎片要使用活动的Context对象时,也可以使用getActivity()方法来获取,因为获取到的活动本身就是一个Context对象。
2) 活动使用碎片中的方法
为了方便碎片和活动之间的通信,FragmentManager提供了一个类似于findViewById()的方法,专门用于从布局文件中获取碎片的实例:
FragmentRightActivity fragment = (FragmentRightActivity ) getFragmentManager().findFragmentById(R.id.right_layout);
可以在活动中获取到碎片的实例。
3) 碎片之间相互调用
碎片之间的相互调用,其实一个碎片获取到该活动的实例,再通过该活动获取到另一个碎片的实例,这样两个碎片便可通信了。
5.碎片的生命周期
碎片的生命周期和活动的生命周期很相似。分为四个状态
1)运行状态
当一个碎片是可见的,并且与它相关联的活动处于运行状态时,该碎片也处于运行状态。
2)暂停状态
当一个活动处于暂停状态(一个未占满屏幕的活动到了返回栈定)时,与它相关联的可见碎片就处于暂停状态。
3)停止状态
当一个活动进入停止状态时与它相关联的碎片就进入停止状态。或者通过调用FragmentTransaction的remove()、replace()方法将碎片从活动中移除,但有在事务提交之前调用addToBackStack()方法,这时的碎片也会进入到停止状态。总的来说,进入停止状态的碎片对用户来说是完全不可见的,有可能会被系统回收。
4)销毁状态
碎片总是依附于活动而存在的,因此当活动被销毁时,与它相关联的碎片就会进入到销毁状态。或者通过调用FragmentTransaction的remove()、replace()方法将碎片从活动中移除,但在事务提交之前并没有调用addToBackStack()方法,这时的碎片也会进入到销毁状态。
一部分回调方法:
1) onAttach()
当碎片和活动建立关联时调用。
2) onCreateView()
为碎片加载布局时调用。
3) onActivityCreated()
确保与碎片相关联的活动一定已经创建完毕的时候调用。
4) onDestroyView()
当与碎片关联的视图被移除的时候调用。
5) onDetach()
当碎片和活动解除关联的时候调用。
Android官网的碎片生命周期示意图
生命周期的理解:
1)当碎片第一次被加载到屏幕上时,会依次执行onAttach()、onCreate()、onCreateView()、onActivityCreated()、onStart()和onResume()方法。
2)碎片被替换成另一个碎片时,原来的碎片进入停止状态(调用了addToBackStack方法),依次执行onPause()、onStop()和onDestroyView()。
3)碎片被替换成另一个碎片时,原来的碎片进入销毁状态(没有调用了addToBackStack方法),依次执行onPause()、onStop()、onDestroyView()、onDestroy()、onDetach()。
4)按键back键时(调用了addToBackStack方法),碎片重新回到运行状态,onActivityCreated()、onStart()和onResume()。onCreate()和onCreateView()方法并不会执行,因为我们借助了addToBackStack()方法使得碎片和它的视图并没有销毁。
5)按键back键时(未调用了addToBackStack方法),碎片处于销毁状态,依次执行onPause()、onStop()、onDestroyView()、onDestroy()、onDetach()。