Fragment 表示应用界面中可重复使用的一部分。Fragment 定义和管理自己的布局,具有自己的生命周期,并且可以处理自己的输入事件。Fragment 不能独立存在,而是必须由 Activity 或另一个 Fragment 托管。Fragment 的视图层次结构会成为宿主的视图层次结构的一部分,或附加到宿主的视图层次结构。
模块化
Fragment 允许您将界面划分为离散的区块,从而将模块化和可重用性引入 Activity 的界面。Activity 是围绕应用的界面放置全局元素(如抽屉式导航栏)的理想位置。相反,Fragment 更适合定义和管理单个屏幕或部分屏幕的界面。
假设有一个响应各种屏幕尺寸的应用。在较大的屏幕上,该应用应显示一个静态抽屉式导航栏和一个采用网格布局的列表。在较小的屏幕上,该应用应显示一个底部导航栏和一个采用线性布局的列表。在 Activity 中管理所有这些变化因素可能会很麻烦。将导航元素与内容分离可使此过程更易于管理。然后,Activity 负责显示正确的导航界面,而 Fragment 采用适当的布局显示列表。
将界面划分为 Fragment 可让您更轻松地在运行时修改 Activity 的外观。当 Activity 处于 STARTED 生命周期状态或更高的状态时,可以添加、替换或移除 Fragment。您可以将这些更改的记录保留在由 Activity 管理的返回堆栈中,从而允许撤消这些更改。
您可以在同一 Activity 或多个 Activity 中使用同一 Fragment 类的多个实例,甚至可以将其用作另一个 Fragment 的子级。考虑到这一点,您应只为 Fragment 提供管理它自己的界面所需的逻辑。您应避免让一个 Fragment 依赖于另一个 Fragment 或从一个 Fragment 操控另一个 Fragment。
1、创建Fragment
设置你的环境
片段需要依赖 AndroidX 片段库 。 你需要 添加 Google Maven 代码库 到你的项目 settings.gradle文件以包含此依赖项。
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
...
}
}
要将 AndroidX Fragment 库包含到您的项目中,请添加以下内容 应用程序中的依赖项 build.gradle文件:
dependencies {
def fragment_version = "1.4.1"
// Java language implementation
implementation "androidx.fragment:fragment:$fragment_version"
// Kotlin
implementation "androidx.fragment:fragment-ktx:$fragment_version"
}
创建一个片段类
要创建片段,请扩展 AndroidX Fragment类,并覆盖 它插入您的应用程序逻辑的方法,类似于您创建的方式 一个 Activity班级。 创建一个最小的 定义自己的布局的片段,提供片段的布局资源 到基本构造函数,如以下示例所示:
class ExampleFragment extends Fragment {
public ExampleFragment() {
super(R.layout.example_fragment);
}
}
Fragment 库还提供了更专业的片段基类:
DialogFragment
显示一个浮动对话框。 使用这个类来创建一个对话框是一个不错的选择 替代在 Activity类,作为片段 自动处理 Dialog. 请参阅 显示对话框 DialogFragment 更多细节。
PreferenceFragmentCompat
显示层次结构 Preference对象作为 列表。 您可以使用 PreferenceFragmentCompat到 创建一个设置屏幕 为您的应用
将Fragment添加到活动
通常,您的片段必须嵌入到 AndroidX 中 FragmentActivity到 为该活动的布局贡献一部分 UI。 FragmentActivity 是基类 AppCompatActivity, 所以如果你已经在子类化 AppCompatActivity提供落后 您的应用程序中的兼容性,那么您不需要更改您的活动 基类。
您可以通过以下方式将片段添加到活动的视图层次结构中 在 Activity 的布局文件中定义片段或通过定义 活动布局文件中的片段容器,然后 以编程方式从您的活动中添加片段。 无论哪种情况,您都需要 添加一个 FragmentContainerView它定义了片段应该放置在 活动的视图层次结构。 强烈建议始终使用 FragmentContainerView作为片段的容器,如 FragmentContainerView包括特定于其他片段的修复 查看组,例如 FrameLayout不提供。
要以声明方式将片段添加到活动布局的 XML,请使用 FragmentContainerView元素。
这是一个示例活动布局,其中包含一个 FragmentContainerView:
xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container_view" android:layout_width="match_parent" android:layout_height="match_parent" android:name="com.example.ExampleFragment" /> 这 android:name属性指定类名 Fragment到 实例化。 当活动的布局膨胀时,指定的片段 被实例化, onInflate() 在新实例化的片段上调用,并且 FragmentTransaction 创建该片段以将片段添加到 FragmentManager. 注意: 您可以使用 class属性而不是 android:name作为一个 指定哪个的替代方法 Fragment实例化。 要以编程方式将片段添加到活动的布局,布局 应该包括一个 FragmentContainerView作为片段容器, 如下例所示: xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container_view" android:layout_width="match_parent" android:layout_height="match_parent" /> 与 XML 方法不同的是, android:name属性未用于 FragmentContainerView在这里,所以没有特定的片段是自动的 实例化。 相反,一个 FragmentTransaction 用于实例化一个片段并将其添加到活动的布局中。 当您的活动正在运行时,您可以进行片段事务,例如 添加、删除或替换片段。 在你的 FragmentActivity, 你可以 获取一个实例 FragmentManager, 哪一个 可用于创建一个 FragmentTransaction. 然后,您可以实例化您的 您活动中的片段 onCreate()使用方法 FragmentTransaction.add(), 传入 ViewGroup布局中容器的 ID 和片段 您要添加的类,然后提交事务,如 以下示例: public class ExampleActivity extends AppCompatActivity { public ExampleActivity() { super(R.layout.example_activity); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .setReorderingAllowed(true) .add(R.id.fragment_container_view, ExampleFragment.class, null) .commit(); } } } 注意: 您应该 始终 使用 setReorderingAllowed(true)什么时候 执行一个 FragmentTransaction. 有关重新排序的更多信息 交易,见 分片交易 。 在前面的例子中,注意只创建了分片事务 什么时候 savedInstanceState是 null. 这是为了确保片段 仅在首次创建活动时添加一次。 当一个 发生配置更改并重新创建活动, savedInstanceState不再是 null,并且片段不需要 第二次添加,因为片段会自动恢复 来自 savedInstanceState. 如果您的片段需要一些初始数据,则可以通过提供 Bundle在调用 FragmentTransaction.add(), 如下所示: public class ExampleActivity extends AppCompatActivity { public ExampleActivity() { super(R.layout.example_activity); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState == null) { Bundle bundle = new Bundle(); bundle.putInt("some_int", 0); getSupportFragmentManager().beginTransaction() .setReorderingAllowed(true) .add(R.id.fragment_container_view, ExampleFragment.class, bundle) .commit(); } } } 论据 Bundle然后可以通过以下方式从您的片段中检索 打电话 requireArguments(), 和适当的 Bundlegetter 方法可用于检索 每个论点。 class ExampleFragment extends Fragment { public ExampleFragment() { super(R.layout.example_fragment); } @Override public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { int someInt = requireArguments().getInt("some_int"); ... } } fragment的静态使用: fragment的静态使用就是在activity的xml布局中把fragment控件来使用,利用name属性设置对应fragment的路径,静态使用时要注意给fragment加id,不加id运行会报错;在Activity的layout文件中声明Fragment,需要特别注意的是 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" android:orientation="vertical" tools:context=".MainActivity"> android:layout_width="match_parent" android:layout_height="50dp" android:background="@color/colorAccent" android:text="标题" android:gravity="center" android:textColor="@android:color/white" android:textSize="20sp"/> android:id="@+id/fragment_content" android:layout_width="match_parent" android:layout_height="match_parent" android:name="com.lsm.myapplication.fragment.ContentFragment"/> 运行效果和平时动态使用的效果是一样的; fragment的动态使用: fragment的动态使用就是利用FragmentManager和FragmentTransaction将对应的fragment与activity布局中对应的id相关联,将对应的fragment添加进去,这也是平时开发中使用的比较多的一种方式;撰写代码将Fragment添加到一个Activity layout中,add()添加一个Fragment(指定要添加的fragment和插入的View),与此类似的还有移除remove()、替换replace()。 FragmentManager fm = getSupportFragmentManager(); FragmentTransaction transaction = fm.beginTransaction(); transaction.add(R.id.content_layout,new ContentFragment()); transaction.commit(); 对于这段代码都不陌生,FragmentTransaction还提供了replace、remove等一系列操作fragment的方法,动态使用和静态使用的效果是一样的;但主要使用动态 ※主要看这个 1、静态绑定 fragment的创建:new-Fragment-新建个空白fragment然后将里面的修改如下(为生命周期而创建): public class BlankFragment extends Fragment { private static final String TAG = "BlankFragment"; @Override public void onAttach(@NonNull Context context) { super.onAttach(context); Log.d(TAG, "onAttach: "); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "onCreate: "); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { Log.d(TAG, "onCreateView: "); View view=inflater.inflate(R.layout.fragment_blank,container,false); return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Log.d(TAG, "onActivityCreated: "); } @Override public void onStart() { super.onStart(); Log.d(TAG, "onStart: "); } @Override public void onResume() { super.onResume(); Log.d(TAG, "onResume: "); } @Override public void onPause() { super.onPause(); Log.d(TAG, "onPause: "); } @Override public void onStop() { super.onStop(); Log.d(TAG, "onStop: "); } @Override public void onDestroyView() { super.onDestroyView(); Log.d(TAG, "onDestroyView: "); } @Override public void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy: "); } @Override public void onDetach() { super.onDetach(); Log.d(TAG, "onDetach: "); } } 在主界面中加入fragment 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=".StaticInflateFragmentActivity" android:orientation="horizontal"> android:layout_weight="1" android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/fragment1" android:name="com.lapian.examplefragment.BlankFragment"/> android:layout_weight="1" android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/fragment2" android:name="com.lapian.examplefragment.BlankFragment2"/> 2、动态绑定 java代码: FragmentManager supportFragmentManager = getSupportFragmentManager();//获取支持fragment的管理者 FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();//管理者开始运输,也即通过`fragment管理者开启一个事务对象 Fragment fragment1=new BlankFragment();//或者直接将下一句的fragment1改为new... fragmentTransaction.add(R.id.fragment_container,fragment1);//运输添加到容器,即在activity添加一个Fragment fragmentTransaction.commit();//提交 xml布局: 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=".DynamicInflateFragmentActivity" android:orientation="vertical"> android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/fragment_container"/> Fragment比Activity多了几个额外的生命周期回调方法: fragment和activity之间的通信: 因为所有的Fragment都是依附于Activity的,所以通信起来并不复杂,大概归纳为: a、如果你Activity中包含自己管理的Fragment的引用,可以通过引用直接访问所有的Fragment的public方法 b、如果Activity中未保存任何Fragment的引用,那么没关系,每个Fragment都有一个唯一的TAG或者ID,可以通过getFragmentManager.findFragmentByTag()或者findFragmentById()获得任何Fragment实例,然后进行操作。 c、在Fragment中可以通过getActivity得到当前绑定的Activity的实例,然后进行操作。 注:如果在Fragment中需要Context,可以通过调用getActivity(),如果该Context需要在Activity被销毁后还存在,则使用getActivity().getApplicationContext()。 fragment回调activity 如果你需要在fragment中处理一些事情,事情的处理结果或者你需要告 诉activity马上要做什么事,这时候就需要和activity进行通讯。包括很多fragment在viewpager中的情况,而且可以保证activity能即时进行响应。相比发送广播,性能更好,代码更少。
onAttach(Activity)
当Fragment与Activity发生关联时调用。
onCreateView(LayoutInflater, ViewGroup,Bundle)
创建该Fragment的视图
onActivityCreated(Bundle)
当Activity的onCreate方法返回时调用
onDestoryView()
与onCreateView想对应,当该Fragment的视图被移除时调用
onDetach()
与onAttach相对应,当Fragment与Activity关联被取消时调用
注意:除了onCreateView,其他的所有方法如果你重写了,必须调用父类对于该方法的实现,