Ci-dessous est mon code qui a 3 Fragment classes
chacun intégré avec chacun des 3 onglets ViewPager
. J'ai une option de menu. Comme indiqué dans le onOptionsItemSelected()
, en sélectionnant une option, je dois mettre à jour le fragment actuellement visible. Pour mettre à jour cela, je dois appeler une méthode qui est dans la classe des fragments. Quelqu'un peut-il suggérer comment appeler cette méthode?
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();
}
}
}
Supposons que ci-dessous soit la classe de fragment avec la méthode que updateList()
je veux appeler:
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
}
}
Réponses:
Une façon simple de le faire consiste à utiliser une astuce liée à la
FragmentPagerAdapter
mise en œuvre:Veuillez repenser votre convention de dénomination des variables, en utilisant comme nom de variable le nom de la classe est très déroutant (donc non
ViewPager ViewPager
, utilisezViewPager mPager
par exemple).la source
instantiateItem()
méthode et en obtenant vous-même les références aux fragments appropriés.mAdapter.getItem(position)
, génial ... Au moins maintenant, je sais que les autres essais 8512 n'ont pas fonctionné. Mercila source
onPageSelected
/onPageDeselected
et je fais en sorte que tous mes fragments de pager le prolongent. VoussetPrimaryitem
pouvez ensuite appeler ces méthodes de manière appropriée lorsque l'utilisateur glisse vers une nouvelle page. Cela signifie que vous pouvez implémenter une stratégie plus paresseuse pour le chargement de données dans des pages qui ne sont même pas affichées. Cependant, vous devez garder à l'esprit que pendant la transition de page, il est préférable que la page suivante soit déjà remplie de données, donc le chargement paresseux de toutes les données dansonPageSelected
peut ne pas être idéal.if
déclaration? Le fragment appelle simplement laequals
méthode de l'objet, qui est une comparaison superficielle. Alors pourquoi ne pas toujours appelermCurrentFragment = ((Fragment) object);
?Tout d'abord, gardez une trace de toutes les pages de fragments "actifs". Dans ce cas, vous gardez une trace des pages de fragments dans FragmentStatePagerAdapter, qui est utilisé par ViewPager.
Pour éviter de conserver une référence aux pages de fragments "inactifs", vous devez implémenter la méthode destroyItem (...) de FragmentStatePagerAdapter:
et lorsque vous devez accéder à la page actuellement visible, vous appelez alors:
Où la méthode getFragment (int) de MyAdapter ressemble à ceci:
J'espère que cela peut aider!
la source
C'est la seule façon dont je n'obtiens pas NullPointerException pour les variables d'instance de ces classes de fragments particulières. Cela pourrait être utile pour d'autres qui s'en tiennent à la même chose. Dans onOptionsItemSelected (), j'ai codé comme suit:
la source
FragmentStatePagerAdapter
sans remplacer aucun code. En fait, cela devrait être aussi simple qu'une fonction de retourviewPager.getAdapter().instantiateItem(viewPager, viewPager.getCurrentItem())
.FragmentStatePagerAdapter a une méthode publique avec le nom instantiateItem qui renvoie votre fragment en fonction des valeurs de paramètre spécifiées, cette méthode a deux paramètres ViewGroup (ViewPager) et position.
Utilisé cette méthode pour obtenir le fragment de position spécifié,
la source
Je sais que c'est trop tard mais j'ai des moyens très simples de le faire,
// pour fragment à 0 possession
la source
Il y a beaucoup de réponses ici qui ne répondent pas vraiment au fait fondamental qu'il n'y a vraiment AUCUNE FAÇON de le faire de manière prévisible, et d'une manière qui ne vous empêche pas de vous tirer une balle dans le pied à un moment donné dans le futur.
FragmentStatePagerAdapter
est la seule classe qui sait accéder de manière fiable aux fragments qui sont suivis par leFragmentManager
- toute tentative pour essayer de deviner l'identifiant ou la balise du fragment n'est pas fiable à long terme. Et les tentatives de suivi manuel des instances ne fonctionneront probablement pas bien lorsque l'état est enregistré / restauré, carFragmentStatePagerAdapter
peut bien que les rappels ne soient pas rappelés lors de la restauration de l'état.À propos de la seule chose que j'ai pu faire fonctionner, c'est la copie du code
FragmentStatePagerAdapter
et l'ajout d'une méthode qui renvoie le fragment, étant donné une position (mFragments.get(pos)
). Notez que cette méthode suppose que le fragment est réellement disponible (c'est-à-dire qu'il était visible à un moment donné).Si vous êtes particulièrement aventureux, vous pouvez utiliser la réflexion pour accéder aux éléments de la
mFragments
liste privée , mais nous revenons à la case départ (le nom de la liste n'est pas garanti de rester le même).la source
Convertissez l'instance récupérée de la ligne ci-dessus dans le fragment sur lequel vous souhaitez travailler. Fonctionne parfaitement bien.
est l'instance de pager gérant les fragments.
la source
Pour obtenir une référence au fragment actuellement visible, supposez que vous avez une référence à
ViewPager
asmPager
. Ensuite, les étapes suivantes obtiendront une référence àcurrentFragment
:PageAdapter adapter = mPager.getAdapter();
int fragmentIndex = mPager.getCurrentItem();
FragmentStatePagerAdapter fspa = (FragmentStatePagerAdapter)adapter;
Fragment currentFragment = fspa.getItem(fragmentIndex);
La seule ligne de distribution utilisée 3 est généralement valide.
FragmentStatePagerAdapter
est un adaptateur utile pour un ViewPager.la source
La meilleure façon de le faire, appelez simplement CallingFragmentName fragment = (CallingFragmentName) viewPager .getAdapter () .instantiateItem (viewPager, viewPager.getCurrentItem ()); Il réinstanciera votre fragment appelant, de sorte qu'il ne lèvera pas d'exception de pointeur nul et n'appellera aucune méthode de ce fragment.
la source
Fragment actuel:
Cela fonctionne si vous avez créé un projet avec le modèle de barre d'onglets de fragments.
Notez que cela fonctionne avec l'implémentation du modèle d'activité à onglets par défaut.
la source
J'ai utilisé ce qui suit:
la source
FragmentStatePagerAdapter
a une variable d'instance privée appeléemCurrentPrimaryItem
de typeFragment
. On ne peut que se demander pourquoi les développeurs Android ne l'ont pas fourni avec un getter. Cette variable est instanciée dans lasetPrimaryItem()
méthode. Donc, remplacez cette méthode de manière à obtenir la référence à cette variable. J'ai simplement fini par déclarer le mienmCurrentPrimaryItem
et copier le contenu desetPrimaryItem()
mon surpassement.Dans votre implémentation de
FragmentStatePagerAdapter
:la source
Vous pouvez définir
PagerAdapter
comme cela , alors vous serez en mesure d'obtenir toutFragment
enViewPager
.Pour obtenir le courant
Fragment
la source
Lorsque nous utilisons le viewPager, un bon moyen d'accéder à l'instance de fragment en activité est instantiateItem (viewpager, index). // index- index du fragment dont vous voulez l'instance.
par exemple, j'accède à l'instance de fragment de 1 index-
la source
Dans mon implémentation précédente, j'ai stocké une liste de fragments enfants pour pouvoir y accéder plus tard, mais cela s'est avéré être une implémentation incorrecte provoquant d'énormes fuites de mémoire.
Je
instantiateItem(...)
finis par utiliser la méthode pour obtenir le fragment actuel:Ou pour obtenir n'importe quel autre fragment en position:
De la documentation :
la source
J'ai eu le même problème et l'ai résolu en utilisant ce code.
Remplacez simplement le nom MyFragment par le nom de votre fragment et ajoutez l'ID de votre conteneur de fragments.
la source
C'est plus pérenne que la réponse acceptée:
la source
Le scénario en question est mieux servi par chaque fragment ajoutant ses propres éléments de menu et traitant directement onOptionsItemSelected (), comme décrit dans la documentation officielle . Il vaut mieux éviter les trucs non documentés.
la source
ViewPager
problème?Après avoir lu tous les commentaires et réponses, je vais vous expliquer une solution optimale pour ce problème. La meilleure option est la solution de @ rik, donc mon amélioration est basée sur la sienne.
Au lieu d'avoir à demander à chaque FragmentClass comme
Créez votre propre interface et faites en sorte que vos fragments enfants l'implémentent, quelque chose comme
Ensuite, vous pouvez faire quelque chose comme ça pour lancer et mettre à jour vos fragments internes.
PS Faites attention où vous mettez ce code, si vous appelez insatiateItem avant que le système ne le crée réellement, le
savedInstanceState
fragment de votre enfant sera nul à cet effetVa planter votre application.
Bonne chance
la source
Sur la base de ce qu'il a répondu @chahat jain:
"Lorsque nous utilisons le viewPager, un bon moyen d'accéder à l'instance de fragment en activité est instantiateItem (viewpager, index). // index- index du fragment dont vous voulez l'instance."
Si vous voulez le faire en kotlin
0 à l'instance de fragment de 0
// ================================================= ========================= // // ###################### ######## Exemple d'utilisation ################################# // // == =================================================== ===================== //
Voici un exemple complet pour avoir une vision des plus
voici mon veiewPager dans le fichier .xml
Et l'activité à domicile où j'insère l'onglet
la source
Dans mon activité, j'ai:
la source
Parfois, le fragment peut envoyer un objet nul, vous pouvez donc exécuter un nouveau Runnable pour résoudre le problème au premier chargement.
Merci rick
la source
Remplacez setPrimaryItem de votre FragmentPagerAdapter: l'objet est le fragment visible:
la source
Obtenez simplement l'élément actuel du téléavertisseur, puis demandez à votre adaptateur le fragment de cette position.
la source
getItem
crée une nouvelle instancePour obtenir le fragment actuel - obtenez la position dans ViewPager à public void onPageSelected (position int finale) , puis
SECTNUM - argument de position affecté dans public PlaceholderFragment statique newInstance (int sectionNumber);de fragment
getChildFragmentManager () ou getFragmentManager () - dépend de la façon dont SectionsPagerAdapter a été créé
la source
Vous pouvez implémenter un BroadcastReceiver dans le fragment et envoyer une intention de n'importe où. Le récepteur du fragment peut écouter l'action spécifique et invoquer la méthode de l'instance.
Une mise en garde consiste à s'assurer que le composant View est déjà instancié et (et pour certaines opérations, telles que le défilement d'une liste, le ListView doit déjà être rendu).
la source
C'est le hack le plus simple:
(code kotlin)
Appelez-le
instantiateItem(viewPager, viewPager.getCurrentItem()
et lancez-leFragment
. Votre article serait déjà instancié. Pour être sûr, vous pouvez ajouter un chèque pourgetCount
.Fonctionne avec les deux
FragmentPagerAdapter
etFragmentStatePagerAdapter
!la source
Si votre téléavertisseur se trouve dans un fragment, utilisez ceci:
Où
R.id.myViewPagerId
est l'ID de votre ViewPager dans la mise en page XML.la source
Vous pouvez déclarer un tableau de fragments en tant que fragments de registre
Ensuite, vous pouvez l'utiliser comme
la source