Domanda

Nell'applicazione sto sviluppando sto usando un mirino con frammenti e ogni frammento costruisce il proprio menu indipendentemente da tutti gli altri frammenti del mirino.

Il problema è che a volte i frammenti inizializzati dal ViewPager per impostazione predefinita (cioè nello stato iniziale) non stanno facendo popolare i loro elementi nel menu degli elementi di azione. Quel che è peggio è che questo problema si verifica solo a intermittenza. Se scorrerò abbastanza attraverso il mirino in modo che i frammenti siano costretti a rein-iniziale, quando scorrerò indietro, il menu popola correttamente.

Codice di attività:

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

Codice frammento:

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

}

Disposizione:

<?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>

Menù:

<?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 Azione popolato:http://i.stack.imgur.com/qfmdd.png

Il menu di azione non è stato popolato:http://i.stack.imgur.com/sh5pp.png

È stato utile?

Soluzione

Dovresti leggere questo (di XColw ...)

Attraverso la sperimentazione sembra che la causa principale sia invalidati che vengano chiamati più di uno senza una pausa sul thread principale per elaborare i lavori in coda. Un'ipotesi: ciò sarebbe importante se una parte critica della creazione di menu fosse differita tramite un post, lasciando la barra di azione in cattivo stato fino a quando non funziona.

Ci sono alcuni punti che possono accadere che non sono ovvi:

  1. Calling ViewPager.SetCurrentItem più volte per lo stesso elemento

  2. Chiamare ViewPager.setCurrentItem in oncreate dell'attività. SetCurrentItem causa invalidare un menu di opzione, che è immediatamente seguito dal menu Opzione dell'attività invalida

Soluzioni alternative che ho trovato per ciascuno

  1. Guarda la chiamata a ViewPager.SetCurrentItem

    if (viewPager.getCurrentItem() != position)
        viewPager.setCurrentItem(position);
    
  2. Rimuovere la chiamata a ViewPager.SetCurrentItem in onCreate

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

Dopo queste modifiche, il menu Opzioni all'interno del Pager Visualizza sembra funzionare come previsto. Spero che qualcuno possa far luce in questo.

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

Altri suggerimenti

La semplice risposta è non usare menu all'interno di frammenti nel Viewpager. Se è necessario utilizzare i menu all'interno dei frammenti, ciò che suggerisco è caricare il menu attraverso il metodo OnCreateOptionsMenu nell'attività dei genitori. Ovviamente dovrai essere in grado di determinare quale menu mostrare.

Sono stato in grado di raggiungere questo obiettivo usando la riflessione della classe. Dovrai anche utilizzare il metodo InvalidateOptionsMenu ogni volta che cambieranno pagine. Avrai bisogno di un onpagechangelistener per chiamarlo quando il mirino cambia pagine.

Ho anche avuto lo stesso problema. Nel mio caso ho un'attività con ViewPager che contiene due frammenti, ogni frammento gonfia il suo menu di azione ma il menu delle azioni di frammento non mostrato.

Visualizza il codice dell'adattatore del cercapersone

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

}

Attività su creazione

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

In questo modo il mio Viewpager ha due frammenti, ogni frammento incanta il proprio compito nella creazione di onActivity, ottieni dati e disegna il suo layout in base ai dati ottenuti. Anche ogni frammento ha 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);
}

Ho trascorso molte volte per risolvere questo problema e capire perché il menu dei frammenti non si mostra. Tutto quello che mi è stato bisogno è

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

Crea innanzitutto un metodo nella classe secondaria di frammentpageradapter per ottenere il frammento attuale

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

Ora sopravvaluta di seguito i metodi nella principale attività

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

Ora chiama l'OptionItemSecked da Activity to Fragment

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

Ho risolto un problema molto simile in cui le icone della barra d'azione assegnate dal frammento all'interno di un mirino stavano scomparendo OnPause (). Avrebbero riapparso quando il frammento tornò in vista e l'utente scorreva a sinistra o a destra, ma non immediatamente. La soluzione stava chiamando NotifyDataSEtchanged () sul metodo Pageradapter nel metodo OnResume () del frammento.

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

Stavo avendo questo problema con gli elementi della barra d'azione mentre stavo usando HorizontalsCrollView per mostrare le schede ma ho cambiato in PagertitLestrip E il problema è stato risolto.

Forse queste informazioni possono aiutare qualcun altro.

Nel mio caso ho rintracciato la causa principale del problema a quello che credo sia un bug in frammentstatepageradapter che sta chiamando Frammento#setmenuvisibilità a falsi e non riuscire a riposizionarlo correttamente su True quando ripristina lo stato.

Soluzioni alternative:

  1. Usa frammentpageradapter anziché frammentstatepageradapter

  2. Se è necessario utilizzare FragmentStatePageradapter, nella sottoclasse dell'adattatore di override setprimaryItem come così:

    @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);
        }
    }
    
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top