碎片Fragment

https://developer.android.google.cn/guide/components/fragments.html

一、什么是Fragment

Fragment(碎片)就是小型的Activity,它是在Android3.0时出现的。Fragment是表现Activity中UI的一个行为或者一部分。

可以把fragment想象成activity的一个模块化区域,有它自己的生命周期,接收属于它自己的输入事件,并且可以在activity运行期间添加和删除(有点像一个可以在不同的activity中重用的“子Activity”)。
Fragment必须被嵌入到一个activity中。它们的生命周期直接受其宿主activity的生命周期影响。当一个activity正在运行时,就可以独立地操作每一个Fragment,比如添加或删除它们。

Fragment可以定义自己的布局、生命周期回调方法,因此可以将fragment重用到多个activity中,因此可以根据不同的屏幕尺寸或者使用场合改变fragment组合。

二、如何创建一个Fragment

1、为Fragment定义一个布局
2、定义类继承Fragment
3、重写类中的onCreateView()方法,返回一个View对象作为当前Fragm
ent的布局。

fragment第一次绘制它的用户界面的时候,系统会调用onCreateView()方法。为了绘制fragment的UI,此方法必须返回一个作为fragment布局的根的view。如果fragment不提供UI,可以返回null。

/**
     * 定义类继承Fragment
     */
    public class TitleFragment extends Fragment {
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            //使用打气筒填充生成一个View对象,fragment_title是一个布局的根节点
            View view = inflater.inflate(R.layout.fragment_title, null);
            return view;
        }
    }

三、如何将Fragment添加到Activity

Activity必须在清单文件中进行声明,但是Fragment不需要,Fragment只需要在Activity的布局文件中声明就可以了。

<fragment
android:id="@+id/fmt_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:name="com.itheima.fragment.TitleFragment"
/>

注意:代码中的四个属性是必须的要给的,“android:name”属性:指定了在layout中实例化的Fragment类是哪个。当系统创建这个activity
layout时,它实例化每一个在layout中指定的Fragment,并调用它们的onCreateView()方法,来获取每一个Fragment的layout,系统将从Fragment返回的View直接插入到<fragment>元素所在的地方每一个fragment都需要一个唯一的标识,如果activity重启,系统可以用来恢
复Fragment,并且可以用id来捕获Fragment来处理事务,例如移除它。
有3种方法来为一个fragment提供一个ID,具体如下所示:

  • 为android:id属性提供一个唯一ID;
  • 为android:tag属性提供一个唯一字符串;
  • 如果以上2个你都没有提供,系统将使用容器view的ID;

四、如何切换Fragment

要在activity中管理Fragment,需要使用FragmentManager可以通过调用activity的getFragmentManager()取得它的实例。
案例:点击不同的按钮切换到不同的Fragment进行显示。具体实现步骤:
1、设置布局文件:添加三个按钮用于切换Fragment,并在按钮下方
添加一个FrameLayout用来替换成响应的Fragment。
2、创建三个Fragment,SportsFragment、NewsFragment、GameFragment。

public class SportsFragment extends Fragment {
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, 
                                 Bundle savedInstanceState) {
            // 使用打气筒生成一个View对象
            View view = inflater.inflate(R.layout.fragment_sports, null);
            return view;
        }
    }

其余两个Fragment跟SportsFragment代码一致,只是布局文件不同。
3、添加切换Fragment的逻辑,这个是新闻频道按钮的点击事件

public void news(View view){
        //获取Fragment管理器对象
        FragmentManager manager = getFragmentManager();
        //开启事务
        FragmentTransaction transaction = manager.beginTransaction();
        //将FrameLayout控件替换成Fragment对象
        transaction.replace(R.id.frame, new NewsFragment());
        //提交事务
        transaction.commit();
    }

sports()方法、games()方法同上,因此不再给出代码清单。
4、运行程序,效果如下
Fragment的生命周期
Fragment的生命周期和activity生命周期很像,其生命周期方法如下所示。

  • onAttach:绑定到activity
  • onCreate:创建fragment
  • onCreateView: 创建fragment的布局
  • onActivityCreated: activity创建完成后
  • onStart: 可见, 不可交互
  • onResume: 可见, 可交互
  • onPause: 部分可见, 不可交互
  • onStop:不可见
  • onDestroyView: 销毁fragment的view对象
  • onDestroy: fragment销毁了
  • onDetach: 从activity解绑了

五、Fragment的向下兼容

Fragment是在Android3.0才推出的,若想在3.0的低版本下使用Fragment,则需要执行下面2步:
1、把所有Fragment和FragmentManager改成support-v4包下的类
2、把Activity的继承改为FragmentActivity(support-v4包下的)

六、Fragment之间的通信案例

案例:创建一个用于显示选项卡的Fragment和一个用于显示内容的Fragment,当选项卡切换时,使内容的Fragment信息跟着一起切换。具体实现步骤如下所示:
1、先创建选项卡Fragment和内容Fragment,并在activity_main.xml布
局文件中进行设置,其布局效果如下:
2、为选项卡Fragment创建布局文件,其布局效果如下:
3、添加内容区域Fragment的代码逻辑

public class ContentFragment extends Fragment {
        private TextView  tv_title;//标题
        private ImageView iv_pic;//内容

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup
                container, Bundle savedInstanceState) {
            //使用打气筒填充布局
            View view = inflater.inflate(R.layout.fragment_content, null);
            //获取布局中的控件
            tv_title = (TextView)view.findViewById(R.id.tv_title);
            iv_pic = (ImageView) view.findViewById(R.id.iv_pic);
            return view;
        }

        //定义一个方法,用于改变标题和图片
        public void setTitleAndImage(String title, int picId) {
            tv_title.setText(title);
            iv_pic.setImageResource(picId);
        }
    }

4、添加选项卡区域Fragment的代码逻辑

public class TabFragment extends Fragment implements OnItemClickListener {
        private String[] datas;
        private int[]    picIds;

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup
                container, Bundle savedInstanceState) {
            //直接使用ListView作为布局,因此不需要布局文件
            ListView listView = new ListView(getActivity());
            //定义一些常量数据作为册数数据
            datas = new String[]{"新闻", "体育", "财经", "社会", "娱乐", "国际"};
            picIds = new int[]{R.drawable.a0, R.drawable.a1, R.drawable.a2, R.drawable.a3, 
                    R.d rawable.a4, R.drawable.a5};
            //设置点击事件
            listView.setOnItemClickListener(this);
            //声明一个ArrayAdapter对象
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
                    android.R.layout.simple_expandable_list_item_1, datas);
            //给ListView设置Adapter
            listView.setAdapter(adapter);
            //返回视图
            return listView;
        }

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            //获取当前的title和图片id
            String title = datas[position];
            int picId = picIds[position];
            //获取Fragment管理器
            FragmentManager manager = getFragmentManager();
            //通过ID选择出ContentFragment对象
            ContentFragment fragment = (ContentFragment) manager.findFragmentById(R.id.fragment_content);
            //调用ContentFragment的方法,给ContentFragment传递参数,实现不同Fragment直接的通信
            fragment.setTitleAndImage(title, picId);
        }
    }

Fragment与Activity如何交互?

这里我不再详细介绍那写比较常规的方式,例如静态变量,静态方法,持
久化,application全局变量,收发广播等等。
首先我们来介绍使用Handler来实现Fragment与Activity
的交互。第一步,我们需要在Activity中定义一个方法用来设置Handler对象。
public void setHandler(Handler handler) {
mHandler = handler;
}
第二步,在Fragment中的回调函数onAttach()中得到Fragment所在Activity,并调用setHandler方法,设置Handler。该Handler在Fragment中定义,用来接收消息与Fragment进行交互。

@Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        mActivity = (MainActivity) activity;
        mActivity.setHandler(mHandler);
    }
    public Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case 1:
                    text.setText((String) msg.obj);
                    break;
            }
        };
    };

然后我们可以在Activity中发送消息给Fragment中的Hanlder进行交互。

public void inter(View view) {
Message msg = new Message();
msg.obj = edit.getText().toString();
msg.what = 1;
mHandler.sendMessage(msg);
}

Fragment回退栈实现

public class MainActivity extends FragmentActivity implements OnClickListener {

    private FragmentA fragmentA;
    private FragmentB fragmentB;
    private FragmentC fragmentC;

    private List<Fragment> fragmentsList = new ArrayList<Fragment>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        findViewById(R.id.btnA).setOnClickListener(this);
        findViewById(R.id.btnB).setOnClickListener(this);
        findViewById(R.id.btnC).setOnClickListener(this);

        fragmentA = new FragmentA();
        fragmentB = new FragmentB();
        fragmentC = new FragmentC();


        //将三个Fragment添加到帧布局中

        /*
         * 1. 获取FragmentManger
         */
        FragmentManager fragmentManager = getSupportFragmentManager();
        /*
         * 2. 通过FragmentManager获取到事务管理器
         */
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        /*
         * 3. 将Fragment添加到帧布局中
         */
        transaction.
        add(R.id.fl, fragmentA, "FragmentA").
        add(R.id.fl, fragmentB,"FragmentB").
        add(R.id.fl, fragmentC,"FragmentC").
        hide(fragmentB).
        hide(fragmentC).
        commit();

        addToBackStack(fragmentA);

    }

    private void addToBackStack(Fragment fragment) {
        if (fragmentsList.contains(fragment)) {
            //先将老的对象移除
            fragmentsList.remove(fragment);
            //将Fragment添加到集合的最后
            fragmentsList.add(fragment);
        }else {
            fragmentsList.add(fragment);
        }
    }

    @Override
    public void onBackPressed() {
//      super.onBackPressed();
        if (fragmentsList.size()>1) {
            //移除最顶端的Fragment
            fragmentsList.remove(fragmentsList.size()-1);
            //将下一个Fragment给显示出来
            showFragment(fragmentsList.get(fragmentsList.size()-1));
        }else {
            //如果当前栈中没有Fragment或者只有一个Fragment,直接退出Activity
            finish();
        }


    }

    private void showFragment(Fragment fragment) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.hide(fragmentA).
        hide(fragmentB).
        hide(fragmentC).
        show(fragment)
        .commit();

    }

    @Override
    public void onClick(View v) {

        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

        transaction.hide(fragmentA).hide(fragmentB).hide(fragmentC);

        switch (v.getId()) {
        case R.id.btnA:
            transaction.show(fragmentA);
            addToBackStack(fragmentA);
            break;
        case R.id.btnB:
            transaction.show(fragmentB);
            addToBackStack(fragmentB);
            break;
        case R.id.btnC:
            transaction.show(fragmentC);
            addToBackStack(fragmentC);
            break;

        default:
            break;
        }

        //把当前事务添加到会退栈中
//      transaction.addToBackStack(null);

        transaction.commit();

    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值