關于切屏時重疊問題,辦法的核心是給每個fragment都設置一個tag,方法是transaction.add(R.id.content, messageFragment,"message");
這樣在豎屏切橫屏的時候用findFragmentByTag("message")
去拿fragment,這樣fragment就不會都為空了。
if(meFragment == null){
meFragment = new MeFragment();
transaction.add(R.id.framelayout_content, meFragment);
}
這種寫法在重建的時候有問題
meFragment = getFragmentManager().findFragmentByTag(tag);
然后如果null才meFragment = new MeFragment();
解決方案
完整Demo
package com.example.fragmentdemo;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.TextView;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.graphics.Color;
/**
* 項目的主Activity,所有的Fragment都嵌入在這里。
*
* @author guolin
*/
public class MainActivity extends Activity implements OnClickListener {
/**
* 用于展示消息的Fragment
*/
private MessageFragment messageFragment;
/**
* 用于展示聯系人的Fragment
*/
private ContactsFragment contactsFragment;
/**
* 用于展示動態的Fragment
*/
private NewsFragment newsFragment;
/**
* 用于展示設置的Fragment
*/
private SettingFragment settingFragment;
/**
* 消息界面布局
*/
private View messageLayout;
/**
* 聯系人界面布局
*/
private View contactsLayout;
/**
* 動態界面布局
*/
private View newsLayout;
/**
* 設置界面布局
*/
private View settingLayout;
/**
* 在Tab布局上顯示消息圖標的控件
*/
private ImageView messageImage;
/**
* 在Tab布局上顯示聯系人圖標的控件
*/
private ImageView contactsImage;
/**
* 在Tab布局上顯示動態圖標的控件
*/
private ImageView newsImage;
/**
* 在Tab布局上顯示設置圖標的控件
*/
private ImageView settingImage;
/**
* 在Tab布局上顯示消息標題的控件
*/
private TextView messageText;
/**
* 在Tab布局上顯示聯系人標題的控件
*/
private TextView contactsText;
/**
* 在Tab布局上顯示動態標題的控件
*/
private TextView newsText;
/**
* 在Tab布局上顯示設置標題的控件
*/
private TextView settingText;
/**
* 用于對Fragment進行管理
*/
private FragmentManager fragmentManager;
/**
* 保存當前顯示的是第幾頁
*/
private int currentPage = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("neo", "onCreate");
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
if(null != savedInstanceState){
currentPage = savedInstanceState.getInt("neo");
}
// 初始化布局元素
initViews();
fragmentManager = getFragmentManager();
//在FragmentManager里面根據Tag去找相應的fragment. 用戶屏幕發生旋轉,重新調用onCreate方法。否則會發生重疊
messageFragment = (MessageFragment) fragmentManager.findFragmentByTag("message");
contactsFragment = (ContactsFragment) fragmentManager.findFragmentByTag("contacts");
newsFragment = (NewsFragment) fragmentManager.findFragmentByTag("news");
settingFragment = (SettingFragment) fragmentManager.findFragmentByTag("setting");
// 第一次啟動時選中第0個tab
setTabSelection(currentPage);
}
/**
* 在這里獲取到每個需要用到的控件的實例,并給它們設置好必要的點擊事件。
*/
private void initViews() {
messageLayout = findViewById(R.id.message_layout);
contactsLayout = findViewById(R.id.contacts_layout);
newsLayout = findViewById(R.id.news_layout);
settingLayout = findViewById(R.id.setting_layout);
messageImage = (ImageView) findViewById(R.id.message_image);
contactsImage = (ImageView) findViewById(R.id.contacts_image);
newsImage = (ImageView) findViewById(R.id.news_image);
settingImage = (ImageView) findViewById(R.id.setting_image);
messageText = (TextView) findViewById(R.id.message_text);
contactsText = (TextView) findViewById(R.id.contacts_text);
newsText = (TextView) findViewById(R.id.news_text);
settingText = (TextView) findViewById(R.id.setting_text);
messageLayout.setOnClickListener(this);
contactsLayout.setOnClickListener(this);
newsLayout.setOnClickListener(this);
settingLayout.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.message_layout:
// 當點擊了消息tab時,選中第1個tab
setTabSelection(0);
currentPage = 0;
break;
case R.id.contacts_layout:
// 當點擊了聯系人tab時,選中第2個tab
setTabSelection(1);
currentPage = 1;
break;
case R.id.news_layout:
// 當點擊了動態tab時,選中第3個tab
setTabSelection(2);
currentPage = 2;
break;
case R.id.setting_layout:
// 當點擊了設置tab時,選中第4個tab
setTabSelection(3);
currentPage = 3;
break;
default:
break;
}
}
/**
* 根據傳入的index參數來設置選中的tab頁。
*
* @param index
* 每個tab頁對應的下標。0表示消息,1表示聯系人,2表示動態,3表示設置。
*/
private void setTabSelection(int index) {
// 每次選中之前先清楚掉上次的選中狀態
clearSelection();
// 開啟一個Fragment事務
FragmentTransaction transaction = fragmentManager.beginTransaction();
// 先隱藏掉所有的Fragment,以防止有多個Fragment顯示在界面上的情況
hideFragments(transaction);
//Log.i("neo", "消息為空? "+messageFragment+"--聯系人為空? "+contactsFragment+"-- 動態為空? "+newsFragment+"-- 設置為空? "+settingFragment);
switch (index) {
case 0:
// 當點擊了消息tab時,改變控件的圖片和文字顏色
messageImage.setImageResource(R.drawable.message_selected);
messageText.setTextColor(Color.WHITE);
//messageFragment = (MessageFragment) fragmentManager.findFragmentByTag("message");
if (messageFragment == null) {
// 如果MessageFragment為空,則創建一個并添加到界面上
messageFragment = new MessageFragment();
transaction.add(R.id.content, messageFragment,"message");
} else {
// 如果MessageFragment不為空,則直接將它顯示出來
transaction.show(messageFragment);
}
break;
case 1:
// 當點擊了聯系人tab時,改變控件的圖片和文字顏色
contactsImage.setImageResource(R.drawable.contacts_selected);
contactsText.setTextColor(Color.WHITE);
// contactsFragment = (ContactsFragment) fragmentManager.findFragmentByTag("contacts");
if (contactsFragment == null) {
// 如果ContactsFragment為空,則創建一個并添加到界面上
contactsFragment = new ContactsFragment();
transaction.add(R.id.content, contactsFragment,"contacts");
} else {
// 如果ContactsFragment不為空,則直接將它顯示出來
transaction.show(contactsFragment);
}
break;
case 2:
// 當點擊了動態tab時,改變控件的圖片和文字顏色
newsImage.setImageResource(R.drawable.news_selected);
newsText.setTextColor(Color.WHITE);
// newsFragment = (NewsFragment) fragmentManager.findFragmentByTag("news");
if (newsFragment == null) {
// 如果NewsFragment為空,則創建一個并添加到界面上
newsFragment = new NewsFragment();
transaction.add(R.id.content, newsFragment,"news");
} else {
// 如果NewsFragment不為空,則直接將它顯示出來
transaction.show(newsFragment);
}
break;
case 3:
default:
// 當點擊了設置tab時,改變控件的圖片和文字顏色
settingImage.setImageResource(R.drawable.setting_selected);
settingText.setTextColor(Color.WHITE);
// settingFragment = (SettingFragment) fragmentManager.findFragmentByTag("setting");
if (settingFragment == null) {
// 如果SettingFragment為空,則創建一個并添加到界面上
settingFragment = new SettingFragment();
transaction.add(R.id.content, settingFragment,"setting");
} else {
// 如果SettingFragment不為空,則直接將它顯示出來
transaction.show(settingFragment);
}
break;
}
transaction.commit();
}
/**
* 清除掉所有的選中狀態。
*/
private void clearSelection() {
messageImage.setImageResource(R.drawable.message_unselected);
messageText.setTextColor(Color.parseColor("#82858b"));
contactsImage.setImageResource(R.drawable.contacts_unselected);
contactsText.setTextColor(Color.parseColor("#82858b"));
newsImage.setImageResource(R.drawable.news_unselected);
newsText.setTextColor(Color.parseColor("#82858b"));
settingImage.setImageResource(R.drawable.setting_unselected);
settingText.setTextColor(Color.parseColor("#82858b"));
}
/**
* 將所有的Fragment都置為隱藏狀態。
*
* @param transaction
* 用于對Fragment執行操作的事務
*/
private void hideFragments(FragmentTransaction transaction) {
if (messageFragment != null) {
transaction.hide(messageFragment);
}
if (contactsFragment != null) {
transaction.hide(contactsFragment);
}
if (newsFragment != null) {
transaction.hide(newsFragment);
}
if (settingFragment != null) {
transaction.hide(settingFragment);
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt("neo",currentPage);
super.onSaveInstanceState(outState);
Log.i("neo", "onSaveInstanceState");
}
}
其他項目源碼樣板
AndroidFire-master
public class MainActivity extends BaseActivity {
@Bind(R.id.tab_layout)
CommonTabLayout tabLayout;
private String[] mTitles = {"首頁", "美女","視頻","關注"};
private int[] mIconUnselectIds = {
R.mipmap.ic_home_normal,R.mipmap.ic_girl_normal,R.mipmap.ic_video_normal,R.mipmap.ic_care_normal};
private int[] mIconSelectIds = {
R.mipmap.ic_home_selected,R.mipmap.ic_girl_selected, R.mipmap.ic_video_selected,R.mipmap.ic_care_selected};
private ArrayList<CustomTabEntity> mTabEntities = new ArrayList<>();
private NewsMainFragment newsMainFragment;
private PhotosMainFragment photosMainFragment;
private VideoMainFragment videoMainFragment;
private CareMainFragment careMainFragment;
private static int tabLayoutHeight;
/**
* 入口
* @param activity
*/
public static void startAction(Activity activity){
Intent intent = new Intent(activity, MainActivity.class);
activity.startActivity(intent);
activity.overridePendingTransition(R.anim.fade_in,
com.jaydenxiao.common.R.anim.fade_out);
}
@Override
public int getLayoutId() {
return R.layout.act_main;
}
@Override
public void initPresenter() {
}
@Override
public void initView() {
//此處填上在http://fir.im/注冊賬號后獲得的API_TOKEN以及APP的應用ID
UpdateKey.API_TOKEN = AppConfig.API_FIRE_TOKEN;
UpdateKey.APP_ID = AppConfig.APP_FIRE_ID;
//如果你想通過Dialog來進行下載,可以如下設置
// UpdateKey.DialogOrNotification=UpdateKey.WITH_DIALOG;
UpdateFunGO.init(this);
//初始化菜單
initTab();
}
@Override
public void onCreate(Bundle savedInstanceState) {
//切換daynight模式要立即變色的頁面
ChangeModeController.getInstance().init(this,R.attr.class);
super.onCreate(savedInstanceState);
//初始化frament
initFragment(savedInstanceState);
tabLayout.measure(0,0);
tabLayoutHeight=tabLayout.getMeasuredHeight();
//監聽菜單顯示或隱藏
mRxManager.on(AppConstant.MENU_SHOW_HIDE, new Action1<Boolean>() {
@Override
public void call(Boolean hideOrShow) {
startAnimation(hideOrShow);
}
});
}
/**
* 初始化tab
*/
private void initTab() {
for (int i = 0; i < mTitles.length; i++) {
mTabEntities.add(new TabEntity(mTitles[i], mIconSelectIds[i], mIconUnselectIds[i]));
}
tabLayout.setTabData(mTabEntities);
//點擊監聽
tabLayout.setOnTabSelectListener(new OnTabSelectListener() {
@Override
public void onTabSelect(int position) {
SwitchTo(position);
}
@Override
public void onTabReselect(int position) {
}
});
}
/**
* 初始化碎片
*/
private void initFragment(Bundle savedInstanceState) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
int currentTabPosition = 0;
if (savedInstanceState != null) {
newsMainFragment = (NewsMainFragment) getSupportFragmentManager().findFragmentByTag("newsMainFragment");
photosMainFragment = (PhotosMainFragment) getSupportFragmentManager().findFragmentByTag("photosMainFragment");
videoMainFragment = (VideoMainFragment) getSupportFragmentManager().findFragmentByTag("videoMainFragment");
careMainFragment = (CareMainFragment) getSupportFragmentManager().findFragmentByTag("careMainFragment");
currentTabPosition = savedInstanceState.getInt(AppConstant.HOME_CURRENT_TAB_POSITION);
} else {
newsMainFragment = new NewsMainFragment();
photosMainFragment = new PhotosMainFragment();
videoMainFragment = new VideoMainFragment();
careMainFragment = new CareMainFragment();
transaction.add(R.id.fl_body, newsMainFragment, "newsMainFragment");
transaction.add(R.id.fl_body, photosMainFragment, "photosMainFragment");
transaction.add(R.id.fl_body, videoMainFragment, "videoMainFragment");
transaction.add(R.id.fl_body, careMainFragment, "careMainFragment");
}
transaction.commit();
SwitchTo(currentTabPosition);
tabLayout.setCurrentTab(currentTabPosition);
}
/**
* 切換
*/
private void SwitchTo(int position) {
LogUtils.logd("主頁菜單position" + position);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
switch (position) {
//首頁
case 0:
transaction.hide(photosMainFragment);
transaction.hide(videoMainFragment);
transaction.hide(careMainFragment);
transaction.show(newsMainFragment);
transaction.commitAllowingStateLoss();
break;
//美女
case 1:
transaction.hide(newsMainFragment);
transaction.hide(videoMainFragment);
transaction.hide(careMainFragment);
transaction.show(photosMainFragment);
transaction.commitAllowingStateLoss();
break;
//視頻
case 2:
transaction.hide(newsMainFragment);
transaction.hide(photosMainFragment);
transaction.hide(careMainFragment);
transaction.show(videoMainFragment);
transaction.commitAllowingStateLoss();
break;
//關注
case 3:
transaction.hide(newsMainFragment);
transaction.hide(photosMainFragment);
transaction.hide(videoMainFragment);
transaction.show(careMainFragment);
transaction.commitAllowingStateLoss();
break;
default:
break;
}
}
/**
* 菜單顯示隱藏動畫
* @param showOrHide
*/
private void startAnimation(boolean showOrHide){
final ViewGroup.LayoutParams layoutParams = tabLayout.getLayoutParams();
ValueAnimator valueAnimator;
ObjectAnimator alpha;
if(!showOrHide){
valueAnimator = ValueAnimator.ofInt(tabLayoutHeight, 0);
alpha = ObjectAnimator.ofFloat(tabLayout, "alpha", 1, 0);
}else{
valueAnimator = ValueAnimator.ofInt(0, tabLayoutHeight);
alpha = ObjectAnimator.ofFloat(tabLayout, "alpha", 0, 1);
}
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
layoutParams.height= (int) valueAnimator.getAnimatedValue();
tabLayout.setLayoutParams(layoutParams);
}
});
AnimatorSet animatorSet=new AnimatorSet();
animatorSet.setDuration(500);
animatorSet.playTogether(valueAnimator,alpha);
animatorSet.start();
}
/**
* 監聽全屏視頻時返回鍵
*/
@Override
public void onBackPressed() {
if (JCVideoPlayer.backPress()) {
return;
}
super.onBackPressed();
}
/**
* 監聽返回鍵
*
* @param keyCode
* @param event
* @return
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
moveTaskToBack(false);
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//奔潰前保存位置
LogUtils.loge("onSaveInstanceState進來了1");
if (tabLayout != null) {
LogUtils.loge("onSaveInstanceState進來了2");
outState.putInt(AppConstant.HOME_CURRENT_TAB_POSITION, tabLayout.getCurrentTab());
}
}
@Override
protected void onResume() {
super.onResume();
UpdateFunGO.onResume(this);
}
@Override
protected void onStop() {
super.onStop();
UpdateFunGO.onStop(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
ChangeModeController.onDestory();
}
}
優化hideAllFragment的方式(未解決重疊)
上面兩個樣板都是 先hide所有的fragment,再show,這樣并不好。可以標記當前的fragment,顯示下一個fragment時候僅僅隱藏當前的(old)fragment,RTVCenter中輪播圖的顯示也是此方式。
public class MainActivity extends BaseActivity {
private LearnFragment learnFragment;
private YoungFragment youngFragment;
private JokeFragment jokeFragment;
private SuperBoonFragment superFragment;
private Fragment oldFragment;
@Bind(R.id.bottomBar)
BottomBar mBottomBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initActionbar();
setAppAbout();
initBottom();
initFragmentContent();
}
/**
* 設置中間內容頁
*/
private void initFragmentContent() {
learnFragment = new LearnFragment();
getSupportFragmentManager().beginTransaction().add(R.id.fragment_content, learnFragment).commit();
oldFragment = learnFragment;
}
/**
* 設置底部按鈕
*/
private void initBottom() {
mBottomBar.setOnTabSelectListener(new OnTabSelectListener() {
@Override
public void onTabSelected(@IdRes int tabId) {
switch (tabId) {
case R.id.menu_learn: //學習
setActTitle(R.string.menu_learn_msg);
toFragment(learnFragment);
break;
case R.id.menu_joke: //開心
checkNet(1);
break;
case R.id.menu_young: //美女
checkNet(2);
break;
case R.id.menu_super: //超級福利
checkNet(3);
break;
default:
setActTitle(R.string.menu_learn_msg);
toFragment(learnFragment);
break;
}
}
});
}
/**
* 檢查網絡,并跳轉
*/
private void checkNet(final int position) {
if (NetStatusUtil.isWifi(MainActivity.this)) {
goFragment(position);
} else {
final MaterialDialog mMaterialDialog = new MaterialDialog(this);
mMaterialDialog.setTitle("提示");
mMaterialDialog.setMessage("您當前不是WIFI狀態,訪問會消耗大量的流量,您確定要訪問嗎?");
mMaterialDialog.setPositiveButton("沒事兒拼了", new View.OnClickListener() {
@Override
public void onClick(View v) {
goFragment(position);
mMaterialDialog.dismiss();
}
});
mMaterialDialog.setNegativeButton("還是不看了", new View.OnClickListener() {
@Override
public void onClick(View v) {
mMaterialDialog.dismiss();
showToast("(*^__^*) 沒事去讀書學習吧");
mBottomBar.selectTabWithId(R.id.menu_learn);
}
});
mMaterialDialog.show();
}
}
private void goFragment(int position) {
switch (position) {
case 1://開心
{
setActTitle(R.string.menu_joke_msg);
if (jokeFragment == null) {
jokeFragment = new JokeFragment();
}
toFragment(jokeFragment);
break;
}
case 2: //美女
{
setActTitle(R.string.menu_young_msg);
if (youngFragment == null) {
youngFragment = new YoungFragment();
}
toFragment(youngFragment);
break;
}
case 3: //超級福利
{
setActTitle(R.string.menu_super_msg);
if (superFragment == null) {
superFragment = new SuperBoonFragment();
}
toFragment(superFragment);
break;
}
default:
break;
}
}
/**
* 切換Fragment
*
* @param to 下一個Fragment頁面
*/
private void toFragment(Fragment to) {
if (to == oldFragment) return;
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction().setCustomAnimations(android
.R.anim.fade_in, android.R.anim.fade_out);
if (!to.isAdded()) { // 先判斷是否被add過
transaction.hide(oldFragment).add(R.id.fragment_content, to).commit(); // 隱藏當前的fragment,add下一個到Activity中
} else {
transaction.hide(oldFragment).show(to).commit(); // 隱藏當前的fragment,顯示下一個
}
oldFragment = to;
}
private void setActTitle(int res) {
mActionTitle.setText(getString(res));
}
private long time = 0;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (System.currentTimeMillis() - time <= 2000) {
finish();
} else {
time = System.currentTimeMillis();
Toast.makeText(getApplicationContext(), R.string.exit_app, Toast.LENGTH_SHORT).show();
}
return true;
}
return super.onKeyDown(keyCode, event);
}
}
參考:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/0415/7830.html