Android之Fragment回退栈详解

来源:互联网 发布:少儿编程工具排行榜 编辑:程序博客网 时间:2024/05/19 17:58

前言:本文将结合开发中的实际需求,来讲解一下Fragment中的回退栈 对于Activity,当按返回键时,能够返回到上一个Activity,但是,当我们Fragment到Activity中时,如果不做任何处理,当按返回键时,当前Fragment都会全部退出,如果想要拥有Activity逐渐退出的效果,我们需要应用一下Fragment中的回退栈.

视频地址:
代码地址:

案例效果

这里写图片描述这里写图片描述

案例描述

大家可以自行打开京东,你会发现,如果你点击了分类,发现,购物车,我的,按钮,再按返回键的话,会先回到首页,然后再退出应用.这里应用的就是Fragment的回退栈功能.,下面我将带领大家了解一下回退栈的实现逻辑

方法介绍

  • addToBackStack(tag); 将Fragment添加到回退栈中
  • popBackStack(); 清除回退栈中栈顶的Fragment
  • popBackStack(String tag, int i );
    • 如果i=0,回退到该tag所对应的Fragment层
    • 如果i=FragmentManager.POP_BACK_STACK_INCLUSIVE,回退到该tag所对应的Fragment的上一层
  • popBackStackImmediate 立即清除回退栈中栈顶Fragment
  • getBackStackEntryCount(); 获取回退栈中Fragment的个数
  • getBackStackEntryAt(int index) 获取回退栈中该索引值下的Fragment

逐层退出回退栈效果代码实现

布局代码,在布局中,写了一个FrameLayout,用来放置Fragment的容器;写了一个RadioGroup,用来放置下边的几个指示按钮

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <FrameLayout        android:id="@+id/framelayout"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1" />    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content" >        <RadioGroup            android:id="@+id/radioGroup"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:background="#ff0000"            android:orientation="horizontal" >            <RadioButton                android:id="@+id/rb_home"                android:layout_width="0dp"                android:layout_height="wrap_content"                android:layout_gravity="center_horizontal"                android:layout_weight="1"                android:button="@drawable/home_selector"                android:checked="true"                android:gravity="center_horizontal" />            <RadioButton                android:id="@+id/rb_cart"                android:layout_width="0dp"                android:layout_height="wrap_content"                android:layout_weight="1"                android:button="@drawable/cart_selector" />            <RadioButton                android:id="@+id/rb_category"                android:layout_width="0dp"                android:layout_height="wrap_content"                android:layout_weight="1"                android:button="@drawable/category_selector" />            <RadioButton                android:id="@+id/rb_personal"                android:layout_width="0dp"                android:layout_height="wrap_content"                android:layout_weight="1"                android:button="@drawable/personal_selector" />        </RadioGroup>    </LinearLayout></LinearLayout>

MainActivity中的代码

  • 初始化,在onCreate方法中
    • 初始化控件,并设置监听
    • 添加一个HomeFragment
@Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();        // 获取Fragment管理者        fragmentManager = getSupportFragmentManager();        // 先默认添加fragment1        addFragment(new Fragment1(), "fragment1");    }
  • 初始化控件给RadioButton设置监听
private void initView() {        radioGroup = (RadioGroup) findViewById(R.id.radioGroup);        rb_cart = (RadioButton) findViewById(R.id.rb_cart);        rb_category = (RadioButton) findViewById(R.id.rb_category);        rb_home = (RadioButton) findViewById(R.id.rb_home);        rb_personal = (RadioButton) findViewById(R.id.rb_personal);        // 对每一个RadioButton都设置点击事件,注意,在这里并没有对radioGroup设置checkChangeListener        rb_cart.setOnClickListener(this);        rb_category.setOnClickListener(this);        rb_home.setOnClickListener(this);        rb_personal.setOnClickListener(this);    }

*点击按钮时,替换Fragment

/**     * 根据点击的按钮---依次替换Fragment     */    @Override    public void onClick(View v) {        switch (v.getId()) {        case R.id.rb_home:            addFragment(new Fragment1(), "fragment1");            break;        case R.id.rb_cart:            addFragment(new Fragment2(), "fragment2");            break;        case R.id.rb_category:            addFragment(new Fragment3(), "fragment3");            break;        case R.id.rb_personal:            addFragment(new Fragment4(), "fragment4");            break;        default:            break;        }    }
  • 添加Fragment的时候,同时将Fragment放到回退栈中
public void addFragment(Fragment fragment, String tag) {        // 开启事务        FragmentTransaction beginTransaction = fragmentManager                .beginTransaction();        // 执行事务,添加Fragment        beginTransaction.add(R.id.framelayout, fragment, tag);        // 添加到回退栈,并定义标记        beginTransaction.addToBackStack(tag);        // 提交事务        beginTransaction.commit();    }
  • 监听Activity中的返回键,判断当前回退栈中的Fragment个数,如果回退栈中有大于一个,就一个个清除Fragment,如果只剩一个,说明只剩首页Fragment所对应的Fragment,就finish();
    @Override    public boolean onKeyDown(int keyCode, KeyEvent event) {        // 判断当前按键是返回键        if (keyCode == KeyEvent.KEYCODE_BACK) {            // 获取当前回退栈中的Fragment个数            int backStackEntryCount = fragmentManager.getBackStackEntryCount();            // 判断当前回退栈中的fragment个数,            if (backStackEntryCount > 1) {                // 立即回退一步                fragmentManager.popBackStackImmediate();                // 获取当前退到了哪一个Fragment上,重新获取当前的Fragment回退栈中的个数                BackStackEntry backStack = fragmentManager                        .getBackStackEntryAt(fragmentManager                                .getBackStackEntryCount() - 1);                // 获取当前栈顶的Fragment的标记值                String tag = backStack.getName();                // 判断当前是哪一个标记                if ("fragment1".equals(tag)) {                    // 设置首页选中                    rb_home.setChecked(true);                } else if ("fragment2".equals(tag)) {                    // 设置购物车的tag                    rb_cart.setChecked(true);                } else if ("fragment3".equals(tag)) {                    rb_category.setChecked(true);                } else if ("fragment4".equals(tag)) {                    rb_personal.setChecked(true);                }            } else {                //回退栈中只剩一个时,退出应用                finish();            }        }        return true;    }}

退出所有只剩首页而Fragment的代码

其他代码和上边一致,只需要修改一下退出的逻辑.需要判断当前回退栈中有多少个Fragment,使用While循环逐个退出.

    @Override    public boolean onKeyDown(int keyCode, KeyEvent event) {        // 判断当前按键是返回键        if (keyCode == KeyEvent.KEYCODE_BACK) {            // 获取当前回退栈中的Fragment个数            int backStackEntryCount = fragmentManager.getBackStackEntryCount();            // 回退栈中至少有多个fragment,栈底部是首页            if (backStackEntryCount > 1) {                // 如果回退栈中Fragment个数大于一.一直退出                while (fragmentManager.getBackStackEntryCount() > 1) {                    fragmentManager.popBackStackImmediate();                    //选中第一个界面                    rb_home.setChecked(true);                }            } else {                finish();            }        }        return true;    }}
0 0
原创粉丝点击