Fragment切換重疊的問題

關于切屏時重疊問題,辦法的核心是給每個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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容