Ich verwende den v4-Kompatibilitäts-ViewPager in Android. Meine FragmentActivity enthält eine Reihe von Daten, die auf verschiedenen Seiten in meinem ViewPager auf unterschiedliche Weise angezeigt werden sollen. Bisher habe ich nur 3 Instanzen desselben ListFragments, aber in Zukunft werde ich 3 Instanzen verschiedener ListFragments haben. Der ViewPager befindet sich auf einem vertikalen Telefonbildschirm. Die Listen werden nicht nebeneinander angezeigt.
Jetzt startet eine Schaltfläche im ListFragment eine separate ganzseitige Aktivität (über die FragmentActivity), die zurückgibt und FragmentActivity die Daten ändert, speichert und dann versucht, alle Ansichten in ihrem ViewPager zu aktualisieren. Hier stecke ich fest.
public class ProgressMainActivity extends FragmentActivity
{
MyAdapter mAdapter;
ViewPager mPager;
@Override
public void onCreate(Bundle savedInstanceState)
{
...
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.viewpager);
mPager.setAdapter(mAdapter);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
...
updateFragments();
...
}
public void updateFragments()
{
//Attempt 1:
//mAdapter.notifyDataSetChanged();
//mPager.setAdapter(mAdapter);
//Attempt 2:
//HomeListFragment fragment = (HomeListFragment) getSupportFragmentManager().findFragmentById(mAdapter.fragId[0]);
//fragment.updateDisplay();
}
public static class MyAdapter extends FragmentPagerAdapter implements
TitleProvider
{
int[] fragId = {0,0,0,0,0};
public MyAdapter(FragmentManager fm)
{
super(fm);
}
@Override
public String getTitle(int position){
return titles[position];
}
@Override
public int getCount(){
return titles.length;
}
@Override
public Fragment getItem(int position)
{
Fragment frag = HomeListFragment.newInstance(position);
//Attempt 2:
//fragId[position] = frag.getId();
return frag;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE; //To make notifyDataSetChanged() do something
}
}
public class HomeListFragment extends ListFragment
{
...
public static HomeListFragment newInstance(int num)
{
HomeListFragment f = new HomeListFragment();
...
return f;
}
...
Wie Sie sehen können, bestand mein erster Versuch darin, DataSetChanged für den gesamten FragmentPagerAdapter zu benachrichtigen. Dies zeigte, dass die Daten manchmal aktualisiert wurden. Bei anderen wurde jedoch eine IllegalStateException angezeigt: Diese Aktion kann nach onSaveInstanceState nicht ausgeführt werden.
Bei meinem zweiten Versuch habe ich versucht, eine Aktualisierungsfunktion in meinem ListFragment aufzurufen, aber getId in getItem hat 0 zurückgegeben. Gemäß den Dokumenten, die ich ausprobiert habe
Abrufen eines Verweises auf das Fragment von FragmentManager mithilfe von findFragmentById () oder findFragmentByTag ()
aber ich kenne das Tag oder die ID meiner Fragmente nicht! Ich habe ein android: id = "@ + id / viewpager" für ViewPager und ein android: id = "@ android: id / list" für meine ListView im ListFragment-Layout, aber ich denke nicht, dass diese nützlich sind.
Wie kann ich also entweder: a) den gesamten ViewPager auf einmal sicher aktualisieren (idealerweise den Benutzer auf die Seite zurückbringen, auf der er zuvor war) - es ist in Ordnung, dass der Benutzer die Ansichtsänderung sieht. Oder vorzugsweise b) eine Funktion in jedem betroffenen ListFragment aufrufen, um die ListView manuell zu aktualisieren.
Jede Hilfe wäre dankbar!
null
Fragmente.FragmentPagerAdaper
, schlägt aber fehlFragmentStatePagerAdaper
(Fragment.getTag()
immer zurückkehrennull
.Die Antwort von Barkside funktioniert mit
FragmentPagerAdapter
, funktioniert aber nichtFragmentStatePagerAdapter
, da sie keine Tags für Fragmente setzt, an die sie übergeben wirdFragmentManager
.Mit
FragmentStatePagerAdapter
scheint es , können wir erhalten , indem ihre VerwendunginstantiateItem(ViewGroup container, int position)
Anruf. Es gibt den Verweis auf das Fragment an der Position zurückposition
. WennFragmentStatePagerAdapter
bereits ein Verweis auf das betreffende Fragment vorhanden ist, wirdinstantiateItem
nur der Verweis auf dieses Fragment zurückgegeben und nicht aufgerufengetItem()
, um es erneut zu instanziieren.Angenommen, ich betrachte derzeit Fragment Nr. 50 und möchte auf Fragment Nr. 49 zugreifen. Da sie nahe beieinander liegen, besteht eine gute Chance, dass die Nummer 49 bereits instanziiert wird. So,
quelle
FragmentStatePagerAdapter
Verwendung des obigen Codes mita.instantiateItem(viewPager, viewPager.getCurrentItem());
(um die 49 loszuwerden), wie von @ mblackwell8 vorgeschlagen, perfekt.instantiateItem
vonstartUpdate
/finishUpdate
Anrufe umgeben sein sollten. Details sind in meiner Antwort auf eine ähnliche Frage: stackoverflow.com/questions/14035090/…OK, ich denke, ich habe in meiner eigenen Frage einen Weg gefunden, die Anfrage b) auszuführen, damit ich sie zum Nutzen anderer teilen kann. Das Tag der Fragmente in einem ViewPager befindet sich in der Form
"android:switcher:VIEWPAGER_ID:INDEX"
, in derVIEWPAGER_ID
sich dasR.id.viewpager
XML-Layout befindet, und INDEX ist die Position im Viewpager. Wenn also die Position bekannt ist (zB 0), kann ich Folgendes ausführenupdateFragments()
:Ich habe keine Ahnung, ob dies eine gültige Methode ist, aber es wird funktionieren, bis etwas Besseres vorgeschlagen wird.
quelle
makeFragmentName
, mit der das Tag generiert wird, das Sie stattdessen für einen etwas weniger hackigen Ansatz verwenden können:HomeListFragment fragment = (HomeListFragment) getSupportFragmentManager().findFragmentByTag(FragmentPagerAdapter.makeFragmentName(R.id.viewpager, 0));
makeFragmentName
ist eineprivate static
Methode, sodass Sie keinen Zugriff darauf erhalten können.Wenn Sie mich fragen, ist die zweite Lösung auf der folgenden Seite, die alle "aktiven" Fragmentseiten im Auge behält, besser: http://tamsler.blogspot.nl/2011/11/android-viewpager-and-fragments-part -ii.html
Die Antwort von Barkside ist mir zu hackig.
Sie verfolgen alle "aktiven" Fragmentseiten. In diesem Fall verfolgen Sie die Fragmentseiten im FragmentStatePagerAdapter, der vom ViewPager verwendet wird.
Um zu vermeiden, dass ein Verweis auf "inaktive" Fragmentseiten beibehalten wird, müssen wir die destroyItem (...) -Methode des FragmentStatePagerAdapter implementieren:
... und wenn Sie auf die aktuell sichtbare Seite zugreifen müssen, rufen Sie an:
... wo die getFragment (int) -Methode des MyAdapters folgendermaßen aussieht:
""
quelle
Okay, nachdem ich die Methode von @barkside oben getestet hatte, konnte ich sie nicht mit meiner Anwendung zum Laufen bringen. Dann erinnerte ich mich, dass die IOSched2012-App auch eine verwendet
viewpager
, und dort fand ich meine Lösung. Es werden keine Fragment-IDs oder Tags verwendet, da diese nichtviewpager
auf leicht zugängliche Weise gespeichert werden .Hier sind die wichtigen Teile der IOSched-Apps HomeActivity. Achten Sie besonders auf den Kommentar , da darin der Schlüssel liegt:
Und speichern Instanzen von Ihnen
Fragments
inFragmentPagerAdapter
etwa so:Denken Sie auch daran, Ihre
Fragment
Anrufe wie folgt zu schützen :quelle
getItem()
nicht aufgerufen werden, nachdem das übergeordnete Element aufgrund einer Änderung des Lebenszyklus neu erstellt wurde. Siehe stackoverflow.com/a/24662049/236743 . Im Beispiel ist dies teilweise für ein Fragment geschützt, nicht jedoch für die beiden anderenSie können
FragmentPagerAdapter
einen Quellcode kopieren und ändern und einegetTag()
Methode hinzufügenbeispielsweise
Erweitern Sie es dann, überschreiben Sie diese abstrakte Methode und müssen Sie keine Angst vor Änderungen in der Android-Gruppe haben
FragmentPageAdapter
Quellcode in der Zukunftquelle
Funktioniert auch ohne Probleme:
irgendwo im Layout des Seitenfragments:
in onCreateView () des Fragments:
und Methode zum Zurückgeben von Fragment aus ViewPager, falls vorhanden:
quelle
Alternativ können Sie die
setPrimaryItem
MethodeFragmentPagerAdapter
wie folgt überschreiben :quelle
Ich möchte meinen Ansatz angeben, falls er jemand anderem helfen kann:
Dies ist mein Pager-Adapter:
In meiner Tätigkeit habe ich:
Um das aktuelle Fragment zu erhalten, mache ich Folgendes:
quelle
Dies ist meine Lösung, da ich meine Registerkarten nicht im Auge behalten und sie trotzdem alle aktualisieren muss.
quelle