java fragment_Fragment简介及使用

概述

Fragment是 Android 3.0(API 11)引入的一种设计,用于大屏幕的设备。

Fragment依托于Activity,受宿主Activity生命周期的影响。但它也有自己的生命周期。

Fragment可重复使用,一个Activity可以有多个Fragment。一个Fragment可以被多个Acitivy使用。

Fragment在Acitivity运行时可以动态的加载或删除。在不同分辨率设备或者横竖屏时 调用对应的Fragment布局就能很好的实现设备的适配,提升用户体验。

注:

AndroidX出来后,使用的Fragment库就在androidx中,下面的例子都是androidx的。

Fragment添加到Activity,一种通过元素插入到布局中,另一种通过代码插入到布局中的。下面的例子就包含这两种。

savedInstanceState这个参数在很多时候是很有用的,在例子中的AnimeDetailFragment中简单的演示了它的使用。

注意不同的设备适配合适的布局,能够很好的提升用户体验。

生命周期

如图,比较详细,稍微了解点或者熟悉Activity的都能直接看懂,下面例子中也通过log大致显示了这一过程。

d51bb9ae35e86ef9291b39160b691257.png

基本使用

先看下例子的效果,这个例子只有一个Activity 和 两个Fragment组成:

b691a51d874d81acd7ea0d1fb0fe51e7.gif

上述效果,Activity布局中 是两个fragment,左侧的标题栏和右侧的详情界面。左侧的标题使用的元素直接插入的,右侧的详情界面 通过点击动态加载的。

Activity布局文件activity_main.xml如下:

Activity很简单:

这里继承了androidx.fragment.app.FragmentActivity。

packagecom.flx.testfragment;importandroid.os.Bundle;importandroid.util.Log;importandroidx.fragment.app.FragmentActivity;importandroidx.fragment.app.FragmentTransaction;public class MainActivity extends FragmentActivity implementsAnimeTitleFragment.OnAmimeSelectedListener {private static final String TAG = "flx_fragment";

@Overrideprotected voidonCreate(Bundle savedInstanceState) {super.onCreate( savedInstanceState );

setContentView( R.layout.activity_main );

}

@Overridepublic void onAnimeSelected(intposition) {

Log.d( TAG,"onArticleSelected: position=" +position );//创建一个详情界面(detailFragment),并出入参数position

AnimeDetailFragment detailFragment = newAnimeDetailFragment();

Bundle args= newBundle();

args.putInt(AnimeDetailFragment.ARG_POSITION, position);

detailFragment.setArguments(args);

FragmentTransaction transaction=getSupportFragmentManager().beginTransaction();//用detailFragment替换anime_detail_fragment_layout中的内容

transaction.replace(R.id.anime_detail_fragment_layout, detailFragment);//将事务添加到返回栈中,允许用户通过按返回按钮返回上个fragment状态。该返回栈由Activity管理。

transaction.addToBackStack(null);//提交事务

transaction.commit();

}

}

AnimeTitleFragment.java:

在布局文件中通过元素插入的,在Activity创建时即生成,即效果图中的左侧标题栏。这里通过继承ListFragment实现,数据和布局使用ArrayAdapter实现关联(Adapter不太了解的,可以参考我对应的其他文章),同时这里的layout考虑了一点兼容性。具体代码如下:

packagecom.flx.testfragment;importandroid.content.Context;importandroid.os.Build;importandroid.os.Bundle;importandroid.util.Log;importandroid.view.LayoutInflater;importandroid.view.View;importandroid.view.ViewGroup;importandroid.widget.ArrayAdapter;importandroid.widget.ListView;importandroidx.annotation.Nullable;importandroidx.fragment.app.ListFragment;public class AnimeTitleFragment extendsListFragment {

AnimeTitleFragment.OnAmimeSelectedListener mCallback;//Activity实现这个接口

public interfaceOnAmimeSelectedListener {void onAnimeSelected(intposition);

}

@Overridepublic voidonCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);//We need to use a different list item layout for devices older than Honeycomb

int layout = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?android.R.layout.simple_list_item_activated_1 : android.R.layout.simple_list_item_1;

String[] anime_names= this.getResources().getStringArray( R.array.anime_name );//使用ArrayAdapter显示所有标题数据

setListAdapter(new ArrayAdapter(getActivity(), layout, anime_names));

}

@Overridepublic voidonAttach(Context context) {super.onAttach(context);//确保Activity实现该接口

try{

mCallback=(AnimeTitleFragment.OnAmimeSelectedListener) context;

}catch(ClassCastException e) {throw newClassCastException(context.toString()+ " must implement OnAmimeSelectedListener");

}

}

@Overridepublic void onListItemClick(ListView l, View v, int position, longid) {//传入position数据,即选中了那个

mCallback.onAnimeSelected(position);

getListView().setItemChecked(position,true);

}

}

AnimeDetailFragment.java:

效果图中的详情界面,根据点击不同的标题显示不同的内容。这里简单使用了savedInstanceState,合理的使用对于某些场景是很有帮助的。具体代码:

packagecom.flx.testfragment;importandroid.content.Context;importandroid.os.Bundle;importandroid.util.Log;importandroid.view.LayoutInflater;importandroid.view.View;importandroid.view.ViewGroup;importandroid.widget.ImageView;importandroid.widget.TextView;importandroidx.annotation.NonNull;importandroidx.annotation.Nullable;importandroidx.fragment.app.Fragment;public class AnimeDetailFragment extendsFragment {private static final String TAG = "flx_AnimeDetailFragment";public static final String ARG_POSITION = "position";private int mCurrentPosition = -1;public staticString[] ANIME_NAMES;public staticString[] ANIME_AUTHORS;public static int[] COVER_IMGS ={R.drawable.hzw1, R.drawable.jjdjr1, R.drawable.hyrz1,

R.drawable.zchzt1, R.drawable.qsmy1, R.drawable.xyj1, R.drawable.hlw1};privateTextView mAnimeName;privateTextView mAnimeAuthor;privateImageView mCoverImg;

@Overridepublic voidonAttach(Context context) {

Log.d( TAG,"onAttach: " + this);super.onAttach( context );

}

@Overridepublic voidonCreate(@Nullable Bundle savedInstanceState) {

Log.d( TAG,"onCreate: " + this);super.onCreate( savedInstanceState );

}

@Nullable

@OverridepublicView onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

Log.d( TAG,"onCreateView: " + this);

ANIME_NAMES=getActivity().getResources().getStringArray( R.array.anime_name );

ANIME_AUTHORS=getActivity().getResources().getStringArray( R.array.anime_author );//savedInstanceState,这个参数很有用,在activity被重新创建时(如旋转屏幕)等,恢复之前的状态。

if (savedInstanceState != null) {

mCurrentPosition=savedInstanceState.getInt(ARG_POSITION);

}

View view= inflater.inflate( R.layout.anime_detail_view, container, false);

mAnimeName=view.findViewById( R.id.anime_name_txt );

mAnimeAuthor=view.findViewById( R.id.anime_author_txt );

mCoverImg=view.findViewById( R.id.anime_cover_img );returnview;

}

@Overridepublic voidonActivityCreated(@Nullable Bundle savedInstanceState) {

Log.d( TAG,"onActivityCreated: " + this);super.onActivityCreated( savedInstanceState );

}

@Overridepublic voidonStart() {

Log.d( TAG,"onStart: " + this);super.onStart();

Bundle args=getArguments();if (args != null) {//根据传入的参数ARG_POSITION 更新

updateAnimeDetailView(args.getInt(ARG_POSITION));

}else if (mCurrentPosition != -1) {//Set article based on saved instance state defined during onCreateView//根据保存的状态中信息 更新

updateAnimeDetailView(mCurrentPosition);

}

}

@Overridepublic voidonResume() {

Log.d( TAG,"onResume: " + this);super.onResume();

}

@Overridepublic voidonSaveInstanceState(Bundle outState) {

Log.d( TAG,"onSaveInstanceState: " + this);super.onSaveInstanceState(outState);//保存fragment当前状态的信息。

outState.putInt(ARG_POSITION, mCurrentPosition);

}public void updateAnimeDetailView(intposition) {

mAnimeName.setText(ANIME_NAMES[position]);

mAnimeAuthor.setText(ANIME_AUTHORS[position]);

mCoverImg.setImageResource(COVER_IMGS[position]);

mCurrentPosition=position;

}

@Overridepublic voidonPause() {

Log.d( TAG,"onPause: " + this);super.onPause();

}

@Overridepublic voidonStop() {

Log.d( TAG,"onStop: " + this);super.onStop();

}

@Overridepublic voidonDestroyView() {

Log.d( TAG,"onDestroyView: " + this);super.onDestroyView();

}

@Overridepublic voidonDestroy() {

Log.d( TAG,"onDestroy: " + this);super.onDestroy();

}

@Overridepublic voidonDetach() {

Log.d( TAG,"onDetach: " + this);super.onDetach();

}

}

一些资源文件:

AnimeDetailFragment的布局文件:anime_detail_view.xml:

strings.xml:

海贼王

进击的巨人

火影忍者

斩赤红之瞳

秦时明月

西游记

葫芦娃

尾田荣一郎

谏山创

岸本齐史

タカヒロ

玄机科技

央视

上海美术电影

生命周期流程

最后,看下log,看看fragment的生命周期

操作:点击第一个标题(海贼王),然后点击第二个标题(进击的巨人),最后点击返回键,下面log的过程 与 生命周期那个图 是一致的,不太明白的,可以仔细看下如下log。

//点击第一个标题,创建了fragment1(52888e9)

2020-03-03 16:22:48.316 20442-20442/com.flx.testfragment D/flx_fragment: onArticleSelected: position=0

2020-03-03 16:22:48.344 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onAttach: AnimeDetailFragment{52888e9 #1 id=0x7f090020}2020-03-03 16:22:48.344 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onCreate: AnimeDetailFragment{52888e9 #1 id=0x7f090020}2020-03-03 16:22:48.347 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onCreateView: AnimeDetailFragment{52888e9 #1 id=0x7f090020}2020-03-03 16:22:48.350 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onActivityCreated: AnimeDetailFragment{52888e9 #1 id=0x7f090020}2020-03-03 16:22:48.350 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onStart: AnimeDetailFragment{52888e9 #1 id=0x7f090020}2020-03-03 16:22:48.357 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onResume: AnimeDetailFragment{52888e9 #1 id=0x7f090020}//点击第二个标题,创建了fragment2(371a2d2), fragment1(52888e9)进入生命周期到onDestroyView

2020-03-03 16:22:51.346 20442-20442/com.flx.testfragment D/flx_fragment: onArticleSelected: position=1

2020-03-03 16:22:51.349 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onAttach: AnimeDetailFragment{371a2d2 #2 id=0x7f090020}2020-03-03 16:22:51.349 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onCreate: AnimeDetailFragment{371a2d2 #2 id=0x7f090020}2020-03-03 16:22:51.350 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onPause: AnimeDetailFragment{52888e9 #1 id=0x7f090020}2020-03-03 16:22:51.350 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onStop: AnimeDetailFragment{52888e9 #1 id=0x7f090020}2020-03-03 16:22:51.350 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onDestroyView: AnimeDetailFragment{52888e9 #1 id=0x7f090020}2020-03-03 16:22:51.365 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onCreateView: AnimeDetailFragment{371a2d2 #2 id=0x7f090020}2020-03-03 16:22:51.369 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onActivityCreated: AnimeDetailFragment{371a2d2 #2 id=0x7f090020}2020-03-03 16:22:51.369 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onStart: AnimeDetailFragment{371a2d2 #2 id=0x7f090020}2020-03-03 16:22:51.391 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onResume: AnimeDetailFragment{371a2d2 #2 id=0x7f090020}//按了返回键,移除了fragment2(371a2d2), fragment1(52888e9)重新恢复。fragment2(371a2d2)执行到onDetach 被销毁。

2020-03-03 16:22:53.144 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onPause: AnimeDetailFragment{371a2d2 #2 id=0x7f090020}2020-03-03 16:22:53.144 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onStop: AnimeDetailFragment{371a2d2 #2 id=0x7f090020}2020-03-03 16:22:53.144 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onDestroyView: AnimeDetailFragment{371a2d2 #2 id=0x7f090020}2020-03-03 16:22:53.148 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onDestroy: AnimeDetailFragment{371a2d2 #2 id=0x7f090020}2020-03-03 16:22:53.148 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onDetach: AnimeDetailFragment{371a2d2 #2 id=0x7f090020}2020-03-03 16:22:53.148 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onCreateView: AnimeDetailFragment{52888e9 #1 id=0x7f090020}2020-03-03 16:22:53.150 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onActivityCreated: AnimeDetailFragment{52888e9 #1 id=0x7f090020}2020-03-03 16:22:53.150 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onStart: AnimeDetailFragment{52888e9 #1 id=0x7f090020}2020-03-03 16:22:53.151 20442-20442/com.flx.testfragment D/flx_AnimeDetailFragment: onResume: AnimeDetailFragment{52888e9 #1 id=0x7f090020}

Fragment使用并不难,用好了,能构建很灵活的界面,做到很好的适配,提升用户体验。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Java应用程序中使用Fragment来实现页面切换,您需要遵循以下步骤: 1. 在XML布局文件中定义Fragment的容器。 2. 创建用于显示在Fragment中的布局文件。 3. 创建一个继承自FragmentJava类,并在其中实现Fragment的行为。 4. 在Activity中实例化Fragment对象并将其添加到Fragment的容器中。 下面是一个简单的示例代码,演示如何使用Fragment实现页面切换: 1. 在布局文件中定义Fragment容器: ```xml <FrameLayout android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 2. 创建用于显示在Fragment中的布局文件: 例如,一个简单的布局文件fragment_layout.xml: ```xml <TextView android:id="@+id/text_view" android:layout_width="match_parent" android:layout_height="match_parent" android:text="This is a fragment" /> ``` 3. 创建一个继承自FragmentJava类,并在其中实现Fragment的行为: ```java public class MyFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_layout, container, false); TextView textView = view.findViewById(R.id.text_view); textView.setText("This is a fragment"); return view; } } ``` 4. 在Activity中实例化Fragment对象并将其添加到Fragment的容器中: ```java FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); MyFragment myFragment = new MyFragment(); fragmentTransaction.add(R.id.fragment_container, myFragment); fragmentTransaction.commit(); ``` 现在,您已经成功地在Java应用程序中使用Fragment实现了页面切换。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值