Mostra il frammento nascosto in Android


98

Sto sviluppando un'applicazione che contiene 2 frammenti e voglio mostrare hide secondo le mie necessità. Il codice seguente ha un semplice esempio del mio problema. Questa semplice attività Fragment contiene 1 pulsante e un listfragment.

Questo semplice esempio funziona perfettamente. ma non sono soddisfatto di show hide fragment. Se rimuovi layout.setVisibility (View.GONE); dal codice poi ft.hide (f); non nasconderà il frammento. In realtà non stiamo nascondendo frammento, stiamo nascondendo contenitore.

La mia domanda è: è questo un modo per mostrare i frammenti nascosti? In caso contrario, spiega con un esempio testato Come nascondere e mostrare i frammenti perché molte persone stanno affrontando questo problema.

 public class MainActivity extends FragmentActivity implements OnClickListener {

        Fragment1 f;
        Button b;
        LinearLayout layout;
        Fragment myf;
        @Override
        public void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            b = (Button) findViewById(R.id.button1);
            layout = (LinearLayout) findViewById(R.id.ll);
            f = new Fragment1();
        }

        @Override
        public void onClick(View v) {

            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);

            if (f.isHidden()) {
                ft.show(f);
                layout.setVisibility(View.VISIBLE);
                b.setText("Hide");
            } else {
                ft.hide(f);
                b.setText("Show");
                layout.setVisibility(View.GONE);
            }
            ft.commit();
            // TODO Auto-generated method stub
        }

Perché è necessario impostare la visibilità del container? Dovrebbe funzionare senza impostare la visibilità.
Andrii Chernenko

Esattamente dovrebbe funzionare senza visibilità del contenitore ma non funziona. Per favore, per favore condividi con me un semplice esempio di lavoro. Allora saprei dove mi manca.
abidkhan303

1
La mia ipotesi è che tu stia cercando di mostrare / nascondere istanze diverse di frammento ogni volta. Quando aggiungi il tuo frammento (non vedo questo pezzo di codice, a proposito) aggiungilo con il tag e poi recuperalo con quel tag (invece di provare a memorizzare il riferimento ad esso). Potrebbe essere quello che ti stai perdendo.
Andrii Chernenko

Risposte:


158

Non scherzare con i flag di visibilità del contenitore: FragmentTransaction.hide / show lo fa internamente per te.

Quindi il modo corretto per farlo è:

FragmentManager fm = getFragmentManager();
fm.beginTransaction()
          .setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
          .show(somefrag)
          .commit();

OPPURE se stai usando android.support.v4.app.Fragment

 FragmentManager fm = getSupportFragmentManager();
 fm.beginTransaction()
          .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out)
          .show(somefrag)
          .commit();

5
Perché sconsiglia di scherzare direttamente con le bandiere? (Non sto contestando la tua raccomandazione, sto solo cercando di capirla.)
Ellen Spertus

1
Sì, l'ho letto nel tuo messaggio originale. Speravo potessi aggiungere una giustificazione per l'overhead extra. Nel frattempo, ne ho scoperti alcuni, come l'opzione di aggiungere allo stack posteriore.
Ellen Spertus

2
È soggetto a errori perché puoi cambiare i tuoi flag a API di basso livello e api di alto livello e se non stai attento (cioè i flag non sono sincronizzati) potresti essere a caccia di bug strani. Questo è il motivo per cui si consiglia di utilizzare il gestore dei frammenti per nascondere e mostrare i frammenti.
numan salati

@numansalati Ciao, esiste una versione compatibile (dalla libreria di supporto) di android.R.animator.fade_in, e android.R.animator.fade_out?
Solace

1
Con il contenitore, puoi impostarlo su MOSTRA, NASCONDI o ANDATO. Non è disponibile alcuna opzione GONE quando si nasconde un frammento.
Stealth Rabbi

57

Inoltre, puoi fare in un frammento (ad esempio quando il recupero dei dati del server non è riuscito):

 getView().setVisibility(View.GONE);

11
Fragment è figlio di Object e non View, quindi non è possibile chiamare: fragment.setVisibility (View.INVISIBLE);
AndroidGeek

8
Arià sta suggerendo qualcosa di diverso, sta suggerendo di ottenere la vista da quel frammento e di impostarne la visibilità.
AlvaroSantisteban

10
Attenzione getView()può essere nullquando non è ancora inizializzato.
TWiStErRob

22

Ciao lo fai usando questo approccio, tutti i frammenti rimarranno nel contenitore una volta aggiunti inizialmente e poi stiamo semplicemente rivelando il frammento desiderato e nascondendo gli altri all'interno del contenitore.

// Within an activity
private FragmentA fragmentA;
private FragmentB fragmentB;
private FragmentC fragmentC;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (savedInstanceState == null) {
        fragmentA = FragmentA.newInstance("foo");
        fragmentB = FragmentB.newInstance("bar");
        fragmentC = FragmentC.newInstance("baz");
    }
}


// Replace the switch method
protected void displayFragmentA() {
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    if (fragmentA.isAdded()) { // if the fragment is already in container
        ft.show(fragmentA);
    } else { // fragment needs to be added to frame container
        ft.add(R.id.flContainer, fragmentA, "A");
    }
    // Hide fragment B
    if (fragmentB.isAdded()) { ft.hide(fragmentB); }
    // Hide fragment C
    if (fragmentC.isAdded()) { ft.hide(fragmentC); }
    // Commit changes
    ft.commit();
}

Per ulteriori informazioni, consulta https://github.com/codepath/android_guides/wiki/Creating-and-Using-Fragments . Spero di poter aiutare qualcuno. Anche se questa è una vecchia domanda.


1
quindi devi avere altri due metodi come displayFragmentB () e displayFragmentC ()?
temirbek

sì @temirbek puoi semplicemente seguire come è implementato il metodo displayFragmentA ().
mangu23

1
Se hai molti frammenti in un'attività (2 o più) e stai usando il metodo sopra, usa questo . Sarà più facile scrivere e leggere.
Maxime Claude

8
public void showHideFragment(final Fragment fragment){

    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.setCustomAnimations(android.R.animator.fade_in,
                    android.R.animator.fade_out);

    if (fragment.isHidden()) {
        ft.show(fragment);
        Log.d("hidden","Show");
    } else {
        ft.hide(fragment);
        Log.d("Shown","Hide");                        
    }

    ft.commit();
}

1
quello corretto è ft.setCustomAnimations (android.R.anim.fade_in, android.R.anim.fade_out);
Webserveis

8

Prova questo:

MapFragment mapFragment = (MapFragment)getFragmentManager().findFragmentById(R.id.mapview);
mapFragment.getView().setVisibility(View.GONE);

2

Dal mio codice, confrontando con la soluzione sopra, il modo più semplice è definire un layout che contiene il frammento, quindi puoi nascondere o mostrare il frammento controllando l'attributo di layout che è allineato con il modo di visualizzazione generale. In questo caso non è necessario alcun codice aggiuntivo e gli attributi di distribuzione aggiuntivi del frammento possono essere spostati nel layout esterno.

<LinearLayout style="@style/StHorizontalLinearView"
    >

    <fragment
        android:layout_width="match_parent"
        android:layout_height="390dp"
        android:layout_alignParentTop="true"
        />

</LinearLayout>

0

Questo ha funzionato per me

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        if(tag.equalsIgnoreCase("dashboard")){

            DashboardFragment dashboardFragment = (DashboardFragment)
                    fragmentManager.findFragmentByTag("dashboard");
            if(dashboardFragment!=null) ft.show(dashboardFragment);

            ShowcaseFragment showcaseFragment = (ShowcaseFragment)
                    fragmentManager.findFragmentByTag("showcase");
            if(showcaseFragment!=null) ft.hide(showcaseFragment);

        } else if(tag.equalsIgnoreCase("showcase")){
            DashboardFragment dashboardFragment = (DashboardFragment)
                    fragmentManager.findFragmentByTag("dashboard");
            if(dashboardFragment!=null) ft.hide(dashboardFragment);

            ShowcaseFragment showcaseFragment = (ShowcaseFragment)
                    fragmentManager.findFragmentByTag("showcase");
            if(showcaseFragment!=null) ft.show(showcaseFragment);
        }

        ft.commit();

0

le risposte qui sono corrette e mi è piaciuta @Jyo l'idea Whiff di mostrare e nascondere l'implementazione di un frammento tranne il modo in cui lo ha attualmente nasconderebbe il frammento alla prima esecuzione, quindi ho aggiunto una leggera modifica in quanto ho aggiunto isAdded check and show il frammento se non è già

public void showHideCardPreview(int id) {
    FragmentManager fm = getSupportFragmentManager();
    Bundle b = new Bundle();
    b.putInt(Constants.CARD, id);
    cardPreviewFragment.setArguments(b);
    FragmentTransaction ft = fm.beginTransaction()
        .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
    if (!cardPreviewFragment.isAdded()){
        ft.add(R.id.full_screen_container, cardPreviewFragment);
        ft.show(cardPreviewFragment);
    } else {
        if (cardPreviewFragment.isHidden()) {
            Log.d(TAG,"++++++++++++++++++++ show");
            ft.show(cardPreviewFragment);
        } else {
            Log.d(TAG,"++++++++++++++++++++ hide");
            ft.hide(cardPreviewFragment);
        }
    }

    ft.commit();
} 

0
final Fragment fragment1 = new fragment1();
final Fragment fragment2 = new fragment2();
final FragmentManager fm = getSupportFragmentManager();
Fragment active = fragment1;

In onCreate, dopo setContentView, ho nascosto due frammenti e li ho inviati al gestore dei frammenti, ma non ho nascosto il primo frammento che servirà da casa.

fm.beginTransaction().add(R.id.main_container, fragment2, "2").hide(fragment2).commit();
fm.beginTransaction().add(R.id.main_container,fragment1, "1").commit();
 @Override
    public void onClick(View v) {
        Fragment another = fragment1;
         if(active==fragment1){
          another = fragment2;
         }
            fm.beginTransaction().hide(active).show(another).commit();
            active = another;
}

Rif: https://medium.com/@oluwabukunmi.aluko/bottom-navigation-view-with-fragments-a074bfd08711


0

Potrei essere troppo tardi, ma potrebbe aiutare qualcuno in futuro.
Questa risposta è una modifica per mangu23 rispondere
ho aggiunto solo un ciclo for per evitare ripetizioni e per aggiungere facilmente più frammenti senza codice boilerplate.

Per prima cosa abbiamo bisogno di un elenco dei frammenti che dovrebbero essere visualizzati

public class MainActivity extends AppCompatActivity{
    //...
    List<Fragment> fragmentList = new ArrayList<>();
}

Quindi dobbiamo riempirlo con i nostri frammenti

@Override
protected void onCreate(Bundle savedInstanceState) {
    //...
    HomeFragment homeFragment = new HomeFragment();
    MessagesFragment messagesFragment = new MessagesFragment();
    UserFragment userFragment = new UserFragment();
    FavoriteFragment favoriteFragment = new FavoriteFragment();
    MapFragment mapFragment = new MapFragment();

    fragmentList.add(homeFragment);
    fragmentList.add(messagesFragment);
    fragmentList.add(userFragment);
    fragmentList.add(favoriteFragment);
    fragmentList.add(mapFragment);
}

E abbiamo bisogno di un modo per sapere quale frammento è stato selezionato dall'elenco, quindi abbiamo bisogno della getFragmentIndexfunzione

private int getFragmentIndex(Fragment fragment) {
    int index = -1;
    for (int i = 0; i < fragmentList.size(); i++) {
        if (fragment.hashCode() == fragmentList.get(i).hashCode()){
            return i;
        }
    }
    return index;
}

E infine, al displayFragmentmetodo piacerà questo:

private void displayFragment(Fragment fragment) {
        int index = getFragmentIndex(fragment);
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        if (fragment.isAdded()) { // if the fragment is already in container
            transaction.show(fragment);
        } else { // fragment needs to be added to frame container
            transaction.add(R.id.placeholder, fragment);
        }
        // hiding the other fragments
        for (int i = 0; i < fragmentList.size(); i++) {
            if (fragmentList.get(i).isAdded() && i != index) {
                transaction.hide(fragmentList.get(i));
            }
        }
        transaction.commit();
    }

In questo modo, possiamo chiamare displayFragment(homeFragment)ad esempio.
Questo mostrerà automaticamente HomeFragmente nasconderà qualsiasi altro frammento nell'elenco.
Questa soluzione consente di aggiungere più frammenti a fragmentListsenza dover ripetere le ifistruzioni nella vecchia displayFragmentversione.
Spero che qualcuno lo trovi utile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.