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();

Fragment切换重叠的问题_第1张图片
解决方案

完整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 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() {

            @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

你可能感兴趣的:(Fragment切换重叠的问题)