目录
知识点
Fragment的基本概念与应用。
Fragment与Activity的对比,生命周期的比较。 Fragment怎么使用,包括静态和动态加载。 Fragment的增,删,替换等操作。
1.Fragment概述
1.1 定义
Fragment(碎片)是一种可以嵌入在活动当中的UI片段,能够让程序更加合理和充分的利用大屏幕的空间,因而在平板上应用得很广泛。和Activity很像,同样可以包含布局,同样拥有自己的生命周期。
1.2 Fragment设计思想
在手机上的界面,看平板上来看就可能完全不一样,可能导致控件被拉长等等。Fragment为了解决终端适配的问题,比如平板和手机。
2.Fragment与Activity区别
区别如下所示:
1.Fragment是Android3.0+以后的 2.一个Activity可以运行多个Fragment 3.Fragment不能脱离Activity而存在 4.Activity是屏幕的主体,而Fragment是Activity的一个组成元素 5.Fragment模块化,可重用 6.Fragment可以互相嵌套,但是最好不用。
3.Fragment生命周期
3.1 Activity与Fragment生命周期的比较
Activity生命周期 Fragment生命周期
1.onAttach()方法:顾名思义,是Fragment和Activity建立关联的时候调用。 2.onCreate()方法:当Fragment创建时调用。 3.onCreateView()方法:为Fragment加载布局时调用。 4.onViewCreated()方法:当Fragment加载布局完成后时调用 5.onActivityCreated()方法:当Activity中的onCreate方法执行完后调用。 6.onStart()方法:当Fragment启动时调用。 7.onResume()方法:当Fragment正在运行时调用。 8.onPause()方法:当Fragment不在交互时调用。 9.onStop()方法:当Fragment不可再见时调用。 10.onDestoryView()方法:Fragment中的布局被移除(即销毁)时调用(即与Fragment关联的视图被移除) 11.onDestory()方法:Fragment被移除(即销毁)时调用。 12.onDetach()方法:Fragment与Activity解除关联时调用。 注意:Fragment中不存在onRestart()方法,该方法只存在与Activity中。
3.2 Fragment的四种状态
运行状态 当Fragment是可见的,且所关联的Activity正处于运行状态时,该Fragment也处于运行状态。 暂停状态 当Activity处于暂停状态(由于另外一个未占满屏幕的活动被添加到了栈顶),与它相关联的可见
Fragment就会进入到暂停状态。
停止状态 当一个Activity处于停止状态,与之关联的Fragment就会进入到停止状态。处于停止状态的Fragment对于
用户来说是完全不可见的,有可能会被系统回收。
销毁状态 当Activity被销毁时,与之关联的Fragment就会进入销毁状态, 3.3 实例创建
需要定义类继承Fragment抽象类:
//Fragment类,继承自android.support.v4.app.Fragment; public class Fragment_1 extends Fragment{ @Override public void onAttach(Context context) { super.onAttach(context); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { //加载布局 View view = inflater.inflate(R.layout.fragment,container,false); return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); } @Override public void onStart() { super.onStart(); } @Override public void onResume() { super.onResume(); } @Override public void onPause() { super.onPause(); } @Override public void onStop() { super.onStop(); } @Override public void onDestroyView() { super.onDestroyView(); } @Override public void onDestroy() { super.onDestroy(); } @Override public void onDetach() { super.onDetach(); } }
注意:Fragment中不存在onRestart()方法,该方法只存在与Activity中。
4.Fragment的创建
4.1 创建方式方法
Fragment可以通过两种方式创建:
静态方法创建 定义布局,定义类继承Fragment,在Activity布局中加入<fragment> 动态方法创建 4.2 Fragment的静态加载
以xxx.xml文件形式加载,把Fragment当成普通的控件,直接写在Activity的布局文件中,步骤:
1、继承Fragment,重写onCreateView决定Fragemnt的布局
2、在Activity的布局文件中中加入此Fragment,就当和普通的View控件一样,<fragment ...../>(name属性传入类名) left_fragment.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#fce57f"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="Button" android:background="#fa6b47"/> </LinearLayout>
right_fragment.xml:
<?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:orientation="vertical" android:background="#751f56"> <TextView android:textSize="20sp" android:textColor="#FFFFFF" android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="This is right fragment"/> </LinearLayout>
LeftFragment.java:
//Fragment类,继承自android.support.v4.app.Fragment; public class LeftFragment extends Fragment{ @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.left_fragment,container,false); return view; } }
RightFragment.java:
public class RightFragment extends Fragment{ @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.right_fragment,container,false); return view; } }
将Fragment添加到Activity的布局文件activity_main.xml中:
<?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"> <!-- id一定别忘记 --> <fragment android:id="@+id/left_fragment" android:layout_width="0dp" android:layout_height="match_parent" android:name="com.administrator.fragmentstudy.LeftFragment" android:layout_weight="1"/> <fragment android:id="@+id/right_fragment" android:layout_width="0dp" android:layout_height="match_parent" android:name="com.administrator.fragmentstudy.RightFragment" android:layout_weight="1"/> </LinearLayout>
运行结果:
注意:添加进去的fragment一定要有id,否则要报错: Error inflating class fragment。
4.3 动态加载
4.3.1 实例
步骤:
1.创建待添加的Fragment实例。 2.在Activity布局中加入FrameLayout布局(所有控件默认摆放在布局的左上角) 3.在Activity中,使用getSupportFragmentManager()获取FragmentManager对象 4.开启一个事务,通过调用beginTransaction()方法开启 5.向容器(通过FrameLayout的id属性)添加Fragment实例,添加使用add(),替换使用replace() 6.提交事务,调用commit()方法 创建another_right_fragment.xml:
<?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="#fce4b8"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="This is another right fragment" android:textSize="20sp" android:textColor="#e10367"/> </LinearLayout>
创建AnotherRightFragment.java:
public class AnotherRightFragment extends Fragment{ @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.another_right_fragment,container,false); return view; } }
在Activity的布局文件,activity_layout.xml:
<?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"> <fragment android:id="@+id/left_fragment" android:layout_width="0dp" android:layout_height="match_parent" android:name="com.administrator.fragmentstudy.LeftFragment" android:layout_weight="1"/> <FrameLayout android:id="@+id/another_right_fragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout>
在MainActivity.java中:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建Fragment实例 AnotherRightFragment anotherRightFragment = new AnotherRightFragment(); FragmentManager fragmentManager = getSupportFragmentManager(); //开启Fragment事务 FragmentTransaction transaction = fragmentManager.beginTransaction(); //向容器添加Fragment实例 transaction.add(R.id.another_right_fragment,anotherRightFragment); //提交事务 transaction.commit(); } }
运行效果:
4.3.2 动态切换fragment的方法:
add(Container container,Fragment fragment) 添加Fragment到指定的容器里面。 remove(Container container,Fragment fragment) 删除指定的Fragment replace(Container container,Fragment fragment) 用新的Fragment替换掉指定的Fragment 4.3.3 Fragment中常用的方法:
android.app.Fragment 主要用于定义Fragment android.app.FragmentManager 主要用于在Activity中操作Fragment android.app.FragmentTransaction 保证一些列Fragment操作的原子性
5.在Fragment中模拟返回栈
通过FragmentTransaction的addToBackStack()方法:
addToBackStack(String s) 接收一个名字用于描述返回栈的状态,一般传入null即可。
6.Fragment的通信传值
6.1 概述
由于Activity与Fragment各自存在一个独立的类中,它们之间因此没有明显的方式来直接进行通信。
6.1.1 获取对方的实例
Fragment获取它所在的Activity 调用Fragment的getActivity()方法即可返回它所在的Activity。 Activity获取它包含的Fragment 调用Activity关联的FragmentManager的findFragmentById(int id) 或
findFragmentByTag(String tag)方法即可获取指定的Fragment。
实例代码如下:
RightFragment rightFragment = (RightFragment)getSupportFragmentManager().findFragmentById(R.id.right_fragment);
6.1.2 与对方进行传值
Activity向Fragment传递数据:
在Activity中创建Bundle数据包,并调用Fragment的setArgument(Bundle bundle)方法即可将Bundle数据包传递给Fragment。 Fragment向Activity传递数据或Activity需要在Fragment运行中进行实时通信:
在Fragment中定义一个内部回调接口,再让包含该Fragment的Activity实现该回调接口,这样Fragment即可调用该回调方法将数据传递给Activity。 6.2 Activity -> Fragment
方法:
Activity通过Bundle对象将其传递的值放在里面,然后通过setArgument()方法来传递,然后Fragment通过getArguments()方法按照键的唯一性来获取值。 setArguments(Bundle bundle) getArguments().XXX方法 在Fragment的继承类中:
public class Fragment_1 extends Fragment { public static final String bundle_content = "BUNDLE_CONTENT"; private String content; private TextView textView; public static Fragment_1 newInstance(String content){ Bundle bundle = new Bundle(); bundle.putString(bundle_content,content); Fragment_1 fragment = new Fragment_1(); //设置Bundle fragment.setArguments(bundle); return fragment; } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_1,container,false); //可以对Fragment布局控件进行操作 textView = view.findViewById(R.id.fragment_1_tv); return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if(getArguments() != null) { //获取内容 content = getArguments().getString(bundle_content); //设置内容 textView.setText(content); } } }
注意:这里的Fragment创建顺序。 textView.setText(content)是放在onActivityCreated()方法里面。
在Activity的MainActivity中:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Fragment_1 fragment = new Fragment_1(); getSupportFragmentManager().beginTransaction() .add(R.id.title,Fragment_1.newInstance("这是Activity向Fragment传递的内容")) //提交 .commit(); getSupportFragmentManager().beginTransaction() .add(R.id.content,Fragment_1.newInstance("这是Activity向Fragment传递的内容")) //提交 .commit(); } }
6.3 Fragment -> Activity
Fragment类方法编写接口,实现回调:
在Fragment中定义一个内部回调接口,再让包含该Fragment的Activity实现该回调接口,这样Fragment即可调用该回调方法将数据传递给Activity。 Callback public class Fragment_1 extends Fragment { private TextView textView; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_1,container,false); //可以对Fragment布局控件进行操作 textView = view.findViewById(R.id.fragment_1_tv); textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String str = textView.getText().toString(); //这里一定要非空判断,否则出现空指针异常 if(onContentClickListener != null){ onContentClickListener.onClick(str); } } }); return view; } //定义接口 public interface OnContentClickListener{ void onClick(String content); } //定义变量 private OnContentClickListener onContentClickListener; //设置接口的方法(括号里面的参数不能与onContentClickListener一样,否则出错) public void setOnContentClickListener(OnContentClickListener listener){ onContentClickListener = listener; } }
Activity类implements Fragment_1.OnContentClickListener,继承接口,实现其方法:
public class MainActivity extends AppCompatActivity implements Fragment_1.OnContentClickListener{ private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = findViewById(R.id.btn); Fragment_1 fragment = new Fragment_1(); getSupportFragmentManager().beginTransaction() .add(R.id.title,fragment) //提交 .commit(); fragment.setOnContentClickListener(this); } @Override public void onClick(String content) { button.setText(content); } }
6.4 Fragment -> Fragment
首先在一个Fragment中可以得到与它相关联的Activity,然后再通过这个Activity去获取另外一个Fragment的实例,这样就实现了Fragment之间的通信。