2012-11-26 14 views
24

Nel mio progetto sto usando viewpager con tre schede denominate History, Main, Map. L'attività principale contiene timer, cronometro, ecc. Mappa visualizza la mappa di google. e in Storia in questo momento sto usando solo semplice Textview.Come risolvere per viewpager: il figlio specificato ha già un genitore. È necessario chiamare removeView() sul genitore del figlio prima

direzione del flusso Viewpager: Storia - principale - Mappa

ho impostato il Main come l'elemento corrente (Bydefault tag display principale) .Ora quando sono scorri da principale>Mappa e Mappa>Principale funziona perfettamente. ma quando scorri da principale>Storia non v'è alcun errore, ma il ritorno indietro da Storia a principale (Storia>principale) eclissare darmi errore del tipo:

E/AndroidRuntime( 533): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. 

E FYI Sto usando intent into Map Activity. Si prega di controllare sotto il codice. Per favore fatemi sapere come può risolvere il mio problema.

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

    } 

History.class:

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

} 

Main.class:

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} 

Grazie.

EDIT:

Senza intenti in attività Mappa funziona pwrfect.I significa quando sto usando lo stesso come la storia in mappa non c'è alcun errore.

risposta

27

Ho anche affrontato questo problema.

È possibile risolverlo basta aggiungere un'unica linea 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 
} 

} 

Good Luck.

35

Ho avuto lo stesso problema quando ho usato

View res = inflater.inflate(R.layout.fragment_guide_search, container); 

all'interno Fragment.onCreateView (...

è necessario chiamare

View res = inflater.inflate(R.layout.fragment_guide_search, container, false); 

o

View res = inflater.inflate(R.layout.fragment_guide_search, null); 
+0

Data la descrizione della documentazione, questo ha perfettamente senso ed è stato risolto il problema. – CoatedMoose

+1

per me :) Visualizza res = inflater.inflate (R.layout.fragment_guide_search, null); – cV2

+0

per me, la seconda opzione anche – androidevil

4

First , la risposta di RB Patel per inserire co de (mostrato sotto), ha funzionato come un incantesimo, ma mentre leggevo su questa funzionalità, ho capito che era inteso come una potenziale ottimizzazione e non è in realtà la soluzione al bug.

mViewPager.setOffscreenPageLimit(3); 

sito degli sviluppatori Android dice il seguente su questo metodo:

setOffscreenPageLimit (limite int) - Impostare il numero di pagine che dovrebbero essere conservati su entrambi i lati della pagina corrente nella vista gerarchia in stato di inattività.

Sembra che questo imposti un limite al numero di pagine memorizzate nella cache a destra oa sinistra della pagina corrente. Nel mio caso questo era solo un aiuto per il problema del band, sì l'errore si è fermato e le cose hanno funzionato senza intoppi, ma avevo ancora del codice in agguato nel mio programma che semplicemente non veniva eseguito. Credo che questo metodo sia stato concepito per essere utilizzato come ottimizzazione e non come una vera correzione al bug.

Mi sono imbattuto in questo problema durante il tentativo di sovraccaricare il metodo instantiateItem() in una classe personalizzata che estende PagerAdapter. Il mio errore è stato gettato dopo che avrò navigato di nuovo in una scheda/pagina che avevo precedentemente visitato/istanziato.

Sono nuovo per Android ma farò del mio meglio per spiegare la mia soluzione. La linea che gettare questo errore è stato il seguente:

v.addView(child); 

Se ho capito bene, si stava soffocando perché il bambino era già un'istanza in precedenza e assegnato un genitore.

Quando tornavo a una vista/pagina precedentemente visitata, stavo tentando di aggiungere una vista che aveva già una vista di layout padre in un nuovo layout, quindi l'errore.

Soluzione: ho appena controllato per vedere se la vista figlio che stavo cercando di visualizzare (istanziare) era già stata istanziata da qualche altra parte, vedendo se aveva una vista padre impostata. Se la vista figlio era già stata creata, allora ho semplicemente usato il genitore della vista figlio invece di creare un nuovo layout.

Ecco il mio codice (mi scuso se offende eventuali esperti):

@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; 
} 
+0

mViewPager.setOffscreenPageLimit (3); salvato la mia vita! Grazie mille! – L93

+0

genitore di ritorno ha ancora ottenuto l'eccezione –

1

Ecco la mia soluzione (utilizzato in ciascuno dei frammenti), che permette sia la scorrevolezza ed evita problemi di 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; 
    } 
1
@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); 
} 
0

se si sta lavorando con FragmentPagerAdapter, quindi utilizzare solo il metodo destroyItem all'interno di FragmentPagerAdapter.

@Override 
public void destroyItem(ViewGroup container, int position, Object object) 
{ 
     FragmentTransaction ft=fm.beginTransaction(); 
     ft.remove((Fragment) object); 
     ft.commit(); 
} 

setOffscreenPageLimit (limite int) consuma più memoria e in alcuni casi non funziona perfettamente. il suo stato di conservazione in entrambi i lati vedere la descrizione. setOffscreenPageLimit (limite int): consente di impostare il numero di pagine che devono essere conservate su entrambi i lati della pagina corrente nella gerarchia della vista in uno stato inattivo.

0

// se la vista figlio da aggiungere è già associata a un genitore, quindi rimuovere il figlio dal genitore e quindi aggiungere nuovamente al contenitore.

if (v.getParent() != null) { 
    ((ViewGroup) v.getParent()).removeView(v); 
} 
container.addView(v); 
Problemi correlati