Android NavigationView 片段状态

Android NavigationView Fragment State

我正在使用新的 NavigationView 来显示带有 Android 设计支持库的导航菜单。我还在 DrawerLayout 中使用 FrameLayout 来替换其中的片段。

当我在片段之间切换时出现问题。我的意思是,当我使用 NavigationView 单击另一个片段并再次返回到第一个片段时,视图只是 "cleaned"(f.e。ViewPagers 选项卡中的内容刚刚消失)。我不知道如何 "refresh" FrameLayout 或者我是否必须重用片段而不是使用 transaction.replace().

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <FrameLayout
            android:id="@+id/content_frame"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="?attr/actionBarSize" />
        <include layout="@layout/toolbar" />
    </RelativeLayout>
    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/drawer_header"
        app:menu="@menu/menu_drawer" />
</android.support.v4.widget.DrawerLayout>

我也是用这个方法在FrameLayout中的fragment之间切换。

private void displayFragment(int position) {
    Fragment fragment = null;
    String title = "";

    switch (position) {
        case 0:
            fragment = new FragmentA();
            title = getString(R.string.fragment_a);
            break;
        case 1:
            fragment = new FragmentB();
            title = getString(R.string.fragment_b);
            break;
        case 2:
            fragment = new FragmentC();
            title = getString(R.string.fragment_c);
            break;

        default:
            fragment = new HomeFragment();
            title = getString(R.string.app_name);
            break;
    }

    if (fragment != null) {
        fragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.content_frame, fragment);
        transaction.commit();

        drawerLayout.closeDrawers();
        setTitle(title);
    } else {
        Log.w(TAG, "Error creating fragment");
    }
}

谢谢!!

您可能需要在替换片段时尝试此操作..

transaction.replace(R.id.content_frame, fragment).addToBackStack("Any_String");

试试这个

     NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
            if (navigationView != null) {
                setupDrawerContent(navigationView);
            }


     private void setupDrawerContent(NavigationView navigationView) {
            navigationView.setNavigationItemSelectedListener(
                    new NavigationView.OnNavigationItemSelectedListener() {
                @Override
                public boolean onNavigationItemSelected(MenuItem menuItem) {
                    Fragment fragment = null;
                    switch (menuItem.getItemId()) {
                        case R.id.nav_home:
                            Log.i("TAG","HOME");
                            fragment = new CheeseListFragment();
                            break;
                        case R.id.nav_messages:
                            fragment = new MessageFragment();
                            break;
                        case R.id.nav_friends:
                            fragment = new FriendsFragment();
                            break;
                        case R.id.nav_discussion:
                             fragment = new DiscussionFragment();
                            break;

                    }

                    if (fragment != null) {
                        FragmentManager fragmentManager = getSupportFragmentManager();
                        fragmentManager.beginTransaction()
                                .replace(R.id.container, fragment).commit();

                    }
                        menuItem.setChecked(true);
                        mDrawerLayout.closeDrawers();
                        return true;

                }
            });
}

您可以通过这种方式打开片段检查在开关盒中选择了哪个菜单并相应地打开片段

不确定是否是同一个问题,这是我的观察和解决方案:

该应用程序有一个 NavigationView,其中有 5 个项目可以切换 5 个不同的片段(A、B、C、D、E)。最初它正确地切换了片段,但在切换了大约 5 次以上之后,一个片段就粘在了支架上 FrameLayout。所有交易均由 replace().commit().

调用
  • 选择A
  • 选B
    ...
    ...
  • 选择C
  • 选A(C就留在支架里,A在下面)
  • 选B(C在支架里,B在下面)

我发现由于屏幕方向改变,片段 A 实际上被片段 C 覆盖了。片段事务已提交,但片段 C 不知何故没有被替换。 我什至尝试使用 getSupportFragmentManager().findFragmentByTag() 来定位前一个片段。什么都没用。

所以对于解决方案,我不确定它是否合法但有效: ```

<android.support.design.widget.CoordinatorLayout
    android:id="@+id/rootLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:theme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_collapseMode="pin"
            app:layout_scrollFlags="enterAlways"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

        </android.support.v7.widget.Toolbar>

    </android.support.design.widget.AppBarLayout>


    <FrameLayout
        android:id="@+id/a_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <FrameLayout
        android:id="@+id/b_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <FrameLayout
        android:id="@+id/c_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <FrameLayout
        android:id="@+id/d_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <FrameLayout
        android:id="@+id/e_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>

<android.support.design.widget.NavigationView
    android:id="@+id/navigation"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    app:itemIconTint="#333"
    app:itemTextColor="#333"
    app:menu="@menu/navigation_drawer_items" />

```

如您所见,每个片段有 5 个 FrameLayout 个容器。当导航项选择其中一个容器设置为 VISIBLE 时,其他容器设置为 GONE。并且比片段交易工作得更顺畅。希望能给你一些想法。

--编辑 有人说使用 attach/detach 而不是替换。

我试试看。如果你找到了什么,请告诉我。

我认为这个解决方案应该对我有用。 在你的 activity 中进行以下更改......并且不要忘记覆盖你的 activity 中的 onbackpressed 按钮......它会在你的片段管理器中加载片段并在按下按钮时将其返回是任何...否则将用户发送到主屏幕(因为它可以由您自定义)

fragmentManager = getSupportFragmentManager();
    ChatWithUs myFragment0 = new ChatWithUs();
    FragmentTransaction ft = fragmentManager.beginTransaction();
    ft.replace(R.id.frameholder, myFragment0);
    ft.addToBackStack("chat_fragment");
    ft.commit();
    Log.i(MainActivity.TAG, "this is create method last line");

@Override
public void onBackPressed() {
    fragmentManager = getSupportFragmentManager();
    int backCount = fragmentManager.getBackStackEntryCount();
    //Log.i(MainActivity.TAG, String.valueOf(backCount));
    if((backCount > 1)){
        //Log.i(MainActivity.TAG, String.valueOf(backCount)) ;
        //Log.i(MainActivity.TAG, "im here") ;
        fragmentManager.popBackStack();
        Log.i(MainActivity.TAG, String.valueOf(fragmentManager.getBackStackEntryCount()));
    }
    else{
        //super.onBackPressed();
        //Log.i(MainActivity.TAG, String.valueOf(fragmentManager.getBackStackEntryCount())) ;
        Intent a = new Intent(Intent.ACTION_MAIN);
        a.addCategory(Intent.CATEGORY_HOME);
        a.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(a);
    }

}`

基于此 answer,解决方案是在包含其他片段(如 ViewPagers 选项卡)的片段中使用 getChildFragmentManager() 而不是 getSupportFragmentManager()