Переключение между фрагментами в одном действии

Я хочу создать Activity, который показывает своего рода меню, через которое может пройти пользователь. Щелчком по элементу отображается новый экран, предоставляющий пользователю больше возможностей (наподобие мастера).

Я хотел реализовать это с помощью Fragments, но у меня это не работает.
Сейчас у меня есть:

main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:id="@+id/main_fragmentcontainer" >

    <fragment
        android:id="@+id/mainmenufragment"
        android:name="com.myapp.MainMenuFragment"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

    <fragment
        android:id="@+id/secondmenufragment"
        android:name="com.myapp.SecondMenuFragment"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</LinearLayout>

MainMenuFragment с OnClickListener:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.mainmenu, container, false);

    setupButton(view);
    return view;
}

/* Button setup code omitted */

@Override
public void onClick(View v) {
    SherlockFragment secondRunMenuFragment = (SherlockFragment) getSherlockActivity().getSupportFragmentManager().findFragmentById(R.id.secondmenufragment);
    FragmentTransaction transaction = getSherlockActivity().getSupportFragmentManager().beginTransaction();

    transaction.replace(android.R.id.content, secondMenuFragment); //also crashes with R.id.main_fragmentcontainer
    transaction.addToBackStack(null);
    transaction.commit();
}

Теперь, когда я нажимаю кнопку, приложение вылетает с этим логарифмом:

06-27 01:45:26.309: E/AndroidRuntime(8747): java.lang.IllegalStateException: невозможно изменить идентификатор контейнера фрагмента SecondMenuFragment{405e2a70 #1 id=0x7f060029}: был 2131099689, теперь 2131099687
06-27 01:45:26.309: E/AndroidRuntime(8747): на android.support.v4.app.BackStackRecord.doAddOp(Неизвестный источник)
06–27 01:45:26.309: E/AndroidRuntime(8747): на android .support.v4.app.BackStackRecord.replace(неизвестный источник)
06-27 01:45:26.309: E/AndroidRuntime(8747): в android.support.v4.app.BackStackRecord.replace(неизвестный источник)< br> 06-27 01:45:26.309: E/AndroidRuntime(8747): в com.myapp.MainMenuFragment$MyButtonOnClickListener.onClick(MainMenuFragment.java:52)

Что я делаю неправильно?


person nhaarman    schedule 26.06.2012    source источник
comment
Здесь есть аналогичный вопрос   -  person adneal    schedule 27.06.2012
comment
Если вы пытаетесь создать мастер, для чего нужен второй <fragment>?   -  person CommonsWare    schedule 27.06.2012
comment
Я действительно видел эти ссылки, но я не знаю, как их применить в моем случае.   -  person nhaarman    schedule 27.06.2012
comment
@CommonsWare Первый Fragment показывает первое меню с кнопками 1, 2 и 3. Второй Fragment показывает второе меню с кнопками 1.1, 1.2 и 1.3. В планах добавить третью Fragment с кнопками 2.1, 2.2 и 2.3. Или я подхожу ко всему этому неправильно?   -  person nhaarman    schedule 27.06.2012


Ответы (3)


Лично у меня не было бы <fragment> элементов.

Шаг № 1: Заполните макет активности <FrameLayout> для переменной части мастера, а также различные кнопки.

Шаг № 2: В onCreate() действия запустите FragmentTransaction, чтобы загрузить первую страницу мастера в FrameLayout.

Шаг № 3: При нажатии кнопки «Далее» запустите FragmentTransaction, чтобы заменить содержимое FrameLayout следующей страницей мастера.

Шаг № 4: Добавьте соответствующие интеллектуальные функции для отключения кнопок, когда они непригодны для использования (например, на первой странице мастера).

Кроме того, вам следует подумать о том, как кнопка НАЗАД должна работать в сочетании с любой экранной кнопкой «назад» в мастере. Если вы хотите, чтобы они оба вели себя одинаково, вам нужно будет добавить каждую транзакцию в задний стек и вытолкнуть материал из заднего стека, когда вы обрабатываете кнопку «назад».

Когда-нибудь, если меня никто не опередит, я попытаюсь создать пример мастера на основе фрагментов или, возможно, повторно используемый компонент.

person CommonsWare    schedule 26.06.2012
comment
Я не уверен, правильно ли я вас понял, но у меня как-то получилось. Я поместил пустой <FrameLayout> в свой файл макета активности. Затем в onCreate() действия я вызвал FragmentTransaction.add(), чтобы добавить new MainMenuFragment() к R.id.main_fragmentcontainer, идентификатору <FrameLayout>. В MainMenuFragment onClick() я создаю new SecondMenuFragment() и добавляю его таким же образом, снова к R.id.main_fragmentcontainer. Это по крайней мере работает. Я особенно запутался в шаге 1 плюс ваши различные кнопки. Что ты имеешь в виду? А нельзя ли просто использовать LinearLayout? - person nhaarman; 27.06.2012
comment
@Niek: Что ты имеешь в виду? -- обычно в интерфейсе мастера есть кнопки «Назад» и «Далее». Нет причин размещать их во фрагментах, поскольку они остаются неизменными на всех этапах мастера, поэтому я полагаю, что вы поместите их непосредственно в действие. А нельзя ли просто использовать LinearLayout? -- за что? - person CommonsWare; 27.06.2012
comment
Ох уж эти кнопки, я думал ты имеешь в виду мои кнопки меню. И вы предложили FrameLayout на шаге 1, но я предполагаю, что это связано с наложением кнопок «Далее» и «Предыдущий». Спасибо за вашу помощь! - person nhaarman; 27.06.2012
comment
@Niek: FrameLayout был слотом для размещения фрагментов. FrameLayout часто используется для этого, так как я полагаю, что это довольно дешевый контейнер с точки зрения обработки. Пока он ведет себя так, как вы хотите, технически любой ViewGroup должен работать. - person CommonsWare; 27.06.2012

Я создаю этот основной макет:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="horizontal"
   tools:context="com.example.fragmentsexample.MainActivity" >

   <FrameLayout 
      android:id="@+id/contentFragment"
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:layout_weight="1" />

</LinearLayout>

И я пополнил в FrameActivity:

@Override
public void onCreate(Bundle savedInstanceState) {
  ...
  Fragment fragment = new Dashboard();
  FragmentManager fm = getSupportFragmentManager();
  FragmentTransaction transaction = fm.beginTransaction();
  transaction.replace(R.id.contentFragment, fragment);
  transaction.commit();
  ...
}

И я повторяю метод onClick с тем же кодом, изменяя фрагмент (панель инструментов для событий):

@Override
public void onClick.... {
  ...
  Fragment fragment = new Events();
  FragmentManager fm = getSupportFragmentManager();
  FragmentTransaction transaction = fm.beginTransaction();
  transaction.replace(R.id.contentFragment, fragment); //Container -> R.id.contentFragment
  transaction.commit();
  ...
}
person Josep Escobar    schedule 25.07.2013

Другой вариант — использовать Android-WizardPager от Романа Нурика.

Ключевая особенность:

  • Ветвление или способность шагов мастера влиять на доступность последующих шагов.
  • Предоставление пользователю возможности просмотра перед фиксацией
  • Предоставление пользователю свободной навигации между шагами мастера
  • Поддержка обязательных и необязательных шагов
  • Поддержка классов шагов (технически каждый шаг является экземпляром класса Java, поэтому в мастере может быть несколько экземпляров)

Подробнее здесь.

person LordRaydenMK    schedule 19.01.2015