Android Fragment Manager изменяет поведение Navigation Drawer



Меня интересует следующее - когда диспетчер фрагментов удаляет и добавляет новый фрагмент - кнопка переключения навигации не реагирует на нажатия.

Подробности
1. В моем проекте есть панель навигации. Он был создан с помощью стандартного проекта студии Android (с навигационным ящиком).
2. Я использую фрагменты и диспетчер фрагментов для обработки содержимого экрана. Это происходит в onNavigationDrawerItemSelected().
3. Вот реализация onCreateOptionsMenu() в MainActivity:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    if (!mNavigationDrawerFragment.isDrawerOpen()) {
        // Only show items in the action bar relevant to this screen
        // if the drawer is not showing. Otherwise, let the drawer
        // decide what to show in the action bar.
        getMenuInflater().inflate(R.menu.main_activity, menu);
        MenuItem item = menu.findItem(R.id.right_item);
        getSupportActionBar().setTitle(mTitle);
        return true;
    }
    return super.onCreateOptionsMenu(menu);
}

4. Когда я использую FragmentManager.replace() - все в порядке. Когда я использую remove (), а затем add (), кнопка переключения ящика навигации не реагирует на нажатия. Я все еще могу нажать на нее, но ящик в это время не открывается. Код в FragmentManager:

.beginTransaction()
.remove(fragmentManager.getFragments().get(0))
.commit();

.beginTransaction()
.add(container, replacingFragment)
.commit();

Примечание. Я не переопределяю никакие методы меню в классах фрагментов.
Может быть, я использую неправильный код для работы с фрагментами?

Причина, по которой я предпочел бы удалить/добавить вместо замены - когда пользователь выбирает элемент в Navigation Drawer, который использует один и тот же фрагмент - содержимое фрагмента должно быть обновлено; и replace() не делает этого для фрагментации.

Но мне очень странно, что операции в Диспетчере фрагментов портят кнопку переключения.

Подробнее. В этом случае onOptionsItemSelected() вызывается в MainActivity и не вызывается во фрагменте NavigationDrawerFragment.

Редактировать
стандартный xml-файл, созданный студией Android

    <!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <!-- As the main content view, the view below consumes the entire
         space available using match_parent in both dimensions. -->
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/bg1" />

    <!-- android:layout_gravity="start" tells DrawerLayout to treat
         this as a sliding drawer on the left side for left-to-right
         languages and on the right side for right-to-left languages.
         If you're not building against API 17 or higher, use
         android:layout_gravity="left" instead. -->
    <!-- The drawer is given a fixed width in dp and extends the full height of
         the container. -->
    <fragment
        android:id="@+id/navigation_drawer"
        android:layout_width="@dimen/navigation_drawer_width"
        android:layout_height="match_parent"
        android:layout_gravity="start|left"
        android:name="com.datingappanrdoid.NavigationDrawerFragment"
        tools:layout="@layout/fragment_navigation_drawer" >
    </fragment>
</android.support.v4.widget.DrawerLayout>

Шаги для воспроизведения странного поведения:
1. В студии Android создайте новый проект - выберите «Проект с навигационным ящиком».
2. Измените метод onNavigationDrawerItemSelected с replace() на remove() и add(). Вот что я имею в виду:

 @Override
    public void onNavigationDrawerItemSelected(int position) {
        // update the main content by replacing fragments
        FragmentManager fragmentManager = getSupportFragmentManager();
//        fragmentManager.beginTransaction()
//                .replace(R.id.container, PlaceholderFragment.newInstance(position + 1))
//                .commit();

        if (tempFragment != null)
            tempFragment.setHasOptionsMenu(false);
        fragmentManager.beginTransaction()
                .remove(fragmentManager.getFragments().get(0))
                .commit();

        tempFragment = PlaceholderFragment.newInstance(position + 1);
        tempFragment.setHasOptionsMenu(true);

        fragmentManager.beginTransaction()
                .add(R.id.container, tempFragment)
                .commit();
    }

Я также добавил использование hasOptionsMenu, как было предложено в комментариях.
3. Готово - теперь кнопка переключения навигации не работает по тапу (но она все еще нажата).

До сих пор нет понимания, почему это происходит.


person Goltsev Eugene    schedule 23.04.2015    source источник
comment
Вы можете показать нам свой xml-файл? тот, из действия, в котором у вас определен навигационный ящик   -  person xanexpt    schedule 23.04.2015
comment
добавлен xml, но он стандартный   -  person Goltsev Eugene    schedule 23.04.2015
comment
да, я обычно не использую фрагмент в навигационном ящике, я просто использую обычный макет (например, прокрутку), никогда не сталкивался с этой проблемой   -  person xanexpt    schedule 23.04.2015


Ответы (1)


Когда вы вызываете add() или remove(), новый фрагмент добавляется/удаляется. Если мы хотим дать navigation drawer options этому фрагменту, нам нужно вызвать setHasOptionsMenu(boolean value) из кода

мы будем вызывать setHasOptionsMenu(true) после add() и будем вызывать setHasOptionsMenu(false) до remove()

Это решит вашу проблему

person Kushal    schedule 23.04.2015
comment
Может я что-то не так делаю, но не работает. Чуть позже выложу куда-нибудь тестовый проект для подтверждения. - person Goltsev Eugene; 24.04.2015
comment
Добавил STR к первоначальному ответу, результата нет. - person Goltsev Eugene; 27.04.2015