android - Cómo resolver viewpager: el hijo especificado ya tiene un padre. Debe llamar primero a removeView() en el padre del niño
google-maps android-viewpager (7)
En mi proyecto estoy usando viewpager con tres pestañas llamadas History
, Main
, Map
. La actividad principal contiene temporizador, cronómetro, etc. Mapa muestra el mapa de google. y en la historia en este momento estoy usando solo Textview simple.
Dirección del flujo de Viewpager: Historial - Principal - Mapa
Configuré Main como el elemento actual (Por defecto, la visualización de la etiqueta principal). Ahora, cuando estoy deslizando desde Main > Map and Map > Main, funciona perfectamente. pero al deslizar desde Main > History no hay ningún error, pero retrocede desde History a Main ( History > Main ) eclipse, dame un error como:
E/AndroidRuntime( 533): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child''s parent first.
Y, para su información, utilizo la intent into Map Activity
. Consulte el código a continuación. Deseo saber cómo puedo resolver mi problema.
Clase ViewPager:
@Override
public Fragment getItem(int position) {
// return SwipeyTabFragment.newInstance(TITLES[position]);
Fragment f = new Fragment();
switch (position) {
case 0:
f = History.newInstance(position);
break;
case 1:
f = Main.newInstance(position);
break;
case 2:
f = Map.newInstance(position);
break;
}
return f;
}
Clase de historia:
public class History extends Fragment {
public static Fragment newInstance(int position) {
History f = new History();
Bundle args = new Bundle();
args.putInt("title", position);
f.setArguments(args);
return f;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.history, null);
( (TextView) root.findViewById(R.id.text)).setText("Hello");
return root;
}
}
Clase principal :
public class Main extends Fragment implements GPSCallback {
......
public static Fragment newInstance(int position) {
Main f = new Main();
Bundle args = new Bundle();
args.putInt("title", position);
f.setArguments(args);
return f;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final ViewGroup root = (ViewGroup) inflater
.inflate(R.layout.main, null);
.......
return root;
}
........
}
Map.class:
public class Map extends Fragment {
private static final String KEY_STATE_BUNDLE = "localActivityManagerState";
private LocalActivityManager mLocalActivityManager;
protected LocalActivityManager getLocalActivityManager() {
return mLocalActivityManager;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle state = null;
if (savedInstanceState != null) {
state = savedInstanceState.getBundle(KEY_STATE_BUNDLE);
}
mLocalActivityManager = new LocalActivityManager(getActivity(), true);
mLocalActivityManager.dispatchCreate(state);
}
public static Fragment newInstance(int position) {
Map f = new Map();
Bundle args = new Bundle();
args.putInt("title", position);
f.setArguments(args);
return f;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Intent i = new Intent(getActivity(), MapViewActivity.class);
// Intent i = new Intent(getActivity(), hellogooglemap.class);
Window w = mLocalActivityManager.startActivity("tag", i);
View currentView=w.getDecorView();
currentView.setVisibility(View.VISIBLE);
currentView.setFocusableInTouchMode(true);
((ViewGroup) currentView).setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
return currentView;
/*ViewGroup root = (ViewGroup) inflater.inflate(R.layout.history, null);
( (TextView) root.findViewById(R.id.text)).setText("Hello");
return root;*/
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBundle(KEY_STATE_BUNDLE,
mLocalActivityManager.saveInstanceState());
}
@Override
public void onResume() {
super.onResume();
mLocalActivityManager.dispatchResume();
}
@Override
public void onPause() {
super.onPause();
mLocalActivityManager.dispatchPause(getActivity().isFinishing());
}
@Override
public void onStop() {
super.onStop();
mLocalActivityManager.dispatchStop();
}
@Override
public void onDestroy() {
super.onDestroy();
mLocalActivityManager.dispatchDestroy(getActivity().isFinishing());
}
}
Logcat:
E/AndroidRuntime( 533): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child''s parent first.
E/AndroidRuntime( 533): at android.view.ViewGroup.addViewInner(ViewGroup.java:1976)
E/AndroidRuntime( 533): at android.view.ViewGroup.addView(ViewGroup.java:1871)
E/AndroidRuntime( 533): at android.view.ViewGroup.addView(ViewGroup.java:1828)
E/AndroidRuntime( 533): at android.view.ViewGroup.addView(ViewGroup.java:1808)
E/AndroidRuntime( 533): at android.support.v4.app.NoSaveStateFrameLayout.wrap(NoSaveStateFrameLayout.java:40)
E/AndroidRuntime( 533): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:874)
E/AndroidRuntime( 533): at android.support.v4.app.FragmentManagerImpl.attachFragment(FragmentManager.java:1240)
E/AndroidRuntime( 533): at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:612)
E/AndroidRuntime( 533): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1416)
E/AndroidRuntime( 533): at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:431)
E/AndroidRuntime( 533): at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:139)
E/AndroidRuntime( 533): at android.support.v4.view.ViewPager.populate(ViewPager.java:804)
E/AndroidRuntime( 533): at android.support.v4.view.ViewPager.completeScroll(ViewPager.java:1280)
E/AndroidRuntime( 533): at android.support.v4.view.ViewPager.computeScroll(ViewPager.java:1176)
E/AndroidRuntime( 533): at android.view.ViewGroup.drawChild(ViewGroup.java:1562)
E/AndroidRuntime( 533): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
E/AndroidRuntime( 533): at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
E/AndroidRuntime( 533): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
E/AndroidRuntime( 533): at android.view.View.draw(View.java:6883)
E/AndroidRuntime( 533): at android.widget.FrameLayout.draw(FrameLayout.java:357)
E/AndroidRuntime( 533): at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
E/AndroidRuntime( 533): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
E/AndroidRuntime( 533): at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
E/AndroidRuntime( 533): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
E/AndroidRuntime( 533): at android.view.View.draw(View.java:6883)
E/AndroidRuntime( 533): at android.widget.FrameLayout.draw(FrameLayout.java:357)
E/AndroidRuntime( 533): at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1862)
E/AndroidRuntime( 533): at android.view.ViewRoot.draw(ViewRoot.java:1522)
E/AndroidRuntime( 533): at android.view.ViewRoot.performTraversals(ViewRoot.java:1258)
E/AndroidRuntime( 533): at android.view.ViewRoot.handleMessage(ViewRoot.java:1859)
E/AndroidRuntime( 533): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 533): at android.os.Looper.loop(Looper.java:130)
E/AndroidRuntime( 533): at android.app.ActivityThread.main(ActivityThread.java:3683)
E/AndroidRuntime( 533): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 533): at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime( 533): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
E/AndroidRuntime( 533): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
E/AndroidRuntime( 533): at dalvik.system.NativeStart.main(Native Method)
W/ActivityManager( 68): Force finishing activity com.android.gps/.viewpager.SwipeyTabsSampleActivity
W/ActivityManager( 68): Activity pause timeout for HistoryRecord{40716740 com.android.gps/.viewpager.SwipeyTabsSampleActivity}
Gracias.
EDITAR:
Sin intención en la actividad del Mapa funciona pwrfect. Quiero decir cuando estoy usando lo mismo que el historial en el mapa no hay ningún error.
// si la vista secundaria que se va a agregar ya está vinculada a un elemento primario, elimine el elemento secundario del elemento primario y luego vuelva a agregarlo al contenedor.
if (v.getParent() != null) {
((ViewGroup) v.getParent()).removeView(v);
}
container.addView(v);
Aquí está mi solución (utilizada en cada uno de los fragmentos), que permite suavidad y evita problemas de memoria:
...
private LayoutInflater mInflater;
private WeakReference<View> mRootView = null;
...
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState)
{
if (inflater != null)
mInflater = inflater;
else
mInflater = LayoutInflater.from(getActivity());
View rootView = mRootView == null ? null : mRootView.get();
if (rootView != null)
{
final ViewParent parent = rootView.getParent();
if (parent != null && parent instanceof ViewGroup)
((ViewGroup) parent).removeView(rootView);
}
else
{
rootView = mInflater.inflate(R.layout.fragment_test, null, false);
mRootView = new WeakReference<View>(rootView);
}
return rootView;
}
En primer lugar, la respuesta de RB Patel para insertar el código (que se muestra a continuación) funcionó a las mil maravillas, pero a medida que leía sobre esta característica, me di cuenta de que era una optimización potencial y que no era la solución al problema.
mViewPager.setOffscreenPageLimit(3);
El sitio para desarrolladores de Android dice lo siguiente sobre este método:
setOffscreenPageLimit (int limit): establezca el número de páginas que se deben conservar en cualquier lado de la página actual en la jerarquía de vistas en un estado inactivo.
Parece que esto solo establece un límite en el número de páginas almacenadas en la memoria caché a la derecha o izquierda de la página actual. En mi caso, esto fue solo una ayuda de banda para el problema, sí, el error se detuvo y las cosas funcionó sin problemas, pero todavía tenía un código malo acechando en mi programa que simplemente no se ejecuta. Creo que este método fue pensado como una optimización y no como una solución real para el error.
Me encontré con este problema al intentar sobrecargar el método instantiateItem () en una clase personalizada que amplía PagerAdapter. Mi error se produjo después de que volvería a navegar a una pestaña / página que había visitado / instanciado previamente.
Soy nuevo en Android pero haré todo lo posible para explicar mi solución. La línea que arrojó este error fue la siguiente:
v.addView(child);
Si entendí esto correctamente, se estaba ahogando porque el niño ya había sido instanciado previamente y se le asignó un padre.
Cuando navegaba de regreso a una vista / página previamente visitada, intentaba agregar una vista que ya tenía una vista de diseño principal a una nueva Distribución, de ahí el error.
Solución: Acabo de verificar si la vista secundaria que estaba intentando mostrar (instancia) ya se ha instanciado en otro lugar al ver si tenía una vista principal configurada. Si la vista hija ya se había creado, entonces solo usé el padre de la vista secundaria en lugar de crear un nuevo Diseño.
Aquí está mi código (me disculpo si ofende a algún experto):
@Override
public Object instantiateItem(View container, int position) {
LinearLayout v = new LinearLayout(mContext);
//the view being loaded (unless it already was then we have to handle it)
View child = mViews.get(position);
//If the child view was loaded already then it will have a parent view it belongs to
//We return the parent view instead of adding the child to the LinearLayout we just created and returning that new layout.
if(child.getParent() != null) {
View parent = (View) child.getParent();
((ViewPager) container).addView(parent);
return parent;
}
//first time instantiating a child view/page
v.addView(child);
// These lines execute the first time a given page is instantiated
((ViewPager) container).addView(v);
return v;
}
También me he enfrentado a este problema.
Puede resolverlo simplemente agregue una sola línea mViewPager.setOffscreenPageLimit(3);
public class SwipeyTabsSampleActivity extends FragmentActivity {
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mViewPager = (ViewPager) findViewById(R.id.viewpager);
mTabs = (SwipeyTabs) findViewById(R.id.swipeytabs);
SwipeyTabsPagerAdapter adapter = new SwipeyTabsPagerAdapter(this,
getSupportFragmentManager());
mViewPager.setAdapter(adapter);
mViewPager.setOffscreenPageLimit(3); <------ Add this one
}
}
Buena suerte.
Tuve el mismo problema cuando utilicé
View res = inflater.inflate(R.layout.fragment_guide_search, container);
dentro de Fragment.onCreateView (...
Debes llamar
View res = inflater.inflate(R.layout.fragment_guide_search, container, false);
o
View res = inflater.inflate(R.layout.fragment_guide_search, null);
si está trabajando con FragmentPagerAdapter, simplemente use el método destroyItem dentro de FragmentPagerAdapter.
@Override
public void destroyItem(ViewGroup container, int position, Object object)
{
FragmentTransaction ft=fm.beginTransaction();
ft.remove((Fragment) object);
ft.commit();
}
setOffscreenPageLimit (int limit) consume más memoria y en algunos casos no funciona a la perfección. su estado de retención en cualquier lado ver descripción. setOffscreenPageLimit (int limit): establezca el número de páginas que se deben conservar en cualquier lado de la página actual en la jerarquía de vistas en un estado inactivo.
@Override
public Object instantiateItem(View arg0, int arg1) {
Log.d("instantiateItem", ""+arg0+" "+arg1);
try {
if(mListViews.get(arg1).getParent()==null)
((ViewPager) arg0).addView(mListViews.get(arg1), 0);
else{
// I am new to android, it is strange that the view to be added is already bound to a parent
// Through trials and error I solve this problem with the following codes
// Add that the element of mlistviews is listview in pagerview;
((ViewGroup)mListViews.get(arg1).getParent()).removeView(mListViews.get(arg1));
((ViewPager) arg0).addView(mListViews.get(arg1), 0);
}
} catch (Exception e) {
Log.d("parent=", ""+mListViews.get(arg1).getParent());
e.printStackTrace();
}
return mListViews.get(arg1);
}