Android之Fragment回退栈详解

前言:本文将结合开发中的实际需求,来讲解一下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();
  •  

退出所有只剩首页而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;
    }
}

转载自:Android之Fragment回退栈详解

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值