Dans l'application que je développe, j'utilise un ViewPager avec des fragments et chaque fragment construit son propre menu indépendamment de tous les autres fragments du ViewPager.
Le problème est que, parfois, les éléments initialisés par défaut par ViewPager (c'est-à-dire dans son état initial) ne voient pas leurs éléments renseignés dans le menu des éléments d'action. Ce qui est pire, c'est que ce problème ne se produit que par intermittence. Si je glisse suffisamment dans le ViewPager pour que les fragments soient forcés de se réinitialiser, le menu se remplit correctement lorsque je recule.
Code d'activité:
package net.solarnz.apps.fragmentsample;
import Android.app.Activity;
import Android.app.Fragment;
import Android.app.FragmentManager;
import Android.os.Bundle;
import Android.support.v13.app.FragmentStatePagerAdapter;
import Android.support.v4.view.ViewPager;
public class FragmentSampleActivity extends Activity {
private ViewPagerAdapter mViewPagerAdapter;
private ViewPager mViewPager;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (mViewPagerAdapter == null) {
mViewPagerAdapter = new ViewPagerAdapter(getFragmentManager());
}
mViewPager = (ViewPager) findViewById(R.id.log_pager);
mViewPager.setAdapter(mViewPagerAdapter);
mViewPager.setCurrentItem(0);
}
private class ViewPagerAdapter extends FragmentStatePagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return 8;
}
@Override
public Fragment getItem(int position) {
Fragment f = Fragment1.newInstance(position);
// f.setRetainInstance(true);
f.setHasOptionsMenu(true);
return f;
}
}
}
Code de fragment:
package net.solarnz.apps.fragmentsample;
import Android.app.Fragment;
import Android.os.Bundle;
import Android.view.Menu;
import Android.view.MenuInflater;
public class Fragment1 extends Fragment {
int mNum;
static Fragment newInstance(int num) {
Fragment1 f = new Fragment1();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mNum = getArguments() != null ? getArguments().getInt("num") : 0;
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_list, menu);
}
}
Disposition:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent" >
<Android.support.v4.view.ViewPager
Android:id="@+id/log_pager"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
</LinearLayout>
Menu:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:id="@+id/menu_refresh"
Android:title="Refresh"
Android:icon="@Android:drawable/ic_delete"
Android:showAsAction="ifRoom|withText" />
</menu>
Menu d'action en cours de remplissage: http://i.stack.imgur.com/QFMDd.png
Menu d'action non renseigné: http://i.stack.imgur.com/sH5Pp.png
Vous devriez lire ceci (par xcolw ...)
Après expérimentation, il semble que la cause principale soit invalidateOptionsMenu, car elle est appelée plus d’une fois sans interruption sur le thread principal pour traiter les travaux en attente. Une hypothèse - cela aurait de l'importance si une partie essentielle de la création de menu était différée via un post, laissant la barre d'action en mauvais état jusqu'à son exécution.
Cela peut arriver à quelques endroits qui ne sont pas évidents:
appelant viewPager.setCurrentItem plusieurs fois pour le même élément
appeler viewPager.setCurrentItem dans onCreate de l'activité. setCurrentItem provoque l'invalidation d'un menu d'options, immédiatement suivi de l'invalidation du menu d'options de l'activité.
Solutions que j'ai trouvées pour chaque
Garde l'appel à viewPager.setCurrentItem
if (viewPager.getCurrentItem() != position)
viewPager.setCurrentItem(position);
Reporter l'appel à viewPager.setCurrentItem dans onCreate
public void onCreate(...) {
...
view.post(new Runnable() {
public void run() {
// guarded viewPager.setCurrentItem
}
}
}
Après ces modifications, le menu d’options à l’intérieur du visualiseur semble fonctionner comme prévu. J'espère que quelqu'un pourra nous éclairer davantage.
sourcehttp://code.google.com/p/Android/issues/detail?id=29472
La réponse simple est de ne pas utiliser les menus au sein de fragments dans ViewPager. Si vous devez utiliser des menus dans les fragments, je vous suggère de les charger via la méthode onCreateOptionsMenu dans l'activité parent. De toute évidence, vous devrez être en mesure de déterminer quel menu afficher.
J'ai pu réaliser cela en utilisant la réflexion en classe. Vous devrez également utiliser la méthode invalidateOptionsMenu chaque fois que vous changez de page. Vous aurez besoin d'un OnPageChangeListener pour l'appeler lorsque ViewPager change de page.
J'ai aussi eu le même problème. Dans mon cas, j'ai une activité avec viewpager qui contient deux fragments, chaque fragment gonflant son propre menu d'actions mais le menu d'actions de fragments non affiché.
Afficher le code de l'adaptateur de téléavertisseur
public class ScreensAdapter extends FragmentPagerAdapter {
public TrackerScreensAdapter(Context context, FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return 2;
}
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position){
case 0:
fragment = new Fragment1();
break;
case 1:
fragment = new Fragment2();
break;
}
return fragment;
}
}
Activité sur créer
screensAdapter = new ScreensAdapter(this, getFragmentManager());
viewPager.setAdapter(screensAdapter);
De cette façon, mon viewPager a deux fragments, chaque fragment lance sa propre tâche dans onActivityCreated, obtient des données et dessine sa présentation en fonction des données obtenues. De plus, chaque fragment a onCreateOptionsMenu
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
MyTask task = new MyTask();
task.setTaskListener(this);
task.execute();
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_menu, menu);
}
J'ai passé plusieurs fois à résoudre ce problème et à comprendre pourquoi le menu de fragments ne s'affiche pas. Tout ce dont j'avais besoin, c'est
screenAdapter = new ScreenAdapter(this, getFragmentManager());
viewPager.post(new Runnable() {
public void run() {
viewPager.setAdapter(screenAdapter);
}
});
Commencez par créer une méthode dans la sous-classe de FragmentPagerAdapter pour obtenir le fragment en cours.
public SherlockFragment getFragment() {
return currentFragment;
}
@Override
public void onTabSelected(final Tab tab, FragmentTransaction ft) {
((SherlockFragmentActivity) mContext).invalidateOptionsMenu();
Fragment f = ((SherlockFragmentActivity) mContext)
.getSupportFragmentManager().findFragmentByTag(
makeFragmentName(tab.getPosition()));
currentFragment=(SherlockFragment) f;
}
Maintenant, remplacez les méthodes ci-dessous dans Actvity principale
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (mTabsAdapter.getPositionOfTabSelected() != 0) {
menu.add("Read").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add("Write").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add("Clear").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
menu.add("Factory data reset").setShowAsAction(
MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
return super.onCreateOptionsMenu(menu);
}
Appelez maintenant onOptionItemSelected d'activité en fragment
@Override
public boolean onOptionsItemSelected(MenuItem item) {
mTabsAdapter.getFragment().onOptionsItemSelected(item);
return super.onOptionsItemSelected(item);
}
J'avais ce problème avec les éléments de la barre d'action lorsque j'utilisais HorizontalScrollView pour afficher les onglets, mais j'ai changé pour PagerTitleStrip et le problème a été résolu.
Peut-être que cette information peut aider quelqu'un d'autre.
Dans mon cas, la cause du problème a été attribuée à ce que je considère être un bogue dans FragmentStatePagerAdapter qui appelle Fragment # setMenuVisibility à false et ne parvient pas à le redéfinir correctement lorsqu'il restaure son état.
Solutions de contournement:
Utilisez FragmentPagerAdapter au lieu de FragmentStatePagerAdapter
Si vous devez utiliser FragmentStatePagerAdapter, dans votre sous-classe d'adaptateur, remplacez setPrimaryItem de la manière suivante:
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
//This is a workaround for a bug in FragmentStatePagerAdapter
Fragment currentItem = getItem(position);
if (currentItem != null) {
currentItem.setMenuVisibility(true);
currentItem.setUserVisibleHint(true);
}
}
J'ai résolu un problème très similaire dans lequel les icônes de la barre d'action attribuées par le fragment à l'intérieur d'un ViewPager disparaissaient de onPause (). Ils réapparaîtront lorsque le fragment reviendra à la vue et que l'utilisateur effectuera un balayage à gauche ou à droite, mais pas immédiatement. La solution appelait notifyDataSetChanged () sur le PagerAdapter de la méthode onResume () du fragment.
@Override
public void onResume() {
mPagerAdapter.notifyDataSetChanged();
}