Wie teste ich, ob eine Fragmentansicht für den Benutzer sichtbar ist?


73

Ich habe einen ViewPager, jede Seite ist eine Fragmentansicht. Ich möchte testen, ob sich ein Fragment in einem sichtbaren Bereich befindet. Der Fragment.ist nur sichtbar

  • Das Fragment ist an eine Aktivität gebunden
  • Das Fragment ist sichtbar
  • Das Fragment wurde einer Ansicht hinzugefügt

Der ViewPager erstellt 3 (standardmäßig) Fragmente und alle drei erfüllen die oben genannten Kriterien, aber nur eines ist für den Benutzer (das menschliche Auge ) tatsächlich sichtbar.


Bitte posten Sie Ihren Code für eine bessere Hilfe.
Raj

4
Das würde ich im Moment sicher auch gerne wissen.
Manfred Moser

Antworten:


19

Sie haben Recht, es gibt einen besseren Weg, dies zu tun!

Wenn Sie sich das FragmentPagerAdapter- Javadoc online ansehen, werden Sie feststellen, dass es eine Methode setPrimaryItem gibt (ViewGroup-Container, int-Position, Objektobjekt): void genau das tun, was Sie brauchen.

Aus dem Javadoc

public void setPrimaryItem (ViewGroup-Container, int-Position, Objektobjekt)

Wird aufgerufen, um den Adapter darüber zu informieren, welches Element derzeit als "primär" betrachtet wird. Dies ist das Element, das dem Benutzer als aktuelle Seite angezeigt wird.

Parametercontainer Die enthaltende Ansicht, aus der die Seite entfernt wird. position Die Seitenposition, die jetzt die primäre ist. object Das gleiche Objekt, das von instantiateItem (View, int) zurückgegeben wurde.

Hinweis zum Bildlaufstatus

Wenn Sie dies jetzt implementieren und mit dem Debuggen beginnen, um ein Gefühl dafür zu bekommen, wann genau dies aufgerufen wird, werden Sie schnell feststellen, dass dies mehrmals beim Vorbereiten des Fragments und beim Wischen des Benutzers ausgelöst wird.

Daher ist es möglicherweise eine gute Idee, auch einen ViewPager.OnPageChangeListener anzuhängen und erst dann das zu tun, was zu tun ist, wenn der Bildlaufstatus des Viewpagers wieder SCOLL_STATE_IDLE wird.


1
Dieser Ansatz funktioniert hervorragend, wenn man die ApplicationKlasse erweitert und testen muss, ob eine bestimmte Benutzeroberfläche angezeigt wird. Am Ende habe ich mehrere Boolesche Werte verwendet, um zu testen, ob die App im Hintergrund ausgeführt wurde und ob ein bestimmtes Fragment angezeigt wurde.
Jemand irgendwo

67

Dies ist, was ich benutze, um die Sichtbarkeit eines Fragments zu bestimmen.

private static boolean m_iAmVisible;

@Override
public void setUserVisibleHint(boolean isVisibleToUser) { 
    super.setUserVisibleHint(isVisibleToUser);
    m_iAmVisible = isVisibleToUser;

    if (m_iAmVisible) { 
        Log.d(localTAG, "this fragment is now visible");
    } else {  
        Log.d(localTAG, "this fragment is now invisible");
    }
}

Dies funktioniert nicht gemäß der Dokumentation: "Legen Sie dem System einen Hinweis darauf fest, ob die Benutzeroberfläche dieses Fragments derzeit für den Benutzer sichtbar ist. Dieser Hinweis ist standardmäßig true und bleibt über das Speichern und Wiederherstellen des Fragmentinstanzstatus hinweg bestehen"
Edison,

1
Gute Lösung (+1), aber Code kann vereinfacht werden: public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); m_iAmVisible = false; //default to not visible if (isVisibleToUser) { m_iAmVisible = true; } }
PeteH

2
vereinfacht ist: public void setUserVisibleHint (boolean isVisibleToUser) {super.setUserVisibleHint (isVisibleToUser); m_iAmVisible = isVisibleToUser;}
Kasas

30
noch einfacher,getUserVisibleHint()
Leonardo Pinto

1
DAS HILFT VIELEN DANK!
Lazar Kukolj

9

Für meine Zwecke hat es funktioniert, ViewPager.OnPageChangeListener.onPageSelected()in Verbindung mit Fragment.onActivityCreated()eine Aktion auszuführen, wenn das Fragment sichtbar ist. Fragment.getUserVisibleHint()hilft auch.


3

Ich verwende "setMenuVisibility" -Methode zur Lösung dieses Problems. Da jedes Fragment Aktionsleistenelemente enthalten kann, können Sie in diesem Teil bestimmen, welches Fragment derzeit für den Benutzer sichtbar ist.

@Override
public void setMenuVisibility(final boolean visible) {
    super.setMenuVisibility(visible);
    if (!visible) {
        //not visible anymore
    }else{
        yay visible to the user
    }
}

3

Was ist falsch daran getView().isShown(), herauszufinden, ob ein Fragment tatsächlich sichtbar ist?


Hast du deine Idee getestet? Ich denke, dieser Beitrag hat auf die gleiche Idee hingewiesen.
David S.

Ja. Es funktioniert für mich, wie im verlinkten Beitrag vorgeschlagen.
Awy

3
isVisible() 

Kann auch dann true zurückgeben, wenn sich das Fragment hinter einer Aktivität befindet.

Ich benutze folgendes:

if (getView() != null && getView().isShown()) {
//your code here
}

1
nach diesem , isShownist ähnlich , getVisibility()so dass es immer noch wahr zurück , wenn VISIBLEaber hinter einer Aktivität
Mysterious_android

2

Wenn Sie wissen, an welche "Seite" jedes Fragment angehängt ist, können Sie mithilfe von ViewPager.getCurrentItem () bestimmen, welches Fragment "sichtbar" ist.


4
Das mache ich gerade. Ich denke nur, ob es andere Wege gibt. Vielen Dank
David S.

0

In meinem Fall muss ich am ersten Fragment arbeiten, wenn das Fragment für den Benutzer sichtbar ist

 @Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);


    if(viewPager.getAdapter() instanceof YourPager)
    {
        Fragment fragemnt=((YourPager)viewPager.getAdapter()).getFragment(0); //getFragment(int index) custom method
        if( fragemnt instanceof YourFragment)
        {
            ((YourFragment)fragemnt).methodWhochShouldBeCalledAfterUIVisible();
        }
    }
}

0

setUserVisibleHintwird wahrscheinlich nicht aufgerufen, onHiddenChangedkann nicht jedes Mal aufgerufen werden, wenn ein anderes Fragment geschlossen wird. Sie können sich also auf onResume(und onPause) verlassen, dies wird jedoch normalerweise zu oft aufgerufen (z. B. wenn Sie einen Gerätebildschirm einschalten). In einigen Situationen, in denen es nicht aufgerufen wird, sollten Sie das aktuelle Fragment in der Hostaktivität verwalten und schreiben:

if (currentFragment != null) {
    currentFragment.onResume();
}

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.