Android替换当前片段为另一个片段。

57

我刚开始学习HoneyComb的片段设计。我创建了两个片段。当我在左边的片段中点击一个按钮时,右边会创建一个新的片段。同时当我在右片段中点击一个按钮时(即下面代码中的DetialsFragment),应该用另一个片段来替换。

<?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="horizontal" >
    <fragment class="com.fragment.example.Titles"
        android:id="@+id/titles" android:layout_weight="1"
        android:layout_width="0px"
        android:layout_height="match_parent" />
    <FrameLayout android:id="@+id/details" android:layout_weight="1"
        android:layout_width="0px"
        android:layout_height="match_parent" />

</LinearLayout>

FragmentExample.java

public class FragmentExample extends Activity {
/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

Titles.java

public class Titles extends Fragment {
    public FragmentTransaction ft;
    @Override
    public View onCreateView(LayoutInflater inflater,
        ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.main1, null);
        Button button1 = (Button)v.findViewById(R.id.button1);
        button1.setText("santhosh");
        button1.setOnClickListener(new OnClickListener() {



            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                 DetailsFragment details = (DetailsFragment)
                            getFragmentManager().findFragmentById(R.id.details);
                    if (details == null || details.getShownIndex() != 1) {
                        // Make new fragment to show this selection.
                        details = DetailsFragment.newInstance(1);

                        // Execute a transaction, replacing any existing
                        // fragment with this one inside the frame.
                        ft
                                = getFragmentManager().beginTransaction();
                        ft.add(R.id.details, details, "detail");
                        ft.setTransition(
                                FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                        ft.commit();
                    }
            }

        });
        return v;
    }
}

DetailsFragment.java

public class DetailsFragment extends Fragment {
    /**
     * Create a new instance of DetailsFragment, initialized to
     * show the text at 'index'.
     */
    Titles title = new Titles();
    String[] titles = {"Title1", "Title2", "Title3", "Title4"};
    public static DetailsFragment newInstance(int index) {
        DetailsFragment f = new DetailsFragment();

        // Supply index input as an argument.
        Bundle args = new Bundle();
        args.putInt("index", index);
        f.setArguments(args);

        return f;
    }

    public int getShownIndex() {
        return getArguments().getInt("index", 0);
    }

    @Override
    public View onCreateView(LayoutInflater inflater,
        ViewGroup container, Bundle savedInstanceState) {
        if (container == null) {
            // Currently in a layout without a container, so no
            // reason to create our view.
            return null;
        }
        Button button = new Button(getActivity());
        button.setText("Next");
        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
            }
        });
        return button;
    }
}
7个回答

106

如果您的按钮正在显示并且点击事件已被触发,您可以在单击事件中调用以下内容:

final FragmentTransaction ft = getFragmentManager().beginTransaction(); 
ft.replace(R.id.details, new NewFragmentToReplace(), "NewFragmentTag"); 
ft.commit(); 

如果你想在点击返回时回到DetailsFragment,请确保将上述事务添加到后台堆栈中,即

ft.addToBackStack(null);

还有其他需要考虑的吗?或者有些人建议您的活动获取按钮的点击事件,并负责在详细信息窗格中替换片段。


5
提供片段标签是可选的。您可以使用 ft.replace(R.id.details, new NewFragmentToReplace()); 来替换新片段。 - Aniket Thakur
还有不要忘记 getFragmentManager().executePendingTransactions(); - Aniket Thakur
9
旧的按钮仍然停留在上一个片段中,这些旧按钮仍然出现在新片段的顶部。 - Santanu
1
@Santanu 发生这种情况的原因是视图的背景颜色没有设置。将其设置为白色,然后它就可以工作了。 - Sambhav Khandelwal
@Santanu请检查R.id.details是否是父片段容器的ID,而不是当前片段的ID。这对我解决了这个问题。 - Ben
@SambhavKhandelwal,你能解释一下这是如何解决问题的吗?我需要更改其他活动共享的工具栏以拥有白色背景,并想了解此修复背后的逻辑。 - Gil Ong

6

最新内容

好的,这是一个非常旧的问题,并且那个时候有很好的答案。但是自那时以来有很多变化。

现在,如果您正在使用Kotlin并且想要更改fragment,则可以执行以下操作(2020年):

  1. 将Fragments的Kotlin扩展添加到您的项目中。

在您的应用程序级别的 build.gradle文件中添加以下内容:

dependencies {
    def fragment_version = "1.2.5"

    // Kotlin
    implementation "androidx.fragment:fragment-ktx:$fragment_version"
    // Testing Fragments in Isolation
    debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
}
  1. 简单的代码来替换片段,

在你的活动中。

supportFragmentManager.commit {
    replace(R.id.frame_layout, YourFragment.newInstance(), "Your_TAG")
    addToBackStack(null)
}

参考资料

查看 Fragment 扩展的最新版本

更多关于 Fragments 的信息


1
截至今天,这适用于Kotlin,只需从此处https://developer.android.com/jetpack/androidx/releases/fragment替换版本为当前版本即可。 - Neo Wakeup

2
您可以尝试以下代码。这是一种非常简单的方法,用于从旧片段推送新片段。
private int mContainerId;
private FragmentTransaction fragmentTransaction;
private FragmentManager fragmentManager;
private final static String TAG = "DashBoardActivity";

public void replaceFragment(Fragment fragment, String TAG) {

    try {
        fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(mContainerId, fragment, tag);
        fragmentTransaction.addToBackStack(tag);
        fragmentTransaction.commitAllowingStateLoss();

    } catch (Exception e) {
        // TODO: handle exception
    }

}

2
什么是mcontainerid? - Ayyoub
@Ayoub 是您的视图 ID。例如,在 Java 中,使用 linearLayout.getId()。 - marlonpya

2
如果您有现有片段的句柄,只需用该片段的ID替换即可。
在Kotlin中的示例:
fun aTestFuction() {
   val existingFragment = MyExistingFragment() //Get it from somewhere, this is a dirty example
   val newFragment = MyNewFragment()
   replaceFragment(existingFragment, newFragment, "myTag")
}

fun replaceFragment(existing: Fragment, new: Fragment, tag: String? = null) {
    supportFragmentManager.beginTransaction().replace(existing.id, new, tag).commit()
}

现有的片段 = supportFragmentManager.fragments.first() - Michael N

2

在你的代码中使用android.support.v4.app来处理FragmentManager和FragmentTransaction,这对我很有效。

DetailsFragment detailsFragment = new DetailsFragment();
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.details,detailsFragment);
fragmentTransaction.commit();

1

更新的答案(适用于重叠问题)

@aniket-thakur(https://stackoverflow.com/users/2396539/aniket-thakur) 给出了正确的答案。感谢您!

但是,getFragmentManager() 已经被弃用,所以以下代码对我有效。

final FragmentTransaction ft = getParentFragmentManager().beginTransaction();
                ft.replace(R.id.nav_host_fragment, new GalleryFragment(), "NewFragmentTag");
                ft.addToBackStack(null);
                ft.commit();

0

如何使用Fragment进行替换非常简单。

DataFromDb changeActivity = new DataFromDb();
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.replace(R.id.changeFrg, changeActivity);
    transaction.commit();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接