java – replace()无法与多片段一起正常工作

主要活动
package example.antonio.activitydemo;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.support.v4.app.*;

public class MainActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final FragmentManager fragmentManager = getSupportFragmentManager();

        Button button = (Button) findViewById(R.id.button);
        button.setonClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FirstFragment fragment = new FirstFragment();
                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

                fragmentTransaction.add(R.id.container,fragment);
                fragmentTransaction.commit();
            }
        });

        Button button2 = (Button) findViewById(R.id.button2);
        button2.setonClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SecondFragment fragment = new SecondFragment();
                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

                fragmentTransaction.replace(R.id.container,fragment);
                fragmentTransaction.commit();
            }
        });
    }
}

FirstFragment

package example.antonio.activitydemo;

import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.view.View;

public class FirstFragment extends Fragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInsanceState) {
        return inflater.inflate(R.layout.first_fragment,container,false);
    }
}

SecondFragment

package example.antonio.activitydemo;

import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.view.View;

public class SecondFragment extends Fragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater,Bundle savedInsanceState) {
        return inflater.inflate(R.layout.second_fragment,false);
    }
}

他们的XML文件

main_activity.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:id="@+id/container"
    android:orientation="vertical">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start1"
        android:id="@+id/button"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start2"
        android:id="@+id/button2"/>

</LinearLayout>

first_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#000000">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="First!"
        android:textColor="#ffffff"/>


</FrameLayout>

second_fragment.xml就像前一个一样,只有android:text =“Second!”

这是奇怪的事情,当我点击4次Start1按钮然后我得到4倍的单词First!,直到这里一切正常.如果我单击Start2按钮,我会期望删除前面的4个片段并添加一个新的片段,其外观为Second!.这是我从文档中理解的:

Replace an existing fragment that was added to a container. This is essentially the same as calling remove(Fragment) for all currently added fragments that were added with the same containerViewId and then add(int,Fragment,String) with the same arguments given here.

但这是我得到的:

After I click 4 times <code></p>Start1</code> button

After I click <code></p>Start2</code> button

我试着阅读源代码,也许我发现了什么是“问题”,我想知道你的想法,如果是我,我在某个地方犯了错误.

以下是BackStackRecord.java的片段,run()方法

case OP_REPLACE: {
                    Fragment f = op.fragment;
                    int containerId = f.mContainerId;
                    if (mManager.mAdded != null) {
                        for (int i = 0; i < mManager.mAdded.size(); i++) {
                            Fragment old = mManager.mAdded.get(i);
                            if (FragmentManagerImpl.DEBUG) {
                                Log.v(TAG,"OP_REPLACE: adding=" + f + " old=" + old);
                            }
                            if (old.mContainerId == containerId) {
                                if (old == f) {
                                    op.fragment = f = null;
                                } else {
                                    if (op.removed == null) {
                                        op.removed = new ArrayList<Fragment>();
                                    }
                                    op.removed.add(old);
                                    old.mNextAnim = op.exitAnim;
                                    if (mAddToBackStack) {
                                        old.mBackStacknesting += 1;
                                        if (FragmentManagerImpl.DEBUG) {
                                            Log.v(TAG,"Bump nesting of "
                                                    + old + " to " + old.mBackStacknesting);
                                        }
                                    }
                                    mManager.removeFragment(old,mTransition,mTransitionStyle);
                                }
                            }
                        }
                    }

这是FragmentManager.java的片段:

public void removeFragment(Fragment fragment,int transition,int transitionStyle) {
        if (DEBUG) Log.v(TAG,"remove: " + fragment + " nesting=" + fragment.mBackStacknesting);
        final boolean inactive = !fragment.isInBackStack();
        if (!fragment.mDetached || inactive) {
            if (false) {
                // Would be nice to catch a bad remove here,but we need
                // time to test this to make sure we aren't crashes cases
                // where it is not a problem.
                if (!mAdded.contains(fragment)) {
                    throw new IllegalStateException("Fragment not added: " + fragment);
                }
            }
            **if (mAdded != null) {
                mAdded.remove(fragment);
            }**
            if (fragment.mHasMenu && fragment.mMenuVisible) {
                mNeedMenuInvalidate = true;
            }
            fragment.mAdded = false;
            fragment.mRemoving = true;
            movetoState(fragment,inactive ? Fragment.INITIALIZING : Fragment.CREATED,transition,transitionStyle,false);
        }
    }

正如您所看到的,removeFragment方法从mAdded中删除一个frament,但是在run()方法之后,i索引没有被修改,它从它离开的地方重新启动,这样就会丢失一些元素……

解决方法

使用linearlayout作为容器无法实现此方案.

如果您尝试将此片段用作linearlayout中的容器,则可以实现此目的.请参阅此链接以获得进一步说明

Android – fragment .replace() doesn’t replace content – puts it on top

否则使用以下代码进行按钮单击操作,

Button button = (Button) findViewById(R.id.button);
    button.setonClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            FirstFragment fragment = new FirstFragment();
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();

            fragmentTransaction.add(R.id.container,fragment).addToBackStack(null);
            fragmentTransaction.commit();
        }
    });

    Button button2 = (Button) findViewById(R.id.button2);
    button2.setonClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            SecondFragment fragment = new SecondFragment();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            for(int i=0; i < getSupportFragmentManager().getBackStackEntryCount(); i++)
                getSupportFragmentManager().popBackStack();
            fragmentTransaction.replace(R.id.container,fragment);
            fragmentTransaction.commit();
        }
    });

希望这会对你有所帮助..谢谢

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...