与 DrawerLayout/NavigationView 重叠的片段

Fragments overlapping with DrawerLayout/NavigationView

使用 DrawerLayoutNavigationViewFrameLayout 我想切换 Fragment。效果很好。 但是,如果我切换得太快,那么 Fragment 会重叠...

好像executePendingTransactions()不行

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <include layout="@layout/toolbar" />

        <FrameLayout
            android:id="@+id/frameLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </LinearLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/navigationView"
        android:layout_width="@240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@color/transparent"
        android:dividerHeight="0dp"
        app:menu="@menu/navigationdrawer" />

</android.support.v4.widget.DrawerLayout>

如果我切换 Fragments(太)快(手动或通过代码在我的 Nexus 5 上延迟 750 毫秒),我会让两个 Fragments 重叠,第二个 Fragment 启用了触摸功能,但第一个 Fragment 在顶部...

第一个 Fragment 包含 ImageViewTextView。第二个 Fragment 包含一个 TabLayout 和一个 ViewPager(如果这对我今天的问题有帮助的话)。是的,我正在使用 AppCompat 22.2.0 和 Design 22.2.0 库。

如果我为两者设置背景颜色,那么我只能看到第一个 Fragment,并且它永远不会改变。

我尝试了popBackStackImmediate()executePendingTransactions()remove(fragment)android:fitsSystemWindows="true"Android: fragments overlapping issue、延迟和其他方法,但都没有成功。

@Override
protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // ...

    mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(final MenuItem menuItem) {
            navigationDrawer(menuItem.getItemId());
            return true;
        }
    });

    if (savedInstanceState == null) {
        final MenuItem menuItem = mNavigationView.getMenu().getItem(0);
        if (menuItem != null) {
            navigationDrawer(menuItem.getItemId());
        }
    }
}

private void navigationDrawer(final int itemId) {
    final Fragment fragment = getFragment(itemId);
    getSupportFragmentManager().beginTrasaction()
        .replace(R.id.frameLayout, fragment)
        .addToBackStack(null)
        .commit();
    mNavigationView.getMenu().findItem(itemId).setChecked(true);
    mDrawerLayout.closeDrawer(mNavigationView);
    supportInvalidateOptionsMenu();
}

@Override
public boolean onOptionsItemSelected(final MenuItem item) {
    switch (item.getItemId()) {
        case R.id.menu_first:
        case R.id.menu_second:
        case R.id.menu_third:
            navigationDrawer(item.getItemId());
            return true;
    }
    return super.onOptionsItemSelected(item);
}

编辑

在我的 onCreate() 中,我是这样做的:

if (savedInstanceState == null) {
    final MenuItem menuItem = mNavigationView.getMenu().getItem(0);
    if (menuItem != null) {
        navigationDrawer(menuItem.getItemId());
    }
}

事实证明打电话太快了。删除此代码解决了我的问题(暂时,见下文)。

我仍然不知道为什么executePendingTransactions()没有阻止这种奇怪的问题...

编辑 2

我考虑保留一个 boolean(init 为 false)以跟踪 Fragment 交易何时发生。我在 navigationDrawer() 中将其设置为 true,在 Fragment.onResume() 中将其设置为 false。还是不行...

所以:我的 MainFragment 仍然有问题,它使用 Picasso 加载图像并太快(800 毫秒)切换到另一个 Fragment:它们仍然重叠...

你可以试试这个... 它会延迟您的频繁点击 ...

private final Handler mDrawerActionHandler = new Handler();
private static final long DRAWER_CLOSE_DELAY_MS = 250;

mDrawerActionHandler.postDelayed(new Runnable() {
      @Override
      public void run() {
        // your navigation code goes here
      }
}, DRAWER_CLOSE_DELAY_MS);

在我的 onCreate() 中,我是这样做的:

    if (savedInstanceState == null) {
        final MenuItem menuItem = mNavigationView.getMenu().getItem(0);
        if (menuItem != null) {
            navigationDrawer(menuItem.getItemId());
        }
    }

事实证明打电话太快了。 删除此代码解决了我的问题。

我还是不知道:

why executePendingTransactions() did not prevent such weird issue...

编辑

我的 MainFragment 仍然有问题,它使用 Picasso 加载图像并且切换到另一个图像的速度太快(800 毫秒):它们仍然重叠...

编辑 2

所以我现在使用一个布尔值来标记我的 Activity 是否正在转换 Fragment 或没有,切换之间的最小计时器为 1 秒。

在我的 FragmentonViewCreated():

if (view != null) {
    view.post(new Runnable() {
        @Override
        public void run() {
            // Activity might be null
            getActivity().setTransitioning(false);
        }
    });
}

在我的 navigationDrawer() 中:

if (isTransitioning()) {
    // Switching Fragments too fast
    return false;
}