目录
一、Fragment是什么
二、Fragment的生命周期
三、添加Fragment的方式
3.1 静态添加fragment
3.2 动态添加Fragment:
一、Fragment是什么
Android3.0以后引进了新的控件Fragment(碎片),Fragment相较于Activity更灵活,Fragment有自己的类和xml配置文件,因此一个Fragment可以被多个Activity复用。而且Activity是需要在Androidmanifest.xml上声明的,Fragment则只需要在调用该Fragment的Activity的配置文件中声明即可。
Fragment主要是为了给更大的屏幕(如平板电脑)上更加动态和灵活的 UI 设计提供支持。由于平板屏幕比手机的屏幕大得多,也能显示更多的布局和组件。
例如,新闻应用可以使用一个片段在左侧显示文章列表,使用另一个片段在右侧显示文章 — 两个片段并排显示在一个 Activity 中,每个片段都具有自己的一套生命周期回调方法,并各自处理自己的用户输入事件。 因此,用户不需要使用一个 Activity 来选择文章,然后使用另一个 Activity 来阅读文章,而是可以在同一个 Activity 内选择文章并进行阅读,如图 1 中的平板电脑布局所示。(可以通过判断屏幕窗口尺寸来决定fragment的布局)
二、Fragment的生命周期
可以看到,Fragment的生命周期其实和Activity很相似,只不过多了几个方法:
- onAttached() —— 当fragment被加入到activity时调用(在这个方法中可以获得所在的activity)。
- onCreateView() —— 当activity要得到fragment的layout时,调用此方法,fragment在其中创建自己的layout(界面)。
- onActivityCreated() —— 当activity的onCreated()方法返回后调用此方法
- onDestroyView() —— 当fragment中的视图被移除的时候,调用这个方法。
- onDetach() —— 当fragment和activity分离的时候,调用这个方法。
三、添加Fragment的方式
3.1 静态添加fragment
步骤:
1.新建Fragment类
2.新建步骤1中Fragment的对应xml
3.在调用Fragment的Activity的配置文件中声明要调用的Fragment
例子:
运行效果:
左边和右边分别是两个不同的Fragment,然后主Activity(MainActivity)调用这两个Fragment:
项目目录如下:
只需要关注红框内的文件即可。
代码:
新建leftFragment和rightFragment两个Fragment的类:
leftFragment.java:
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.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
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
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;
}
}
然后创建leftFragment和righFragment的布局文件 left_fragment.xml 和 right_fragment.xml :
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="@android:color/darker_gray">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Button" />
</LinearLayout>
right_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="@android:color/holo_purple">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
android:text="this is Fragment" />
</LinearLayout>
在调用Fragment的Activity配置文件中声明Fragment:
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<fragment
android:id="@+id/fragment01"
android:name="com.example.fragmenttest.leftFragment" //leftFragment的全限定名
android:layout_width="215dp"
android:layout_height="741dp"
android:layout_weight="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<fragment
android:id="@+id/fragment02"
android:name="com.example.fragmenttest.rightFragment"
android:layout_width="198dp"
android:layout_height="739dp"
android:layout_weight="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
3.2 动态添加Fragment:
跟静态不同的是,动态可以通过与用户交互的方式,动态改变Fragment ,例如增加,删除,切换Fragment,而静态添加则不行。静态添加的方式在activity的配置文件就把Fragment写死了,而动态添加的方式则不需要在activity的配置文件中声明Fragment,(使用起来更加的解耦)而是使用事务的方式,更换Fragment。具体代码如下:
效果:
点击ONE和TWO按钮都会动态地调出各自的Fragment
代码:
先定义 Fragment01和Fragment02的布局文件:
fragment01.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:layout_gravity="center"
android:background="@android:color/holo_blue_light"
>
<LinearLayout
android:layout_width="446dp"
android:layout_height="462dp"
android:orientation="vertical">
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Fragment01" />
</LinearLayout>
</LinearLayout>
fragment02.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="@android:color/holo_orange_light">
<LinearLayout
android:layout_width="459dp"
android:layout_height="550dp"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="This is Fragment02" />
</LinearLayout>
</LinearLayout>
定义好fragment的布局文件后,创建对应fragment的类文件:
fragment01.java:
package com.example.dynamicfragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.app.Fragment;
public class Fragment01 extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment01,null);
}
}
fragment02.java:
package com.example.dynamicfragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.app.Fragment;
public class Fragment02 extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment02,null);
}
}
定义完fragment组建的相关代码后,开始准备用Activity调用这些fragment。
我们使用MainActivity进行对fragment的调用,因此先改写一下MainActivity的配置文件
activity_main.xml:
值得注意的是:我们在此布局的配置文件中,创建一个 LinearLayout布局来装fragment,并把这个LinearLayout布局命名为frame_id。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="One"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.297"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.812" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Two"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.467"
app:layout_constraintStart_toEndOf="@+id/button"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.812" />
<LinearLayout
android:id="@+id/frame_id"
android:layout_width="352dp"
android:layout_height="476dp"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.102"></LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
最后写MainActivity调用 fragment的逻辑
MainActivity.java:
package com.example.dynamicfragment;
import androidx.appcompat.app.AppCompatActivity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Button b1,b2;
private FragmentManager fm;
private FragmentTransaction ft;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b1 = (Button)findViewById(R.id.button);
Button b2 = (Button)findViewById(R.id.button2);
b1.setOnClickListener(this);
b2.setOnClickListener(this);
fm = getFragmentManager();
ft = fm.beginTransaction();
ft.add(R.id.frame_id,new Fragment01());
ft.commit(); //提交事务
}
@Override
public void onClick(View v) {
ft = fm.beginTransaction();
switch (v.getId()){
case R.id.button:
ft.replace(R.id.frame_id,new Fragment01());
ft.addToBackStack(null);//把Fragment01 放到栈中,等以后按下返回键时,可以返回到Fragment01中
break;
case R.id.button2:
ft.replace(R.id.frame_id,new Fragment02());
ft.addToBackStack(null);
break;
default:break;
}
ft.commit();
}
}