Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Androide; Fragmentos se superponen al cambiar las pestañas

Primero, gracias a todos por esta gran comunidad.

Estoy intentando seguir el código de muestra de las demostraciones de la ayuda para poner una interfaz tabbed-fragment.

Nivel superior, estoy intentando implementar dos pestañas, asociar un solo fragmento con cada pestaña y hacer que aparezcan los fragmentos cuando cada pestaña se seleccione en consecuencia.

Actualmente, tengo dos problemas (pero estoy seguro de que están relacionados …)

1) Los fragmentos de cada pestaña se superponen entre sí. Esto podría estar relacionado con fragmento indebido adjuntar / separar.

2) Un tercer fragmento de misterio se está creando en algún lugar y se superponen los otros fragmentos, así


En el emulador (y en un dispositivo físico), puede ver que hay dos fragmentos que se superponen cuando se selecciona una de las pestañas

Cuando se selecciona tab1, el fragmento 1 y el fragmento desconocido se superponen.

Cuando se selecciona tab2, el fragmento 1 y el fragmento 2 se superponen.


Enlaces a las capturas de pantalla (no hay suficiente reputación para subir fotos …)

(Tab1 superposición) http://s8.postimg.org/kv81yz745/tab1_overlapping.png

(Tab2 superposición) http://s8.postimg.org/3tf7wvs91/tab2_overlapping.png


Aquí, he separado el texto en cada fragmento para fines de demostración / claridad.

Los enlaces a estas capturas de pantalla están abajo en mi comentario / respuesta. (No hay suficiente reputación para subir más de 2 enlaces …)

Disposición de la actividad (fragment_tabs.xml)

<TabHost xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/tabhost" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TabWidget android:id="@android:id/tabs" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0"/> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="0dp" android:layout_height="0dp" android:layout_weight="0"/> <FrameLayout android:id="@+id/realtabcontent" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> </LinearLayout> </TabHost> 

Código fuente

 public class TabbedInfoHome extends SherlockFragmentActivity { TabHost mTabHost; TabManager mTabManager; static String tag1name = "simple1"; static String tag2name = "simple2"; static String tab1string = "You are looking at fragment 1"; static String tab2string = "You are looking at fragment 2"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fragment_tabs); if (savedInstanceState == null) { // Do first time initialization -- add initial fragment. Fragment frag1 = CountingFragment.newInstance(tab1string); Fragment frag2 = CountingFragment.newInstance(tab2string); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.add(R.id.realtabcontent, frag1, tag1name); ft.add(R.id.realtabcontent, frag2, tag2name); ft.commit(); } else { mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); } mTabHost = (TabHost)findViewById(android.R.id.tabhost); mTabHost.setup(); mTabManager = new TabManager(this, mTabHost, R.id.realtabcontent); mTabManager.addTab(mTabHost.newTabSpec(tag1name) .setIndicator(tag1name), TabbedInfoHome.CountingFragment.class, null); mTabManager.addTab(mTabHost.newTabSpec(tag2name) .setIndicator(tag2name), TabbedInfoHome.CountingFragment.class, null); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString("tab", mTabHost.getCurrentTabTag()); } public static class CountingFragment extends SherlockFragment { String displayString; String FRAGMENT_TAG = this.getClass().getSimpleName(); /** * Create a new instance of CountingFragment, providing "num" * as an argument. */ static CountingFragment newInstance(String toDisplay) { CountingFragment f = new CountingFragment(); Bundle args = new Bundle(); args.putString("string", toDisplay); f.setArguments(args); return f; } /* When creating, retrieve this instance's number from its arguments. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); displayString = getArguments() != null ? getArguments().getString("string") : "no string was passed in!"; } /* The Fragment's UI is just a simple text view showing its * instance number. */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.hello_world, container, false); View tv = v.findViewById(R.id.text); boolean separateStrings = false; /* the overlapping is hard to decipher, so * lets illustrate how both fragments are appearing */ if(separateStrings) { String temp; /* b/c I only created TWO instances of the CountingFragments object, * there should only be TWO "displayStrings" to consider... */ if( (displayString.compareTo(tab1string) == 0) ) { /* user clicked tab 1 */ temp = "\n\n\n\n" + displayString; } else if( (displayString.compareTo(tab2string) == 0) ) { /* user clicked tab2 */ temp = "\n\n\n\n\n\n\n" + displayString; } else { /* unknown CountingFragment instance */ temp = "What am I doing here..??? "; } ((TextView)tv).setText(temp); } else { /* normal case of the fragment being shown; (but they overlap!) */ ((TextView)tv).setText(displayString); } return v; } } /** * This is a helper class that implements a generic mechanism for * associating fragments with the tabs in a tab host. It relies on a * trick. Normally a tab host has a simple API for supplying a View or * Intent that each tab will show. This is not sufficient for switching * between fragments. So instead we make the content part of the tab host * 0dp high (it is not shown) and the TabManager supplies its own dummy * view to show as the tab content. It listens to changes in tabs, and takes * care of switch to the correct fragment shown in a separate content area * whenever the selected tab changes. */ public static class TabManager implements TabHost.OnTabChangeListener { private final FragmentActivity mActivity; private final TabHost mTabHost; private final int mContainerId; private final HashMap<String, TabInfo> mTabs = new HashMap<String, TabInfo>(); TabInfo mLastTab; static final class TabInfo { private final String tag; private final Class<?> clss; private final Bundle args; private Fragment fragment; TabInfo(String _tag, Class<?> _class, Bundle _args) { tag = _tag; clss = _class; args = _args; } } static class DummyTabFactory implements TabHost.TabContentFactory { private final Context mContext; public DummyTabFactory(Context context) { mContext = context; } @Override public View createTabContent(String tag) { View v = new View(mContext); v.setMinimumWidth(0); v.setMinimumHeight(0); return v; } } public TabManager(FragmentActivity activity, TabHost tabHost, int containerId) { mActivity = activity; mTabHost = tabHost; mContainerId = containerId; mTabHost.setOnTabChangedListener(this); } public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) { tabSpec.setContent(new DummyTabFactory(mActivity)); String tag = tabSpec.getTag(); TabInfo info = new TabInfo(tag, clss, args); // Check to see if we already have a fragment for this tab, probably // from a previously saved state. If so, deactivate it, because our // initial state is that a tab isn't shown. info.fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag); if (info.fragment != null ) { // && !info.fragment.isDetached()) { Log.d("addingTab", "we already have a fragment for this tab. tabInfo.fragment.id: " + info.fragment.getId()); FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction(); ft.detach(info.fragment); ft.commit(); mActivity.getSupportFragmentManager().executePendingTransactions(); } // associate the tabSpec tag with a particular TabInfo object mTabs.put(tag, info); mTabHost.addTab(tabSpec); } @Override public void onTabChanged(String tabId) { TabInfo newTab = mTabs.get(tabId); if (mLastTab != newTab) { FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction(); if (mLastTab != null) { if (mLastTab.fragment != null) { ft.detach(mLastTab.fragment); } } if (newTab != null) { if (newTab.fragment == null) { newTab.fragment = Fragment.instantiate(mActivity, newTab.clss.getName(), newTab.args); ft.add(mContainerId, newTab.fragment, newTab.tag); } else { ft.attach(newTab.fragment); } } mLastTab = newTab; ft.commit(); mActivity.getSupportFragmentManager().executePendingTransactions(); } } } 

4 Solutions collect form web for “Androide; Fragmentos se superponen al cambiar las pestañas”

Después de días de experimentación, conseguí esto funcionar correctamente.

En el método onCreate de mi clase TabbedInfoHome , al crear nuevas instancias de los fragmentos por primera vez ( savedInstanceState == null ), savedInstanceState == null la ejecución de transacciones pendientes en FragmentTransaction usando this.getSupportFragmentManager().executePendingTransactions()

Esta explicación se basa un poco en la documentación que se encuentra en: http://developer.android.com/reference/android/app/FragmentManager.html#executePendingTransactions ()

Después de que FragmentTransaction se compromete con FragmentTransaction.commit() , está programado para ser ejecutado asincrónicamente > en el subproceso principal del proceso. Si desea ejecutar inmediatamente cualquier operación pendiente, puede llamar a esta función.

Una pregunta pendiente que todavía tengo es cómo la falta de ejecución inmediata de transacciones pendientes se manifiesta en el comportamiento visto en la pregunta original.

En otras palabras … ¿cómo la FALTA de this.getSupportFragmentManager().executePendingTransactions() explica los fragmentos que se solapan?


El código editado está debajo; Una línea adicional

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fragment_tabs); if (savedInstanceState == null) { // Do first time initialization -- add initial fragment. Fragment frag1 = CountingFragment.newInstance(tab1string); Fragment frag2 = CountingFragment.newInstance(tab2string); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.add(R.id.realtabcontent, frag1, tag1name); ft.add(R.id.realtabcontent, frag2, tag2name); ft.commit(); this.getSupportFragmentManager().executePendingTransactions(); // <----- This is the key } else { mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); } mTabHost = (TabHost)findViewById(android.R.id.tabhost); mTabHost.setup(); mTabManager = new TabManager(this, mTabHost, R.id.realtabcontent); mTabManager.addTab(mTabHost.newTabSpec(tag1name) .setIndicator(tag1name), TabbedInfoHome.CountingFragment.class, null); mTabManager.addTab(mTabHost.newTabSpec(tag2name) .setIndicator(tag2name), TabbedInfoHome.CountingFragment.class, null); } 

También obtengo este problema en Nexus 5.

Creo que tenemos la otra solución mejor que eliminar la solución mediante el uso de esta manera.

En all your xml files , debe definir el color de fondo para él, se solucionará el problema:

Añada este android:background="@android:color/black" a la etiqueta Ver que definió.

Estoy tratando de hacer lo mismo y esta mañana tuve los mismos problemas. Los resuelvo con la información que recibí de otra pregunta similar.

En mi caso no estoy usando SherlockActionBar, pero la solución debe trabajar para usted.

En la parte donde compruebas si hay un fragmento inflado para la pestaña que utilizo:

  // in order to avoid fragment Fragment prevFragment; FragmentManager fm = mActivity.getFragmentManager(); prevFragment = fm.findFragmentByTag(mTag); if (prevFragment != null) { mFragment = prevFragment; } // \previous Fragment management 

Supongo que esto debe funcionar para usted si lo adecuado a los comandos SherlockActionBar (cos donde he leído la información que se utiliza con SherlockActionBar).

¡Espero que funcione para ti!

Ya muchas soluciones se dan, pero no pude resolver el problema, debido a un error tonto. El problema era, en el SDK nuevo por defecto Las actividades se extienden a "ActionbarActivity" en el cual el fragmento consigue creado pero se solapan. Para resolverlo, amplía su actividad a "FragmentActivity"

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.