Unten ist mein Code, in den 3 Fragment classes
jeweils die drei Registerkarten eingebettet sind ViewPager
. Ich habe eine Menüoption. Wie in der Abbildung gezeigt onOptionsItemSelected()
, muss ich durch Auswahl einer Option das derzeit sichtbare Fragment aktualisieren. Um dies zu aktualisieren, muss ich eine Methode aufrufen, die sich in der Fragmentklasse befindet. Kann jemand bitte vorschlagen, wie man diese Methode aufruft?
public class MainActivity extends ActionBarActivity {
ViewPager ViewPager;
TabsAdapter TabsAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewPager = new ViewPager(this);
ViewPager.setId(R.id.pager);
setContentView(ViewPager);
final ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
//Attaching the Tabs to the fragment classes and setting the tab title.
TabsAdapter = new TabsAdapter(this, ViewPager);
TabsAdapter.addTab(bar.newTab().setText("FragmentClass1"),
FragmentClass1.class, null);
TabsAdapter.addTab(bar.newTab().setText("FragmentClass2"),
FragmentClass2.class, null);
TabsAdapter.addTab(bar.newTab().setText("FragmentClass3"),
FragmentClass3.class, null);
if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.addText:
**// Here I need to call the method which exists in the currently visible Fragment class**
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex());
}
public static class TabsAdapter extends FragmentPagerAdapter
implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
public TabsAdapter(ActionBarActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
@Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// TODO Auto-generated method stub
}
@Override
public void onPageSelected(int position) {
// TODO Auto-generated method stub
mActionBar.setSelectedNavigationItem(position);
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Object tag = tab.getTag();
for (int i=0; i<mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
tabPosition = tab.getPosition();
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
@Override
public int getCount() {
return mTabs.size();
}
}
}
Angenommen, unten ist die Fragmentklasse mit der Methode, die updateList()
ich aufrufen möchte:
public class FragmentClass1{
ArrayList<String> originalData;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.frag1, container, false);
originalData = getOriginalDataFromDB();
return fragmentView;
}
public void updateList(String text)
{
originalData.add(text);
//Here I could do other UI part that need to added
}
}
Antworten:
Eine einfache Möglichkeit hierfür ist die Verwendung eines Tricks im Zusammenhang mit der
FragmentPagerAdapter
Implementierung:Bitte überdenken Sie Ihre Namenskonvention für Variablen. Verwenden Sie als Variablennamen den Namen der Klasse, der sehr verwirrend ist (also nein
ViewPager ViewPager
, verwenden SieViewPager mPager
zum Beispiel).quelle
instantiateItem()
Methode überschreiben und selbst Verweise auf die richtigen Fragmente erhalten.mAdapter.getItem(position)
, super ... Zumindest weiß ich jetzt, dass die anderen 8512-Versuche nicht funktioniert haben. Vielen Dankquelle
onPageSelected
/onPageDeselected
und lasse es von allen meinen Pager-Fragmenten erweitern. DannsetPrimaryitem
können diese Methoden in geeigneter Weise aufrufen , wenn der Benutzer auf eine neue Seite klaut. Dies bedeutet, dass Sie möglicherweise eine faulere Strategie zum Laden von Daten auf Seiten implementieren, die nicht einmal angezeigt werden. Sie sollten jedoch berücksichtigen, dass es während des Seitenübergangs besser aussieht, wenn die nächste Seite bereits mit Daten gefüllt ist, sodass das verzögerte Laden aller DatenonPageSelected
möglicherweise nicht ideal ist.if
Aussage? Fragment ruft nur dieequals
Methode des Objekts auf, die ein flacher Vergleich ist. Warum also nicht einfach immer anrufenmCurrentFragment = ((Fragment) object);
?Verfolgen Sie zunächst 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 Sie 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:
Hoffe es kann helfen!
quelle
Nur so erhalte ich keine NullPointerException für die Instanzvariablen dieser bestimmten Fragmentklassen. Dies kann für andere hilfreich sein, die an der gleichen Sache festhalten. In onOptionsItemSelected () habe ich den folgenden Weg codiert:
quelle
FragmentStatePagerAdapter
ohne Code zu überschreiben. Tatsächlich sollte es so einfach sein wie eine Funktion, die einfach zurückkehrtviewPager.getAdapter().instantiateItem(viewPager, viewPager.getCurrentItem())
.FragmentStatePagerAdapter verfügt über eine öffentliche Methode mit dem Namen instantiateItem, die Ihr Fragment basierend auf angegebenen Parameterwerten zurückgibt. Diese Methode verfügt über zwei Parameter ViewGroup (ViewPager) und position.
Verwendete diese Methode, um das Fragment der angegebenen Position abzurufen.
quelle
Ich weiß, dass es zu spät ist, aber ich habe wirklich einfache Möglichkeiten, es zu tun,
// für Fragment bei 0 Besitz
quelle
Hier gibt es viele Antworten, die nicht wirklich die grundlegende Tatsache ansprechen, dass es wirklich KEINE MÖGLICHKEIT gibt, dies vorhersehbar zu tun, und auf eine Weise, die nicht dazu führt, dass Sie sich irgendwann in der Zukunft in den Fuß schießen.
FragmentStatePagerAdapter
ist die einzige Klasse, die weiß, wie sie zuverlässig auf die Fragmente zugreifen kann, die von der verfolgt werdenFragmentManager
- Jeder Versuch, die ID oder das Tag des Fragments zu erraten, ist langfristig nicht zuverlässig. Und Versuche, die Instanzen manuell zu verfolgen, funktionieren wahrscheinlich nicht gut, wenn der Status gespeichert / wiederhergestellt wird, weilFragmentStatePagerAdapter
die Rückrufe möglicherweise nicht aufgerufen werden, wenn der Status wiederhergestellt wird.Das einzige, wofür ich arbeiten konnte, ist das Kopieren des Codes für
FragmentStatePagerAdapter
und das Hinzufügen einer Methode, die das Fragment bei gegebener Position zurückgibt (mFragments.get(pos)
). Beachten Sie, dass diese Methode davon ausgeht, dass das Fragment tatsächlich verfügbar ist (dh es war irgendwann sichtbar).Wenn Sie besonders abenteuerlustig sind, können Sie mithilfe der Reflexion auf die Elemente der privaten
mFragments
Liste zugreifen , aber dann kehren wir zum ersten Punkt zurück (der Name der Liste bleibt garantiert nicht gleich).quelle
Wandeln Sie die von der obigen Zeile empfangene Instanz in das Fragment um, mit dem Sie arbeiten möchten. Funktioniert einwandfrei.
ist die Pager-Instanz, die die Fragmente verwaltet.
quelle
Angenommen, Sie haben einen Verweis auf
ViewPager
as, um einen Verweis auf das aktuell sichtbare Fragment zu erhaltenmPager
. Die folgenden Schritte erhalten dann einen Verweis aufcurrentFragment
:PageAdapter adapter = mPager.getAdapter();
int fragmentIndex = mPager.getCurrentItem();
FragmentStatePagerAdapter fspa = (FragmentStatePagerAdapter)adapter;
Fragment currentFragment = fspa.getItem(fragmentIndex);
Die einzige Besetzung, die in Zeile 3 verwendet wird, ist normalerweise gültig.
FragmentStatePagerAdapter
ist ein nützlicher Adapter für einen ViewPager.quelle
Rufen Sie am besten einfach CallingFragmentName auf fragment = (CallingFragmentName) viewPager .getAdapter () .instantiateItem (viewPager, viewPager.getCurrentItem ()); Das aufrufende Fragment wird erneut instanziiert, sodass keine Nullzeigerausnahme ausgelöst und keine Methode dieses Fragments aufgerufen wird.
quelle
Aktuelles Fragment:
Dies funktioniert, wenn Sie ein Projekt mit der Registerkartenvorlage Fragmente erstellt haben.
Beachten Sie, dass dies mit der Standardimplementierung von Aktivitätsvorlagen mit Registerkarten funktioniert.
quelle
Ich habe folgendes verwendet:
quelle
FragmentStatePagerAdapter
hat eine private InstanzvariablemCurrentPrimaryItem
vom TypFragment
. Man kann sich nur fragen, warum Android-Entwickler es nicht mit einem Getter geliefert haben. Diese Variable wird in dersetPrimaryItem()
Methode instanziiert . Überschreiben Sie diese Methode also so, dass Sie den Verweis auf diese Variable erhalten. Am Ende habe ich einfach meine eigenen deklariertmCurrentPrimaryItem
und den Inhalt von kopiertsetPrimaryItem()
meiner Überschreibung .Bei Ihrer Implementierung von
FragmentStatePagerAdapter
:quelle
Sie können die definieren ,
PagerAdapter
wie dies dann können Sie alle bekommenFragment
inViewPager
.Um den Strom zu bekommen
Fragment
quelle
Wenn wir den viewPager verwenden, ist instantiateItem (viewpager, index) eine gute Möglichkeit, in Aktivität auf die Fragmentinstanz zuzugreifen. // Index - Index des Fragments, dessen Instanz Sie möchten.
Zum Beispiel greife ich auf die Fragmentinstanz von 1 index- zu.
quelle
Ich hatte das gleiche Problem und löste es mit diesem Code.
Ersetzen Sie einfach den Namen MyFragment durch den Namen Ihres Fragments und fügen Sie die ID Ihres Fragmentcontainers hinzu.
quelle
Dies ist zukunftssicherer als die akzeptierte Antwort:
quelle
Das fragliche Szenario wird besser bedient, wenn jedes Fragment seine eigenen Menüelemente hinzufügt und onOptionsItemSelected () direkt verarbeitet, wie in der offiziellen Dokumentation beschrieben . Es ist besser, undokumentierte Tricks zu vermeiden.
quelle
ViewPager
Problem?Nachdem ich alle Kommentare und Antworten gelesen habe, erkläre ich eine optimale Lösung für dieses Problem. Die beste Option ist @ riks Lösung, daher basiert meine Verbesserung auf seiner.
Anstatt jede FragmentClass wie fragen zu müssen
Erstellen Sie Ihre eigene Benutzeroberfläche, und lassen Sie Ihre Kinderfragmente sie implementieren
Dann können Sie so etwas tun, um Ihre inneren Fragmente zu initiieren und zu aktualisieren.
PS Seien Sie vorsichtig, wo Sie diesen Code ablegen. Wenn Sie insatiateItem aufrufen, bevor das System ihn tatsächlich erstellt, ist das
savedInstanceState
Ihres untergeordneten Fragments dafür nullStürzt Ihre App ab.
Viel Glück
quelle
Basierend auf dem, was er @chahat jain geantwortet hat:
"Wenn wir den viewPager verwenden, ist instantiateItem (viewpager, index) eine gute Möglichkeit, auf die Fragmentinstanz in Aktivität zuzugreifen. // Indexindex des Fragments, dessen Instanz Sie möchten."
Wenn du das in Kotlin machen willst
0 auf die Fragmentinstanz von 0
// ================================================ ========================= // // ###################### ######### Anwendungsbeispiel ################################## // // == ================================================== ===================== //
Hier ist ein vollständiges Beispiel, um eine verlustreichste Vision zu erhalten
Hier ist mein veiewPager in der XML-Datei
Und die Heimaktivität, bei der ich die Registerkarte einfüge
quelle
In meiner vorherigen Implementierung habe ich eine Liste untergeordneter Fragmente gespeichert, um später darauf zugreifen zu können. Dies stellte sich jedoch als falsche Implementierung heraus, die zu großen Speicherverlusten führte.
Am Ende benutze ich die
instantiateItem(...)
Methode, um das aktuelle Fragment zu erhalten:Oder um ein anderes Fragment in Position zu bringen:
Aus der Dokumentation :
quelle
In meiner Tätigkeit habe ich:
quelle
Manchmal kann das Fragment ein Nullobjekt auslösen, sodass Sie eine neue ausführbare Datei ausführen können, um das Problem beim ersten Laden zu beheben.
Danke Rick
quelle
Überschreiben Sie setPrimaryItem aus Ihrem FragmentPagerAdapter: Das Objekt ist das sichtbare Fragment:
quelle
Holen Sie sich einfach den aktuellen Artikel vom Pager und fragen Sie Ihren Adapter nach dem Fragment dieser Position.
quelle
getItem
eine neue Instanz erstelltUm das aktuelle Fragment abzurufen , rufen Sie die Position in ViewPager bei public void onPageSelected (endgültige int-Position) ab und dann
SECTNUM - Positionsargument, das im öffentlichen statischen PlaceholderFragment newInstance (int sectionNumber) zugewiesen wurde; des Fragments
getChildFragmentManager () oder getFragmentManager () - hängt davon ab, wie SectionsPagerAdapter erstellt wurde
quelle
Sie können einen BroadcastReceiver im Fragment implementieren und eine Absicht von überall senden. Der Empfänger des Fragments kann auf die bestimmte Aktion warten und die Methode der Instanz aufrufen.
Eine Einschränkung besteht darin, sicherzustellen, dass die View-Komponente bereits instanziiert ist und (und für einige Vorgänge, z. B. das Scrollen einer Liste, muss die ListView bereits gerendert sein).
quelle
Dies ist der einfachste Hack:
(Kotlin-Code)
Rufen
instantiateItem(viewPager, viewPager.getCurrentItem()
Sie einfach an und sprechen Sie es anFragment
. Ihr Artikel wurde bereits instanziiert. Um sicherzugehen, können Sie einen Scheck für hinzufügengetCount
.Funktioniert mit beiden
FragmentPagerAdapter
undFragmentStatePagerAdapter
!quelle
Wenn sich Ihr Pager in einem Fragment befindet, verwenden Sie Folgendes:
Wo
R.id.myViewPagerId
befindet sich die ID Ihres ViewPagers im XML-Layout?quelle
Sie können ein Array von Fragmenten als Registerfragmente deklarieren
Dann können Sie es als verwenden
quelle