之前寫的第一篇Fragment執行個體,和大多數人一開始學的一樣。都是通過FragmentTransaction的replace方法來實作,replace方法相當于先移除remove()原來全部已存在的fragments,然後加入add()目前這個fragment。這就導緻了一個問題,我們切換一次,然後再切換回來,相當于又一次載入了這個fragment,原來的狀态不複存在,這顯然與我們的日常使用不符。
想要儲存切換後的狀态。思路還是非常easy的。我們先加入了若幹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後并沒有進行其它生命周期,僅僅是簡單地隐藏了起來。這樣應該非常明了了吧。