2013-12-23 2 views
19

У меня есть три фрагмента F1 F2 F3 F4, все из которых доступны из боковой панели.Принесите фрагмент к фронту (нет отдыха фрагмента)

все четыре могут быть вызваны в любое время и в любом порядке,

Теперь я хочу, если F1 уже нажата (создается), то никогда не создать F1, но только вернуть фрагмент F1, чтобы перед использованием менеджер фрагментов. То же самое для всех других фрагментов

До сих пор я попробовал это для каждого фрагмента в моем контейнере (ФРАГМЕНТ АКТИВНОСТЬ)

if (fragmentManager.findFragmentByTag("apps")==null) { 
FragmentManager fragmentManager = getSupportFragmentManager(); 
FragmentTransaction transaction = fragmentManager.beginTransaction(); 
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); 

Fragment newFragment = new CategoriesFragment(); 
transaction.replace(R.id.content_frame, newFragment, "apps"); 
transaction.addToBackStack("apps"); 
transaction.commit(); 
} else{ 

} 

If часть обеспечивает меня NO фрагмент не воссоздан (если его создал уже) еще раз , но то, что я должен написать в else части так, что уже созданный фрагмент может быть доведен до фронта в иерархии видов

Пожалуйста, помогите, я застрял в этом е или 2 дня.

+0

Сколько видов фрагментов у вас есть? – Triode

+0

@Rajesh CP ВСЕ фрагменты расширены от класса FRAGMENT только никакие другие типы фрагментов –

+0

Помог ли мой ответ вообще? –

ответ

5

Получить фрагмент по тэгу и заменить его в контейнере,

else{ 
Fragment existingFragment = (CategoriesFragment)fragmentManager.findFragmentByTag("apps"); 
transaction.replace(R.id.content_frame,existingFragment, "apps"); 
transaction.addToBackStack("apps"); 
transaction.commit(); 
} 

UPDATE: вы можете использовать скрыть и показать фрагмент, чтобы избежать recreation.instead использования «transaction.replace()»

fragmentTransaction.hide(<oldFragment>); 
fragmentTransaction.show(<newFragment>); 
+0

Я проверил код, который вы предоставили, но он воссоздает фрагмент поверх иерархии представлений, вместо того, чтобы возвращать ранее созданный фрагмент –

+0

, пожалуйста, обратитесь к моему обновленному ответу. – nikvs

+0

это все еще не полезно, потому что когда я пытаюсь показать ранее созданный поток, тогда код не имеет никакого эффекта. 'Fragment existingFragment = (CategoriesFragment) fragmentManager.findFragmentByTag (« apps »); \t \t \t \t transaction.show (existingFragment); ' –

2
  1. Используйте простой ArrayList<Fragment> для фрагментов, и добавить их в порядке, так что вы знаете, получить (0) получит F1, получим (1) получает F2 и т.д.

  2. Создайте фрагменты как одиночные. В каждом фрагменте добавить статическое поле и метод:

    private static Fragment mMyInstance = null; 
    
    public static Fragment newInstance() { 
        if (mMyInstance == null) { 
         mMyInstance = new F1(); 
        } 
        return mMyInstance; 
    } 
    
  3. Создание фрагментов с помощью статического метода и добавить их в ArrayList.

  4. В каждом фрагменте добавьте команду setRetainInstance(true); в метод onCreate().

Теперь, когда вы добавляете фрагмент с FragmentManager, onCreate() будет называться только первый раз, но onCreateView() будет вызываться каждый раз. Вы хотите раздуть представление и подключить виджеты каждый раз, только если ваша активность была восстановлена ​​из-за изменения конфигурации. Но вы можете проверить что-то, что вы добавите, чтобы увидеть, было ли это в первый раз или нет, и сбросить виджеты до их предыдущего состояния, если нет. Таким образом, вам понадобятся переменные-члены в ваших фрагментах, чтобы отслеживать их состояние. Переопределите onStop(), чтобы сохранить состояние и повторно применить его в onCreateView() после подключения виджетов.

Затем, когда нажата кнопка боковой панели, вы получаете фрагмент, соответствующий этой кнопке, удалите предыдущий фрагмент и добавьте текущий с помощью FragmentManager (или просто используйте команду replace() вместо remove()/Добавить()).

+2

Сохранение списка фрагментов самостоятельно считается плохой практикой. Зачем? Учтите, что пользователь меняет ориентацию, ui будет уничтожен и т. Д. У вас все еще есть ссылки на несуществующие фрагменты, что приводит к неприятным утечкам памяти, а в некоторых случаях к сбоям приложения. PS: Если вы используете supportFragmentManager, вы можете легко получить к ним доступ с помощью SupportFragmentManager..getFragments() и выяснить, существует ли нужный фрагмент, или вам нужно создать новый. Вы также избегаете утечек памяти. Я бы предложил использовать то, что было предназначено для использования для операций с фрагментами;) – vanomart

10

Я бы поставил этот код в классе деятельности, которые должны быть FrameLayout с идентификатором R.id.fragment_container.

private Fragment1 F1; 
private Fragment2 F2; 
private Fragment3 F3; 
private Fragment4 F4;  

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    F1 = new Fragment1(); 
    getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, F1).commit(); 
    F2 = new Fragment2(); 
    getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, F2).commit(); 
    F3 = new Fragment3(); 
    getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, F3).commit(); 
    F4 = new Fragment4(); 
    getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, F4).commit(); 

    //if needed show F1 
    getSupportFragmentManager().beginTransaction().show(F1).commit(); 

} 

И добавим для нажатия кнопки:

public void onBtnClick(View view){ 
    if(mShowF1){ 
     getSupportFragmentManager().beginTransaction().show(F1).commit(); 
     getSupportFragmentManager().beginTransaction().hide(F2).commit(); 
     getSupportFragmentManager().beginTransaction().hide(F3).commit(); 
     getSupportFragmentManager().beginTransaction().hide(F4).commit(); 
    } 
    //... 
} 

На кнопку мыши (ы) вы можете показать, что фрагмент, который вы хотите и скрыть другие.

Примечание (@ developer1011): Для использования после деятельности, кроме состояния вызова commitAllowingStateLoss(). Используйте с осторожностью, потому что фрагмент не восстанавливается с восстановлением активности.

ПРИМЕЧАНИЕ: Основная функция должна реализовать OnFragmentInteractionListener для каждого фрагмента.

public class MainActivity extends FragmentActivity implements Fragment1.OnFragmentInteractionListener, Fragment2.OnFragmentInteractionListener, Fragment3.OnFragmentInteractionListener, Fragment4.OnFragmentInteractionListener {//.. 

    @Override 
    public void onFragmentInteraction(Uri uri) { 
     // 
    } 
} 
+0

Вызов в результате совершения приводит к появлению java.lang.IllegalStateException: commit уже вызвал :( '' 'Из документов разработчика: - транзакция может быть совершена только с помощью этого метода до его сохранения, сохраняя его состояние.Если совершить попытку после этой точки, будет выбрано исключение. '' ' – developer1011

+0

@ developer1011: вопрос не указывает, если состояние должно быть восстановлено при восстановлении активности. Из документов: commitAllowingStateLoss () Как commit(), но позволяет совершить фиксацию после сохранения состояния активности. ПРИМЕЧАНИЕ: используйте с осторожностью! – Solata

0

Если вы используете Фрагмент поддержки, то этот статический метод выполняет задание.

/** 
* Takes a Fragment TAG and tries to find the fragment in the manager if it exists and bring it to front. 
* if not, will return false; 
* @param manager 
* @param tag 
*/ 
public static boolean resurfaceFragment(FragmentManager manager, String tag){ 
    Fragment fragment = manager.findFragmentByTag(tag); 
    FragmentTransaction transaction = manager.beginTransaction(); 
    if (fragment!=null){ 
     for (int i = 0; i < manager.getFragments().size(); i++) { 
      Fragment f = manager.getFragments().get(i); 
      transaction.hide(f); 

     } 
     transaction.show(fragment).commit(); 
     return true; 
    } 

    return false; 
} 
+0

fragmentManager.getFragments() дает предупреждение, что он может быть вызван только из той же группы библиотек –

0

Если вы просто пытаетесь добавить Fragment без необходимости беспокоиться о воссоздании его, то я думаю, что этот метод, который я написал, чтобы добавить Fragment будет делать вам работу.

public static void attachFragment (int fragmentHolderLayoutId, Fragment fragment, Context context, String tag) { 


    FragmentManager manager = ((AppCompatActivity) context).getSupportFragmentManager(); 
    manager.findFragmentByTag (tag); 
    FragmentTransaction ft = manager.beginTransaction(); 

    if (manager.findFragmentByTag (tag) == null) { // No fragment in backStack with same tag.. 
     ft.add (fragmentHolderLayoutId, fragment, tag); 
     ft.addToBackStack (tag); 
     ft.commit(); 
    } 
    else { 
     ft.show (manager.findFragmentByTag (tag)).commit(); 
    } 
} 
Смежные вопросы