在我自己做的几个app中,几乎每个主页都是长这样。对于可以滑动的主页,可以用ViewPager+Fragment来实现。对于不可滑动的,可以用FrameLayout+Fragment实现,这里又分两种情况,用replace来实现,则会频繁的创建和销毁Fragment,效率有点低;但是用hide/show来实现时,又会碰到状态保存和视图重叠的问题。怎样才算是最好的实践呢?

这里呢,我还是使用hide/show来实现Fragment的切换的,不过,这里做了一下当内存重启时Fragment状态的缓存,同时,又给每一个Fragment都设置了tag来防止重叠。
/**
* 主页卡基类-不可滑动
* <p>
* 作者:余天然 on 2017/3/13 下午4:09
*/
public abstract class TabActivity extends AppCompatActivity {
private static String CUR_TAB = "CUR_TAB";
private int curTab;//当前的tab的位置
private int tabNum;//tab的个数
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(CUR_TAB, curTab);
super.onSaveInstanceState(outState);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getContentViewId());
if (savedInstanceState != null) {
curTab = savedInstanceState.getInt(CUR_TAB, 0);
}
tabNum = getFragmentSize();
initButton();
switchTab(curTab);
}
protected abstract void initButton();
protected void switchTab(int pos) {
switchButton(pos);
switchFragment(pos);
curTab = pos;
}
protected abstract void switchButton(int pos);
private void switchFragment(int index) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
for (int i = 0; i < tabNum; i++) {
Fragment fragment = getFragmentWithCache(i);
if (i == index) {
if (fragment.isAdded()) {
transaction = transaction.show(fragment);
} else {
transaction = transaction.add(getFragmentViewId(), fragment, String.valueOf(i));
}
} else {
if (fragment.isAdded()) {
transaction = transaction.hide(fragment);
}
}
}
transaction.commit();
}
private Fragment getFragmentWithCache(int pos) {
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(String.valueOf(pos));
return fragment == null ? getFragment(pos) : fragment;
}
protected abstract int getContentViewId();
protected abstract int getFragmentViewId();
protected abstract int getFragmentSize();
protected abstract Fragment getFragment(int pos);
}
这样,当我们要使用时,就无需再关注Fragment之间切换和状态保存的具体逻辑了,只需要继承TabActivity即可:
public class MainActivity extends TabActivity {
private TextView[] tabs;
@Override
protected int getContentViewId() {
return R.layout.activity_main;
}
@Override
protected int getFragmentViewId() {
return R.id.fr_fragment;
}
@Override
protected int getFragmentSize() {
return 4;
}
@Override
protected Fragment getFragment(int pos) {
switch (pos) {
case 0:
return new HomeFragment();
case 1:
return new ChatFragment();
case 2:
return new FindFragment();
case 3:
return new MineFragment();
}
return null;
}
@Override
protected void initButton() {
TextView tvHome = (TextView) findViewById(R.id.tv_home);
TextView tvChat = (TextView) findViewById(R.id.tv_chat);
TextView tvFind = (TextView) findViewById(R.id.tv_find);
TextView tvMine = (TextView) findViewById(R.id.tv_mine);
tabs = new TextView[]{tvHome, tvChat, tvFind, tvMine};
for (int i = 0; i < tabs.length; i++) {
final int finalI = i;
tabs[i].setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
switchTab(finalI);
}
});
}
}
@Override
protected void switchButton(int pos) {
for (int i = 0; i < tabs.length; i++) {
if (i == pos) {
tabs[i].setSelected(true);
} else {
tabs[i].setSelected(false);
}
}
}
}
简单测试了一下,当手机开启“不保留活动”时,状态保存正常,并且没有出现重叠的问题。
最后,奉上Github地址:Best-Fragment
网友评论