之前写的第一篇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. BZOJ 3675: [Apio2014]序列分割( dp + 斜率优化 )

    WA了一版... 切点确定的话, 顺序是不会影响结果的..所以可以dp dp(i, k) = max(dp(j, k-1) + (sumn - sumi) * (sumi - sumj)) 然后斜率优 ...

  2. BZOJ 1231: [Usaco2008 Nov]mixup2 混乱的奶牛( dp )

    状压dp dp( x , S ) 表示最后一个是 x , 当前选的奶牛集合为 S , 则状态转移方程 : dp( x , S ) =  Σ dp( i , S - { i } )  ( i ∈ S , ...

  3. apt-get 命令详解(中文),以及实例

    apt-get 命令详解(中文),以及实例 一,什么的是apt-get 高级包装工具(英语:Advanced Packaging Tools,简称:APT)是Debian及其衍生发行版(如:ubunt ...

  4. Python之路Day19

    志不坚者智不达. 主要内容:Django分页.自定义simpletag.权限管理 Django分页 Django自带了一个分页功能,使用起来很方便.官方文档 先来看一下效果图: 后台代码: def c ...

  5. android handler工作原理

    android handler工作原理 作用 便于在子线程中更新主UI线程中的控件 这里涉及到了UI主线程和子线程 UI主线程 它很特别.通常我们会认为UI主线程将页面绘制完成,就结束了.但是它没有. ...

  6. 学校作业-Dp练习

    题目 ★Stringsobits01 串  考虑排好序的 N(N<=31)位二进制数.  你会发现,这很有趣.因为他们是排列好的,而且包含所有可能的长度为 N 且含有 1 的个数小于等于 L(L ...

  7. Roseonly:互联网轻奢品牌之路-搜狐IT

    Roseonly:互联网轻奢品牌之路-搜狐IT Roseonly:互联网轻奢品牌之路

  8. c++隐藏实例

    隐藏:是指派生类的函数屏蔽了与其同名的基类函数,规则如下:(1)如果派生类的函数与基类的函数同名,但是参数不同.此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆). 很简单略去 ...

  9. [Swust OJ 1126]--神奇的矩阵(BFS,预处理,打表)

    题目链接:http://acm.swust.edu.cn/problem/1126/ Time limit(ms): 1000 Memory limit(kb): 65535 上一周里,患有XX症的哈 ...

  10. OpenSSL命令---req

    用途: 本指令用来创建和处理PKCS#10格式的证书.它还能够建立自签名证书,做Root CA. 用法: openssl req [-inform PEM|DER] [-outform PEM|DER ...