Pregunta

En la aplicación que estoy desarrollando estoy usando un ViewPager con fragmentos y cada fragmento construye su propio menú independientemente de todos los otros fragmentos en el ViewPager.

El problema es que a veces los fragmentos que el ViewPager inicializa de forma predeterminada (es decir, en su estado inicial) no tienen sus elementos poblados en el menú de elementos de acción. Lo que es peor es que este problema solo ocurre de manera intermitente. Si deslizo a través del ViewPager lo suficiente como para que los fragmentos se vean obligados a reinicializarlos, cuando retrocedo, el menú se llena correctamente.

Código de actividad:

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

Código de fragmento:

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

}

Diseño:

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

Menú de acción que se está poblando:http://i.stack.imgur.com/qfmdd.png

El menú de acción no está poblado:http://i.stack.imgur.com/sh5pp.png

¿Fue útil?

Solución

Deberías leer esto (por xcolw ...)

A través de la experimentación, parece que la causa raíz es invalidación, se llama a más de uno sin un descanso en el hilo principal para procesar los trabajos en cola. Una suposición: esto importaría si alguna parte crítica de la creación del menú fuera diferida a través de una publicación, dejando la barra de acción en mal estado hasta que se ejecute.

Hay algunos puntos que esto puede suceder que no son obvios:

  1. Llamar a ViewPager.setCurrentItem varias veces para el mismo elemento

  2. Llamar a la vista. setCurrentItem hace que un menú de opción invalide, que es seguido inmediatamente por el menú de opciones de la actividad invalidar

Soluciones que he encontrado para cada

  1. Proteger la llamada a viewPager.setCurrentItem

    if (viewPager.getCurrentItem() != position)
        viewPager.setCurrentItem(position);
    
  2. Diferir la llamada a ViewPager.SetCurrentItem en OnCreate

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

Después de estos cambios, el menú de opciones dentro del buscapersonas View parece funcionar como se esperaba. Espero que alguien pueda arrojar más luz sobre esto.

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

Otros consejos

La respuesta simple es no usar menús dentro de fragmentos en el ViewPager. Si necesita usar menús dentro de los fragmentos, lo que sugiero es cargar el menú a través del método OnCreateeCtionsMenu en la actividad principal. Obviamente, deberá poder determinar qué menú mostrar.

Pude lograr esto usando la reflexión de clase. También deberá utilizar el método InvalidateOptionsMenu cada vez que cambie las páginas. Necesitará un OnpageChangeListener para llamar a esto cuando el ViewPager cambie las páginas.

También tuve el mismo problema. En mi caso, tengo una actividad con ViewPager que contiene dos fragmentos, cada fragmento inflan su propio menú de acción pero el menú de acciones de fragmentos no se muestra.

Ver código adaptador de buscapersonas

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

}

Actividad en Crear

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

De esta manera, mi vista tiene dos fragmentos, cada fragmento dispara su propia tarea en OnactivityCreated, obtiene datos y dibuja su diseño en función de los datos obtenidos. Además, cada fragmento tiene información

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

Pasé muchas veces para resolver este problema y descubra por qué no se muestra el menú de fragmentos. Todo lo que necesitaba es

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

Primero cree un método en la subcase de FragmentPagerAdapter para obtener el fragmento actual

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

Ahora anule los métodos a continuación en la actitud principal

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

Ahora llame al OnOptionItemeled de actividad a fragmento

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

Resolví un problema muy similar en el que los íconos de la barra de acción asignados por el fragmento dentro de un vista estaban desapareciendo enpause (). Volverían a aparecer cuando el fragmento volviera a la vista y el usuario deslizó hacia la izquierda o hacia la derecha, pero no de inmediato. La solución estaba llamando a NotifyDataSetchanged () en el PagerAdapter en el método OnResume () del fragmento.

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

Estaba teniendo este problema con los elementos de la barra de acción mientras usaba Horizontalscrollview Para mostrar las pestañas pero cambié a Pagertitlestra y el problema se resolvió.

Quizás esta información pueda ayudar a alguien más.

En mi caso, trazé la causa raíz del problema a lo que creo que es un error en FragmentStatePagerAdapter que está llamando Fragmento#setmenuvisibility a falso y no lo establece correctamente en verdadero cuando restaura su estado.

Solución:

  1. Use FragmentPagerAdapter en lugar de FragmentStatePagerAdapter

  2. Si debe usar FragmentStatePagerAdapter, en su adaptador subclase anular setPrimaryItem como así:

    @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);
        }
    }
    
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top