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后并没有进行其他生命周期,只是简单地隐藏了起来。这样应该很明了了吧。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值