Android组件:Fragment切换后保存状态
之前写的第一篇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切换后保存状态的更多相关文章
- Flutter - TabBar导航栏切换后,状态丢失
上一篇讲到了 Flutter - BottomNavigationBar底部导航栏切换后,状态丢失 里面提到了TabBar,这儿专门再写一下吧,具体怎么操作,来不让TabBar的状态丢失.毕竟大家99 ...
- Fragment、Activity 保存状态
Activity 保存状态1. void onCreate(Bundle savedInstanceState) 当Activity被第首次加载时执行.我们新启动一个程序的时候其主窗体的onCreat ...
- Android使得Fragment 切换时不重新实例化
以前实现Fragment的切换都是用replace方法实现 public void startFragmentAdd(Fragment fragment) { FragmentManager frag ...
- Fragment实现底部Tab,切换可保存状态
activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android& ...
- 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. ...
- 解决Fragment在Viepager中切换不保存状态的问题
在FragmentPagerAdapter中重写以下方法: @Override public Object instantiateItem(ViewGroup container, int posit ...
- 16-Flutter移动电商实战-切换后页面状态的保持AutomaticKeepAliveClientMixin
底栏切换每次都重新请求是一件非常恶心的事,flutter 中提供了AutomaticKeepAliveClientMixin 帮我们完成页面状态保存效果. 1.AutomaticKeepAliveCl ...
- Flutter移动电商实战 --(16)切换后页面状态的保持AutomaticKeepAliveClientMixin
底栏切换每次都重新请求是一件非常恶心的事,flutter 中提供了AutomaticKeepAliveClientMixin 帮我们完成页面状态保存效果. 1.AutomaticKeepAliveCl ...
- Flutter - BottomNavigationBar底部导航栏切换后,状态丢失
如果你用过BottomNavigationBar.TabBar.还有Drawer,你就会发现,在切换页面之后,原来的页面状态就会丢失. 要是上一页有一个数据列表,很多数据,你滚动到了下头,切换页面后, ...
随机推荐
- Linux下载文件时报错 To connect to ohse.de insecurely, use ‘--no-check-certificate’.
远程调用下载文件直接用wget就可以,一般文件路径类型是http.如果有遇到是https就会下载出错. 错误如下: [root@vmu010226-node1 tmp]# wget https://w ...
- CXF 开发 WebService
什么是CXF: Apache CXF = Celtix + Xfire 支持多种协议: SOAP1.1,1.2 XML/HTTP CORBA(Common Object Request Broker ...
- PHP学习建议(来自老手)
框架太多了,有一个用着,先用熟练,因为框架思想区别不大. 用熟悉一个,再看其他,就容易多.看那么多,没有一个熟悉的,还是什么也不知道. 框架还是要用熟悉才行,然后才是产品如何设计,mysql性能真的有 ...
- (Problem 28)Number spiral diagonals
Starting with the number 1 and moving to the right in a clockwise direction a 5 by 5 spiral is forme ...
- QR码生成原理
一.什么是QR码 QR码属于矩阵式二维码中的一个种类,由DENSO(日本电装)公司开发,由JIS和ISO将其标准化.QR码的样子其实在很多场合已经能够被看到了,我这还是贴个图展示一下: 这个图如果被正 ...
- hibernate Annotation 以及注解版的数据关联 4.4
目的是不写xxx.hbm.xml映射文件,使用注解 主配置文件还是要有hibernate.cfg.xml <?xml version="1.0" encoding=" ...
- 资源文件(.RES)的应用
资源档有什麽用处呢?最重要的有两个地方1.国际发行:我们将Application中所有的文字从Resource用读取,那麽,只要更动 Resource档的内容,就可以用不同语言的 ...
- 工商管理硕士(MBA)-北大国际MBA
工商管理硕士(MBA)-北大国际MBA [EMBA校友跨届晚会]不管风雨彩虹 我们永远在一起
- PHP中magic_quotes_gpc和 magic_quotes_runtime区别及其反斜线转义问题
php中关于反斜线转义: php中数据的魔法引用函数 magic_quotes_gpc 或 magic_quotes_runtime 设置为on时,当数据遇到 单引号' 和 双引号&quo ...
- UVA 10341 Solve It 解方程 二分查找+精度
题意:给出一个式子以及里面的常量,求出范围为[0,1]的解,精度要求为小数点后4为. 二分暴力查找即可. e^(-n)可以用math.h里面的exp(-n)表示. 代码:(uva该题我老是出现Subm ...