Fragment的切换导致重叠

刚接触fragment,之前在书上看的时候,由于它当时是加上了背景颜色,所以在切换的时候我没有去注意到重叠的问题。然后最近在做一个项目的时候用到fragment,才发现了这个问题。

我用RadioGroup里的RadioButton来做切换

package com.moke.activity;

public class CJD_CardPackageActivity extends Activity implements OnCheckedChangeListener {
    
    private RadioGroup radipGroup;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.cjd_cardpackageactivity);
    
        init();
        
    }
    
    
    private void init() {
        radipGroup = (RadioGroup)findViewById(R.id.cjd_CardPackageActivity_rgp);
        bindClick();
        
    }    
    
    private void bindClick(){
        radipGroup.setOnCheckedChangeListener(this);
    }

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        // TODO Auto-generated method stub
        
        CJD_Fragment_CardPackageUnused unusedFragment = new CJD_Fragment_CardPackageUnused();
        CJD_Fragment_CardPackageUsed usedFragment = new CJD_Fragment_CardPackageUsed();
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        
        switch (checkedId) {
        //切换到未使用页面
        case R.id.cjd_CardPackageActivity_rbtn_unused:
            transaction.replace(R.id.cjd_CardPackageActivity_fl_switch, unusedFragment);
            transaction.commit();
            break;
        //切换到使用页面
        case R.id.cjd_CardPackageActivity_rbtn_used:
            transaction.replace(R.id.cjd_CardPackageActivity_fl_switch, usedFragment);
            transaction.commit();
            break;
        default:
            break;
        }
        
    }
}

布局文件的代码cjd_cardpackageactivity.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
 
    <RadioGroup 
        android:id="@+id/cjd_CardPackageActivity_rgp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        
        <RadioButton 
            android:id="@+id/cjd_CardPackageActivity_rbtn_unused"
            style="@style/radioButtonInTop"
            android:text="@string/unused"
            android:checked="true"/>
        
        <RadioButton 
            android:id="@+id/cjd_CardPackageActivity_rbtn_used"
            style="@style/radioButtonInTop"
            android:text="@string/used"/>
    </RadioGroup>
    
   
    <FrameLayout 
        android:id="@+id/cjd_CardPackageActivity_fl_switch"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
         <fragment 
        
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.moke.fragment.CJD_Fragment_CardPackageUnused"/>
    
        
    </FrameLayout>
    
   

</LinearLayout>

一开始“未使用”的界面:
图片描述

切换到“已使用”界面
图片描述

切换回“未使用”界面并向下活动:
图片描述

这样就发现新的重叠在了原来的Fragment上,当然原来的Fragment是固定不动的,还保留着当时的位置。

这是修改后的代码,目前从效果上看已经没有了重叠的现象了,非常感谢“li21”!!

public class CJD_CardPackageActivity extends Activity implements OnCheckedChangeListener {
    
    private RadioGroup radipGroup;
    private FragmentTransaction transaction;
    private CJD_Fragment_CardPackageUnused unusedFragment;
    private CJD_Fragment_CardPackageUsed usedFragment;
    private FragmentManager fragmentManager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.cjd_cardpackageactivity);
        
        init();
        
    }
    
    
    private void init() {
        radipGroup = (RadioGroup)findViewById(R.id.cjd_CardPackageActivity_rgp);
        unusedFragment = new CJD_Fragment_CardPackageUnused();
        usedFragment = new CJD_Fragment_CardPackageUsed();        
        fragmentManager = getFragmentManager();
        
//        unusedFragment = (CJD_Fragment_CardPackageUnused) getFragmentManager().findFragmentByTag("unused");
//        usedFragment = (CJD_Fragment_CardPackageUsed) getFragmentManager().findFragmentByTag("used");
        transaction = fragmentManager.beginTransaction();
        transaction.add(R.id.cjd_CardPackageActivity_fl_switch, unusedFragment).commit();
        bindClick();
        
    }    
    
    private void bindClick(){
        radipGroup.setOnCheckedChangeListener(this);
    }

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        // TODO Auto-generated method stub

        switch (checkedId) {
        //切换到未使用页面
        case R.id.cjd_CardPackageActivity_rbtn_unused:
            
            transaction = fragmentManager.beginTransaction();
            transaction.replace(R.id.cjd_CardPackageActivity_fl_switch, unusedFragment);
            transaction.commit();
            break;
        //切换到使用页面
        case R.id.cjd_CardPackageActivity_rbtn_used:
            
            transaction = fragmentManager.beginTransaction();
            transaction.replace(R.id.cjd_CardPackageActivity_fl_switch, usedFragment);
            transaction.commit();
            break;
        default:
            break;
        }
        
    }
         
}

我把布局里的fragment删掉了,然后在一开始的时候把unusedFragment add上去。接下来的工作应该是我要去试一下fragment的切换过程中会不会重新加载这样的问题,找到了一些有关hide()和show()的东西。

阅读 17.9k
1 个回答

只从你贴出来的这段代码看,并不会造成重叠。所以我猜是你的其它代码造成的问题,根据我的测试情况,有两种可能:

可能1. 在你的布局文件内,存在一个组件,和你的R.id.cjd_CardPackageActivity_fl_switch 占据同样的位置。并且有代码向其中添加了usedFragment:ft.add或者replace(R.id.*, usedFragment);
因为资源ID会告诉FragmentManager fragment视图应该出现在activity视图的哪个位置。所以,如果先向其中一个ID添加了Fragment,然后又向另一个ID添加了Fragment,就会导致重叠。

可能2. 如果你贴出来的代码是位于Fragment中的代码(也就是说你是通过Fragment管理的这两个Fragment),在onCheckedChanged()方法以外,是不是也添加过Fragment?比如在onCreateView()中,先add了一个usedFragment,并且是通过getChildFragmentManager()获取的FragmentManager。
而你后面又是通过getFragmentManager()管理的Fragment,此时replace无法替换掉之前add的fragment,就导致了重叠。

我目前就测试到这两种情况会导致重叠。

如果上述列举的两种都不是造成你问题的原因,那么临时的解决办法是,加背景色;或者,参考这个答案的办法 http://segmentfault.com/q/1010000003731705/a-1020000003738254
在replace之前,先remove所有的子Fragment:

    if (fm.getFragments() != null && fm.getFragments().size() > 0) {
        for (Fragment cf : fm.getFragments()) {
            ft.remove(cf);
        }
    }

Update1

添加fragment到activity布局中,就等同于将fragment及其视图与activity的视图绑定在一起,且在activity的生命周期过程中,无法切换fragment视图。 《Android权威编程指南 the big nerd ranch guide 7.4.2》

所以把Layout中的fragment去掉就可以了,问题的原因在『可能1』 中给出了解释。

  <fragment 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.moke.fragment.CJD_Fragment_CardPackageUnused"/>

Update2 开始就没有默认显示“未使用”界面,而是要进行切换操作后才显示,要怎么处理?

在初始化的地方,add一个fragment以填充视图。

推荐问题
宣传栏