Zeige verstecktes Fragment in Android

98

Ich entwickle eine Anwendung, die 2 Fragmente enthält, und ich möchte je nach Bedarf Haut zeigen. Der folgende Code enthält ein einfaches Beispiel für mein Problem. Diese einfache Fragmentaktivität enthält 1 Schaltfläche und ein Listenfragment.

Dieses einfache Beispiel funktioniert einwandfrei. aber ich bin nicht zufrieden mit show hide fragment. Wenn Sie layout.setVisibility (View.GONE) entfernen; aus dem Code dann ft.hide (f); Fragment nicht verbergen. Tatsächlich verstecken wir kein Fragment, sondern einen Container.

Meine Frage ist, IST dies eine Möglichkeit, Hautfragmente anzuzeigen? Wenn nicht, erklären Sie bitte anhand eines getesteten Beispiels, wie Fragmente ausgeblendet und angezeigt werden, da viele Menschen mit diesem Problem konfrontiert sind.

 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
        }
abidkhan303
quelle
Warum müssen Sie die Sichtbarkeit des Containers einstellen? Es sollte funktionieren, ohne die Sichtbarkeit einzustellen.
Andrii Chernenko
Genau sollte es ohne Sichtbarkeit des Containers funktionieren, aber es funktioniert nicht. Bitte, bitte, bitte teile mir ein einfaches Arbeitsbeispiel mit. Dann würde ich wissen, wo ich vermisse.
abidkhan303
1
Ich vermute, dass Sie jedes Mal versuchen, eine andere Fragmentinstanz ein- oder auszublenden. Wenn Sie Ihr Fragment hinzufügen (ich sehe diesen Code übrigens nicht), fügen Sie es mit einem Tag hinzu und rufen Sie es dann mit diesem Tag ab (anstatt zu versuchen, einen Verweis darauf zu speichern). Das könnte das sein, was du vermisst.
Andrii Chernenko

Antworten:

158

Leg dich nicht mit den Sichtbarkeitsflags des Containers an - FragmentTransaction.hide / show erledigt das intern für dich.

Der richtige Weg, dies zu tun, ist also:

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

ODER wenn Sie android.support.v4.app.Fragment verwenden

 FragmentManager fm = getSupportFragmentManager();
 fm.beginTransaction()
          .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out)
          .show(somefrag)
          .commit();
numan salati
quelle
5
Warum empfehlen Sie, nicht direkt mit den Flags zu spielen? (Ich bestreite Ihre Empfehlung nicht, versuche nur, sie zu verstehen.)
Ellen Spertus
1
Ja, das habe ich in Ihrer Originalnachricht gelesen. Ich hatte gehofft, Sie könnten den zusätzlichen Aufwand begründen. In der Zwischenzeit habe ich einige entdeckt, beispielsweise die Option zum Hinzufügen zum Backstack.
Ellen Spertus
2
Es ist fehleranfällig, da Sie Ihre Flags bei niedriger und hoher API ändern können und wenn Sie nicht vorsichtig sind (dh Flags nicht mehr synchron sind), könnten Sie seltsame Fehler verfolgen. Aus diesem Grund wird empfohlen, den Fragment-Manager zum Ausblenden und Anzeigen Ihrer Fragmente zu verwenden.
numan salati
@numansalati Hallo, gibt es eine kompatible (aus der Support-Bibliothek) Version von android.R.animator.fade_inund android.R.animator.fade_out?
Trost
1
Mit dem Container können Sie SHOW, HIDE oder GONE einstellen. Beim Ausblenden eines Fragments gibt es keine Option GONE.
Stealth Rabbi
57

Darüber hinaus können Sie in einem Fragment Folgendes tun (z. B. wenn das Abrufen von Serverdaten fehlgeschlagen ist):

 getView().setVisibility(View.GONE);
Arie
quelle
11
Fragment ist ein Kind von Object und nicht View, daher kann man nicht aufrufen: fragment.setVisibility (View.INVISIBLE);
Zar E Ahmer
8
Arià schlägt etwas anderes vor, schlägt vor, die Ansicht von diesem Fragment zu erhalten und seine Sichtbarkeit auf "weg" zu setzen.
AlvaroSantisteban
10
Vorsicht getView()kann sein, nullwenn es noch nicht initialisiert ist.
TWiStErRob
22

Hallo, wenn Sie diesen Ansatz verwenden, bleiben alle Fragmente nach dem erstmaligen Hinzufügen im Container. Dann enthüllen wir einfach das gewünschte Fragment und verstecken die anderen im Container.

// 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();
}

Weitere Informationen finden Sie unter https://github.com/codepath/android_guides/wiki/Creating-and-Using-Fragments . Ich hoffe ich kann jemandem helfen. Auch wenn dies eine alte Frage ist.

mangu23
quelle
1
Sie müssen also zwei weitere Methoden wie displayFragmentB () und displayFragmentC () haben?
Temirbek
yes @temirbek Sie können einfach verfolgen, wie die displayFragmentA () -Methode implementiert wird.
Mangu23
1
Wenn Sie viele Fragmente in einer Aktivität haben (2 oder mehr) und die oben beschriebene Methode verwenden, verwenden Sie diese bitte . Es wird einfacher zu schreiben und zu lesen sein.
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();
}
Jyo der Hauch
quelle
1
richtig ist ft.setCustomAnimations (android.R.anim.fade_in, android.R.anim.fade_out);
Webserveis
8

Versuche dies:

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

Im Vergleich zu der obigen Lösung besteht der einfachste Weg aus meinem Code darin, ein Layout zu definieren, das das Fragment enthält. Anschließend können Sie das Fragment ein- oder ausblenden, indem Sie das Layoutattribut steuern, das an der allgemeinen Ansicht ausgerichtet ist. In diesem Fall ist kein zusätzlicher Code erforderlich, und die zusätzlichen Bereitstellungsattribute des Fragments konnten in das äußere Layout verschoben werden.

<LinearLayout style="@style/StHorizontalLinearView"
    >

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

</LinearLayout>
BrainAtom
quelle
0

Das hat bei mir funktioniert

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();
Shankey
quelle
0

Die Antworten hier sind richtig und ich mochte @Jyo die Whiff-Idee einer Implementierung zum Anzeigen und Verstecken von Fragmenten, außer dass die Art und Weise, wie er sie derzeit hat, das Fragment beim ersten Durchlauf ausblenden würde, also habe ich eine kleine Änderung hinzugefügt, indem ich den isAdded-Check und die Show hinzugefügt habe das Fragment, wenn es nicht schon ist

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();
} 
martinseal1987
quelle
0
final Fragment fragment1 = new fragment1();
final Fragment fragment2 = new fragment2();
final FragmentManager fm = getSupportFragmentManager();
Fragment active = fragment1;

In onCreate habe ich nach setContentView zwei Fragmente versteckt und sie an den Fragmentmanager übergeben, aber das erste Fragment, das als Home dienen soll, habe ich nicht ausgeblendet.

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;
}

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

Rachit Vohera
quelle
0

Ich bin vielleicht viel zu spät, aber es könnte jemandem in der Zukunft helfen.
Diese Antwort ist eine Modifikation der mangu23 Antwort.
Ich habe nur eine for-Schleife hinzugefügt, um Wiederholungen zu vermeiden und einfach weitere Fragmente ohne Boilerplate-Code hinzuzufügen.

Wir brauchen zuerst eine Liste der Fragmente , die angezeigt werden sollen

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

Dann müssen wir es mit unseren Fragmenten füllen

@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);
}

Und wir brauchen eine Möglichkeit zu wissen, welches Fragment aus der Liste ausgewählt wurde, also brauchen wir getFragmentIndexFunktion

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;
}

Und schließlich wird die displayFragmentMethode so aussehen:

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();
    }

Auf diese Weise können wir displayFragment(homeFragment)zum Beispiel anrufen .
Dadurch wird das HomeFragmentandere Fragment in der Liste automatisch angezeigt und ausgeblendet.
Mit dieser Lösung können Sie weitere Fragmente an das anhängen, fragmentListohne die ifAnweisungen in der alten displayFragmentVersion wiederholen zu müssen .
Ich hoffe, jemand wird dies nützlich finden.

Mohamed Medhat
quelle