之前写的第一篇Fragment实例,和大多数人一开始学的一样,都是通过FragmentTransaction的replace方法来实现,replace方法相当于先移除remove()原来所有已存在的fragments,然后添加add()当前这个fragment。这就导致了一个问题,我们切换一次,然后再切换回来,相当于重新加载了这个fragment,原来的状态不复存在,这显然与我们的日常使用不符。想要保存切换后的状态,思路还是很简单的,我们先添加了若干fragments,切换后将所有fragments都隐藏hide(),并显示show()切换后的fragment即可。

实例:山寨微信

由于代码较长,这里只讲核心的部分,有兴趣的可以下载源码来看一下

public class MainActivity extends ActionBarActivity implements OnClickListener {

  private View weixinLayout, tongxunluLayout, faxianLayout, woLayout;
private TextView weixinTv, tongxunluTv, faxianTv, woTv;
private ImageView weixinIv, tongxunluIv, faxianIv, woIv;
private Fragment1 fragment1;
private Fragment2 fragment2;
private Fragment3 fragment3;
private Fragment4 fragment4;
private FragmentManager fm; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化
initViews(); fm = getFragmentManager(); // 初识状态是显示微信
weixinIv.setBackgroundResource(R.drawable.weixin2);
weixinTv.setTextColor(getResources().getColor(R.color.green));
showFragment(1);
} void initViews() {
// 注册各IamgeView
weixinIv = (ImageView) findViewById(R.id.weixin_iv);
tongxunluIv = (ImageView) findViewById(R.id.tongxunlu_iv);
faxianIv = (ImageView) findViewById(R.id.faxian_iv);
woIv = (ImageView) findViewById(R.id.wo_iv); // 注册各TextView
weixinTv = (TextView) findViewById(R.id.weixin_tv);
tongxunluTv = (TextView) findViewById(R.id.tongxunlu_tv);
faxianTv = (TextView) findViewById(R.id.faxian_tv);
woTv = (TextView) findViewById(R.id.wo_tv); // 注册各Layout
weixinLayout = (View) findViewById(R.id.weixin_layout);
tongxunluLayout = (View) findViewById(R.id.tongxunlu_layout);
faxianLayout = (View) findViewById(R.id.faxian_layout);
woLayout = (View) findViewById(R.id.wo_layout); // 各Layout注册监听器
weixinLayout.setOnClickListener(this);
tongxunluLayout.setOnClickListener(this);
faxianLayout.setOnClickListener(this);
woLayout.setOnClickListener(this); } @Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
// 当点击某个layout时,先清除状态,这里的状态指的是布局里面的图片和文字
clearState();
switch (arg0.getId()) {
case R.id.weixin_layout:
// 如果点的是微信,将微信布局的图片和文字的颜色变为绿色
weixinIv.setBackgroundResource(R.drawable.weixin2);
weixinTv.setTextColor(getResources().getColor(R.color.green));
// 显示微信的fragment
showFragment(1);
break;
case R.id.tongxunlu_layout:
tongxunluIv.setBackgroundResource(R.drawable.tongxunlu2);
tongxunluTv.setTextColor(getResources().getColor(R.color.green));
showFragment(2);
break;
case R.id.faxian_layout:
faxianIv.setBackgroundResource(R.drawable.faxian2);
faxianTv.setTextColor(getResources().getColor(R.color.green));
showFragment(3);
break;
case R.id.wo_layout:
woIv.setBackgroundResource(R.drawable.wo2);
woTv.setTextColor(getResources().getColor(R.color.green));
showFragment(4);
break;
}
} public void clearState() {
// 未选中时的图片
weixinIv.setBackgroundResource(R.drawable.weixin1);
tongxunluIv.setBackgroundResource(R.drawable.tongxunlu1);
faxianIv.setBackgroundResource(R.drawable.faxian1);
woIv.setBackgroundResource(R.drawable.wo1);
// 未选中时字体颜色
weixinTv.setTextColor(getResources().getColor(R.color.black));
tongxunluTv.setTextColor(getResources().getColor(R.color.black));
faxianTv.setTextColor(getResources().getColor(R.color.black));
woTv.setTextColor(getResources().getColor(R.color.black));
} public void showFragment(int index) {
FragmentTransaction ft = fm.beginTransaction(); // 想要显示一个fragment,先隐藏所有fragment,防止重叠
hideFragments(ft); switch (index) {
case 1:
// 如果fragment1已经存在则将其显示出来
if (fragment1 != null)
ft.show(fragment1);
// 否则是第一次切换则添加fragment1,注意添加后是会显示出来的,replace方法也是先remove后add
else {
fragment1 = new Fragment1();
ft.add(R.id.content, fragment1);
}
break;
case 2:
if (fragment2 != null)
ft.show(fragment2);
else {
fragment2 = new Fragment2();
ft.add(R.id.content, fragment2);
}
break;
case 3:
if (fragment3 != null)
ft.show(fragment3);
else {
fragment3 = new Fragment3();
ft.add(R.id.content, fragment3);
}
break;
case 4:
if (fragment4 != null)
ft.show(fragment4);
else {
fragment4 = new Fragment4();
ft.add(R.id.content, fragment4);
}
break;
}
ft.commit();
} // 当fragment已被实例化,就隐藏起来
public void hideFragments(FragmentTransaction ft) {
if (fragment1 != null)
ft.hide(fragment1);
if (fragment2 != null)
ft.hide(fragment2);
if (fragment3 != null)
ft.hide(fragment3);
if (fragment4 != null)
ft.hide(fragment4);
} }

当我们一开始把微信fragment的ListView下拉到如上图时,切换到通讯录fragment,然后再切换回去微信fragment,此时微信的ListView还是原来的状态,这是因为并非重新加载微信fragment,而是将其先hide起来,切换回来后再show出来。

引用上篇文章的fragment生命周期图:

如果是repalce方法,我们切换至当前fragment则进行红线以上的生命周期,切换到其他fragment后进行红线以下的生命周期。但是,如果我们使用hide()和show()的方法, 切换至当前fragment依然进行红线以上的生命周期,切换到其他fragment后并没有进行其他生命周期,只是简单地隐藏了起来。这样应该很明了了吧。

源码:

http://download.csdn.net/detail/leelit/8179147

Android组件:Fragment切换后保存状态的更多相关文章

  1. Flutter - TabBar导航栏切换后,状态丢失

    上一篇讲到了 Flutter - BottomNavigationBar底部导航栏切换后,状态丢失 里面提到了TabBar,这儿专门再写一下吧,具体怎么操作,来不让TabBar的状态丢失.毕竟大家99 ...

  2. Fragment、Activity 保存状态

    Activity 保存状态1. void onCreate(Bundle savedInstanceState) 当Activity被第首次加载时执行.我们新启动一个程序的时候其主窗体的onCreat ...

  3. Android使得Fragment 切换时不重新实例化

    以前实现Fragment的切换都是用replace方法实现 public void startFragmentAdd(Fragment fragment) { FragmentManager frag ...

  4. Fragment实现底部Tab,切换可保存状态

    activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android& ...

  5. Android fragment切换后onresume时报 Attempt to write to field 'int android.support.v4.app.Fragment.mNextAnim'

    动态加载fragment以后,调用了remove方法移除Fragment,在返回来的时候报 Attempt to write to field 'int android.support.v4.app. ...

  6. 解决Fragment在Viepager中切换不保存状态的问题

    在FragmentPagerAdapter中重写以下方法: @Override public Object instantiateItem(ViewGroup container, int posit ...

  7. 16-Flutter移动电商实战-切换后页面状态的保持AutomaticKeepAliveClientMixin

    底栏切换每次都重新请求是一件非常恶心的事,flutter 中提供了AutomaticKeepAliveClientMixin 帮我们完成页面状态保存效果. 1.AutomaticKeepAliveCl ...

  8. Flutter移动电商实战 --(16)切换后页面状态的保持AutomaticKeepAliveClientMixin

    底栏切换每次都重新请求是一件非常恶心的事,flutter 中提供了AutomaticKeepAliveClientMixin 帮我们完成页面状态保存效果. 1.AutomaticKeepAliveCl ...

  9. Flutter - BottomNavigationBar底部导航栏切换后,状态丢失

    如果你用过BottomNavigationBar.TabBar.还有Drawer,你就会发现,在切换页面之后,原来的页面状态就会丢失. 要是上一页有一个数据列表,很多数据,你滚动到了下头,切换页面后, ...

随机推荐

  1. 关于Spring的BeanPostProcessor

    BeanPostProcessor接口作用是:如果我们需要在Spring容器完成Bean的实例化.配置和其他的初始化前后添加一些自己的逻辑处理,我们就可以定义一个或者多个BeanPostProcess ...

  2. 纯css画哆啦A梦

    今天有点无聊,照着网上的图写了个哆啦A梦,无技术可言,纯考耐心. <!doctype html> <html lang="en"> <head> ...

  3. QT学习 之 对话框 (四) 字体对话框、消息对话框、文件对话框、进程对话框(超详细中文注释)

    QMessageBox类: 含有Question消息框.Information消息框.Warning消息框和Critical消息框等 通常有两种方式可以来创建标准消息对话框: 一种是采用“基于属性”的 ...

  4. 禁用 Windows Azure 网站中的 ARR 实例关联

    编辑人员注释: 本博客文章由 Windows Azure 网站团队的项目经理 Erez Benari 撰写. 在 Windows Azure 网站中设置网站的多个实例是横向扩展网站的绝佳方式,Azur ...

  5. F#实现的单链表(函数式的思想)

    // 在 http://fsharp.net 上了解有关 F# 的更多信息 // 请参阅“F# 教程”项目以获取更多帮助. type list = | Nil | Cons of int * list ...

  6. Python 中的list小结

    list的下标和子list list的下表从零开始,和C语言挺类似的,但是增加了负下标的使用. -len-----第一个元素 ......       ...... -2 ------ 倒数第二个元素 ...

  7. c++构造函数析构函数调用顺序

    #include <iostream> using namespace std; class A { public: A () { cout<<"A 构造 " ...

  8. BZOJ 2654: tree( 二分 + MST )

    我们给白色的边增加权值 , 则选到的白色边就会变多 , 因此可以二分一下. 不过这道题有点小坑... ------------------------------------------------- ...

  9. Linux下查看二进制文件命令

    一.在Linux下查看二进制文件的软件: xxd hexdump 二.编辑: 1.biew 2.hexedit 3.vim Vim 来编辑二进制文件.Vim 本非为此而设计的,因而有若干局限.但你能读 ...

  10. yii_wiki_145_yii-cjuidialog-for-create-new-model (通过CJuiDialog来创建新的Model)

    /**** CJuiDialog for create new model http://www.yiiframework.com/wiki/145/cjuidialog-for-create-new ...