Question

Dans l'application que je développe, je me sers d'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 fragments qui sont initialisés par le ViewPager par défaut (i.e. dans son état initial) ne sont pas d'avoir leurs articles dans le menu peuplé d'éléments d'action. Ce qui est pire est que ce problème ne se produit que par intermittence. Si je Feuilletez le ViewPager assez pour que les fragments sont contraints de réinitialiser eux-mêmes, quand je balayez vers le dos, le menu renseigne correctement.

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;
        }
    }
}

Fragment de code:

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);
    }

}

Mise en page:

<?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 étant rempli: http://i.stack.imgur.com/QFMDd.png

Menu d'action ne sont pas renseignés: http://i.stack.imgur.com/sH5Pp.png

Était-ce utile?

La solution

Vous devriez lire (par xcolw ...)

Par l'expérimentation, il semble que la cause racine est invalidateOptionsMenu obtenir appelé plus d'un sans interruption sur le thread principal de processus mis en attente des emplois. Une estimation - ce serait grave si une partie critique de la création de menu a été reporté par un poste, laissant la barre d'action en mauvais état jusqu'à ce qu'il fonctionne.

Il y a quelques endroits cela peut arriver qui ne sont pas évidentes:

  1. appelant viewPager.setCurrentItem plusieurs fois pour le même élément

  2. appelant viewPager.setCurrentItem à onCreate de l'activité. setCurrentItem provoque une invalidate de menu d'options, qui est immédiatement suivie par la invalidate de menu d'options de l'activité

Je Contournements ai trouvé pour chaque

  1. Garde l'appel à viewPager.setCurrentItem

    if (viewPager.getCurrentItem() != position)
        viewPager.setCurrentItem(position);
    
  2. Différer l'appel à viewPager.setCurrentItem dans onCreate

    public void onCreate(...) {
        ...
        view.post(new Runnable() {
            public void run() {
                // guarded viewPager.setCurrentItem
            }
        }
    }
    

Après ces options changements menu à l'intérieur du téléavertisseur vue semble fonctionner comme prévu. J'espère que quelqu'un peut jeter plus de lumière dans tout cela.

source http: // code. google.com/p/android/issues/detail?id=29472

Autres conseils

La réponse simple est de ne pas utiliser les menus des fragments du ViewPager. Si vous avez besoin d'utiliser des menus dans les fragments, ce que je propose est le chargement de menu par la méthode onCreateOptionsMenu dans l'activité mère. Il est évident que vous devez être en mesure de déterminer quel menu à afficher.

J'ai pu y parvenir en utilisant la réflexion de la classe. Vous devrez également utiliser la méthode invalidateOptionsMenu chaque fois que vous changez de page. Vous aurez besoin d'un OnPageChangeListener appeler quand le ViewPager change pages.

J'ai aussi eu même question. Dans mon cas, j'ai une activité avec viewpager qui contient deux fragments, chaque fragment gonfler son propre menu d'action mais le menu actions fragment non représentées.

Voir le code de l'adaptateur pager

 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 create

    screensAdapter = new ScreensAdapter(this, getFragmentManager());
    viewPager.setAdapter(screensAdapter);

De cette façon, mon viewPager a deux fragments, chaque fragment feu sa propre tâche onActivityCreated, d'obtenir des données et d'en tirer sa mise en page à partir des données obtenues. Aussi 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);
}

Nous avons passé plusieurs fois pour résoudre ce problème et comprendre pourquoi le menu fragment montre pas. Tout ce que j'avais besoin est

    screenAdapter = new ScreenAdapter(this, getFragmentManager());
    viewPager.post(new Runnable() {
        public void run() {
            viewPager.setAdapter(screenAdapter);
        }
    });

Tout d'abord créer une méthode dans la sous-classe de FragmentPagerAdapter pour obtenir le fragment courant

    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;
 }

outrepasser ci-dessous dans les méthodes principales actvity

@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);
}

Maintenant, appelez le onOptionItemSelected de l'activité à fragment

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    mTabsAdapter.getFragment().onOptionsItemSelected(item);
    return super.onOptionsItemSelected(item);
}

Je résolu une question très similaire dans lequel les icônes de la barre d'action assignés par l'intérieur du fragment d'un ViewPager disparaissaient OnPause (). Ils réapparaissent lorsque le fragment est revenu en vue et l'utilisateur gauche ou à droite glissée dans le terminal, mais pas immédiatement. La solution a été appelle notifyDataSetChanged () sur la PagerAdapter dans le procédé onResume () du fragment.

@Override
public void onResume() {
    mPagerAdapter.notifyDataSetChanged();
}

J'avais ce problème avec la barre d'action Articles alors que 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, je trace la cause profonde du problème à ce que je crois est un bogue dans FragmentStatePagerAdapter qui appelle Fragment # setMenuVisibility false et de ne pas correctement le remettre à vrai quand il restaure l'état est tout.

Solutions de contournement:

  1. Utilisez FragmentPagerAdapter au lieu de FragmentStatePagerAdapter

  2. Si vous devez utiliser FragmentStatePagerAdapter, dans votre override de l'adaptateur de setPrimaryItem comme ceci:

    @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);
        }
    }
    
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top