Fragment使用详解

来源:互联网 发布:淘宝网买卖中心 编辑:程序博客网 时间:2024/05/21 01:45

fragment是Google在3.0版本中推出的新功能,现在已经加入到V4包中,如果要使用V4兼容包中的Fragment需要将Activity换成FragmentActivity,调用的getSupportFragmentManager获取FragmentManager而不是getFragmentManager。Fragment是Google大力推荐使用的一个功能,它和Activity功能其实差不多,不过比Activity更加的灵活和轻巧,Fragment寄存在Activity上面,他的生命周期直接受宿主Activity的影响,我们使用Fragment可以把它当做一个自定义视图一样来使用,使用好Fragment的前提是了解其生命周期,下面一张图来显示其与宿主Activity生命周期的关系:


当然上面的生命周期中我们不需要都重写,甚至你一个生命周期方法不写程序也可以正常运行。一般如果Fragment有视图的话我们需要重写onCreateView,更加需要你也可以重写其它的生命周期的方法。


与本节知识点相关的类主要有:FragmentManager、FragmentTransaction、Fragment这三个。这里我给大家提出来几个实用的类,都是Google帮我们分装好并且经常会使用到的类:DialogFragment、ListFragment、PreferenceFragment,第一个是用来创建Dialog的,第二个是一个含有ListView的Fragment,最后一个一般用来作为偏好方面的功能的设计,类似于手机里面的设置界面。下面就来给这三个类中的常用方法列出来。

FragmentManager:

beginTransaction():用来得到事务对象,后续对Fragment的添加删除等都是靠事务对象。

addOnBackStackChangedListener():给回退栈添加一个监听,回退栈中的Fragment数量变化都会调用这个监听。

findFragmentbyid():根据Fragment的id找到对应的Fragment;

findFragmentByTag():根据TAG找到对应的Fragment

popBackStack():将回退栈中的Fragment弹出也就是销毁,这个方法有很多个重载方法,可以指定一个Fragment弹出。

FragmentTransaction:

add():将一个Fragment添加到事务中,该方法有多个重载;

replace():将Fragment替换指定的容器控件,如果是动态创建一个Fragment经常使用这个方法。

addtoBackStack():将Fragment添加到回退栈中。

remove():移除一个Fragment对象。

hide():隐藏一个Fragment对象。

commit():提交本次事务,只要涉及到事务都会有这么一个方法,比如数据库中用到了事务也有这个方法。

show():跟hide对应使用。

Fragment:

setArguement():经常使用这个方法传递数据,对应的方法为getArgument();


我们用一个实例来演示Fragment的使用,实例只有一个Activity,而Activity布局文件中左右各一个Fragment,左边的Fragment中只有一个ListView,右边Fragment中只有一个ImageView,点击左边的ListView让右边的Fragment中的ImageView显示不同的图片。这里关键是左右Fragment交互的问题,解决这个问题我们有两种方式,一种是基于接口回调的方式,另一种我们可以是观察者模式,可以使用我们先前讲过的第三方EvnetBus,这里我们就使用接口回调的方式来解决,我们先来上效果图


(这里ListView的线条不对的问题是模拟器的原因,真机运行不存在这个bug)


Fragment的使用有两种方式

静态:直接在布局文件中声明Fragment。

动态:在布局文件中使用容器控件占位,然后使用前面说的replace方法替换掉。

因为第一种方式比较简单,这里的例子我们使用第二种方式。

首先来看Activity的布局文件

<?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="horizontal">    <RelativeLayout        android:id="@+id/containerB"        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_marginRight="20dp"        android:layout_weight="1"        android:gravity="center"></RelativeLayout>    <FrameLayout        android:id="@+id/containerA"        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="3"></FrameLayout></LinearLayout>

使用一个Relativelayout和一个framelayout作为占位控件。当然我们先要有2个Fragment,下面贴出两个Fragment的代码:

左边的Fragment:

public class BFragment extends Fragment {    private ListView listView;    private OnClickItemListener onClickItemListener;    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        onClickItemListener = (OnClickItemListener) getActivity();        View view = inflater.inflate(R.layout.bfragment_layout, null);        listView = ((ListView) view.findViewById(R.id.bfragment_listView));        List<String> names = new ArrayList<>();        {            names.add("可爱");            names.add("活泼");            names.add("成熟");            names.add("高贵");            names.add("文静");        }        ArrayAdapter adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, names);        listView.setAdapter(adapter);        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {            @Override            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {                onClickItemListener.clickedItem(position);                Toast.makeText(getActivity(), ((TextView) view).getText(), Toast.LENGTH_SHORT).show();            }        });        return view;    }    //回调接口用于传递数据    public interface OnClickItemListener {        void clickedItem(int position);    }}
这里我们定义了一个接口OnClickItemListener用于和Activity通信。

右边的Fragment:

public class AFragment extends Fragment {    private View view;    private ImageView imageView;    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        view = inflater.inflate(R.layout.afragment_layout, null);        imageView = (ImageView) view.findViewById(R.id.afragment_imgv);        imageView.setImageResource(R.drawable.girl);        return view;    }    @Override    public void onResume() {        super.onResume();        Bundle bundle = getArguments();        if (bundle != null) {            switch (bundle.getInt("position")) {                case 0:                    imageView.setImageResource(R.drawable.loveliness);                    break;                case 1:                    imageView.setImageResource(R.drawable.lively);                    break;                case 2:                    imageView.setImageResource(R.drawable.ripe);                    break;                case 3:                    imageView.setImageResource(R.drawable.noble);                    break;                case 4:                    imageView.setImageResource(R.drawable.gentle);                    break;                default:                    imageView.setImageResource(R.drawable.girl);            }        }    }}
这里代码很简单我就不多说了,下面重点是如何把这两个Fragment添加到Activity中和他们之间如何通信的。既然Activity是这两个Fragment的宿主,那么Activity和Fragment的通信自然是很简单的,既然Activity和Fragment通信很简单而且两个Fragment又是在同一个Activity中,那么他们之间的通信自然就很方便了,没错,我们就是使用Activity作为中转类似于手机通信中的基站的作用。前面一个Fragment已经提供了一个接口,我们只需要让Activity实现这个接口就可以了,至于把Fragment添加到Activity中的问题,我们前面已经提供了2个容器控件,这里就非常简单了,代码如下

   getFragmentManager().beginTransaction().replace(R.id.containerA, new AFragment()).commit();        getFragmentManager().beginTransaction().replace(R.id.containerB, new BFragment()).commit();

没错,简单的我都不想再和你提什么了!来看Activity的完整代码

public class MainActivity extends Activity implements BFragment.OnClickItemListener {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        getFragmentManager().beginTransaction().replace(R.id.containerA, new AFragment()).commit();        getFragmentManager().beginTransaction().replace(R.id.containerB, new BFragment()).commit();    }    @Override    public void clickedItem(int position) {        AFragment aFragment = new AFragment();        Bundle bundle = new Bundle();        bundle.putInt("position", position);        aFragment.setArguments(bundle);        getFragmentManager().beginTransaction().replace(R.id.containerA, aFragment).addToBackStack(null).commit();    }}

扫描关注我的微信公众号:




是不是特别简单呢??我们只需要在重写的方法中动态的去创建右边的Fragment就可以把点击的位置传过去了,很微妙的一种方式,如果你对这个不太熟可以慢慢的体会其中的关系,这里我给大家说说大致的思路:左边的Fragment我们提供了一个接口,而里面又有一个属性是这个接口,属性指向Activity,当使用接口中的方法的时候系统会去找实现了这个接口的类,自然就找到了Activity了,也就是会执行Activity中重写的clickItem方法,因为这个方法在Activity中,我们自己可以在这个方法中动态的去创建又变的Fragment并且把点击的位置传给它。回调接口的时候刚开始我也不是很会,慢慢的不管他然后自己就回了,真是奇怪!!Fragment的知识大致就是这么多吧,最后送上demo给大家:点击打开链接





2 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 对象想跟你啪啪怎么办 相亲对象好像不太想理我怎么办 想跟对象分手了怎么办 异地恋分手后该怎么办 面膜敷了一晚上怎么办 梦见被刺猬咬了怎么办 梦见死人叫我名字答应怎么办 香瓜苗叶子长斑怎么办 奶油打出来很稀怎么办 寄的水果压坏了怎么办 吃了一个烂水果怎么办 孕期吃了烂水果怎么办 邮快递水果坏了怎么办 快递寄水果坏了怎么办 闲鱼买家拒收水果怎么办 洗澡桶里有很多老鼠屎怎么办? 塑料和金属断了怎么办 孕妇吃了沙拉酱怎么办 孕妇淀粉吃多了怎么办 怀孕初期吃了杏怎么办 如果睡觉吃梨了怎么办 怀孕6个月有点贫血怎么办 怀孕八个多月有点贫血怎么办 生完小孩身体虚怎么办 孩子咳嗽厉害怎么办吃什么药 新生儿三天不拉大便怎么办 胃吃的变大了怎么办 小孩长高长的慢怎么办 小孩长高长得慢怎么办 小孩吃东西不吸收营养怎么办 婴儿长得太快怎么办 2个月婴儿长太快怎么办 孩子脚长得太快怎么办 4个月宝宝缺钙怎么办 2个月宝宝不长肉怎么办 小孩子长得不高怎么办 宝宝误吃蜂蜜了怎么办 有人拿着吃完的东西退货怎么办 婴儿个子长的慢怎么办 儿童长得太快怎么办 宝宝个子长太快怎么办