您的位置:首页 > 移动开发 > Android开发

Android之Fragment回退栈详解

2016-09-20 09:54 225 查看

前言:本文将结合开发中的实际需求,来讲解一下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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息