2012-11-26 3 views
24

In meinem Projekt verwende ich Viewpager mit drei Registerkarten mit den Namen History, Main, . Haupt Aktivität enthalten Timer, Stoppuhr, etc. Karte Anzeige der Google-Karte. und in Geschichte gerade benutze ich nur einfache Textview.So lösen Sie nach Viewpager: Das angegebene Kind hat bereits einen Elternteil. Sie müssen RemoveView() auf der Eltern übergeordneten zuerst aufrufen

Viewpager Strömungsrichtung: Geschichte - Haupt - Karte

stellte ich der Main als das aktuelle Element (Bydefault Haupt-Tag-Anzeige) .Nun, wenn ich Swipe bin von Haupt>Karte und Karte>Haupt seine Arbeit perfekt. aber wenn Streichen von Haupt>Geschichte kein Fehler vorhanden ist, aber zurück Rückkehr aus Geschichte zu Haupt (Geschichte>Haupt) eclipse geben Sie mir Fehler wie:

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

Und FYI Ich verwende intent into Map Activity. Bitte überprüfen Sie unten Code. Bitte lassen Sie mich wissen, wie kann ich mein Problem lösen.

ViewPager Klasse:

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

Dank.

EDIT:

Ohne Absicht in Map-Aktivität funktioniert es pwrfect.I bedeuten, wenn ich denselben bin mit wie die Geschichte in der Karte gibt es kein irgendein Fehler.

Antwort

27

Ich habe auch dieses Problem konfrontiert.

Sie können es lösen, indem nur mViewPager.setOffscreenPageLimit(3); einzelne Zeile hinzufügen

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

Ich hatte das gleiche Problem, wenn ich

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

innen Fragment.onCreateView (...

Sie

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

oder

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

Angesichts der Beschreibung aus der Dokumentation, macht dies vollkommen Sinn, und war, was mein Problem behoben. – CoatedMoose

+1

für mich :) Ansicht res = inflater.inflate (R.layout.fragment_guide_search, null); – cV2

+0

für mich, die zweite Option zu – androidevil

4

Zunächst rufen müssen , die Antwort von RB Patel, um co de (siehe unten), funktionierte wie ein Zauber, aber als ich über dieses Feature las, wurde mir klar, dass es als potenzielle Optimierung gedacht war und nicht wirklich die Lösung für den Fehler ist.

mViewPager.setOffscreenPageLimit(3); 

Die Android Developer-Website sagt folgendes über diese Methode:

setOffscreenPageLimit (int limit) - Legen Sie die Anzahl der Seiten, die zu beiden Seiten der aktuellen Seite in der Ansicht beibehalten werden soll Hierarchie in einem Leerlaufzustand.

Es scheint so, als ob dadurch die Anzahl der Seiten begrenzt wird, die rechts oder links von der aktuellen Seite zwischengespeichert werden. In meinem Fall war das nur ein Pflaster für das Problem, ja der Fehler hörte auf und die Dinge liefen reibungslos, aber ich hatte immer noch schlechten Code, der in meinem Programm lauerte und einfach nicht ausgeführt wurde. Ich glaube, dass diese Methode als eine Optimierung und nicht als eine tatsächliche Behebung des Fehlers verwendet werden sollte.

Ich stieß auf dieses Problem beim Versuch, die instanziateItem() -Methode in einer benutzerdefinierten Klasse zu überladen, die PagerAdapter erweitert. Mein Fehler wurde ausgelöst, nachdem ich zu einer Registerkarte/Seite zurückgekehrt bin, die ich zuvor besucht/instanziiert hatte.

Ich bin neu in Android, aber ich werde mein Bestes tun, um meine Lösung zu erklären. Die Linie, die diesen Fehler zu werfen war die folgende:

v.addView(child); 

Wenn ich das richtig verstehen, es erstickten, weil das Kind schon vorher und einen Elternteil zugewiesen instanziiert wurde.

Als ich zurück zu einer zuvor besuchten Ansicht/Seite navigieren wollte, versuchte ich, eine Ansicht hinzuzufügen, die bereits eine übergeordnete Layoutansicht zu einem neuen Layout hatte, daher der Fehler.

Lösung: Ich habe gerade überprüft, ob die untergeordnete Ansicht, die ich anzeigen wollte (instanziieren), bereits an anderer Stelle instanziiert wurde, indem ich sah, ob sie eine übergeordnete Ansichtsgruppe hatte. Wenn die untergeordnete Ansicht bereits erstellt wurde, habe ich einfach die übergeordnete Ansicht der untergeordneten Ansicht verwendet, anstatt ein neues Layout zu erstellen.

Hier ist mein Code (ich entschuldige mich, wenn es keine Experten beleidigt):

@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.setOffscopePageLimit (3); gerettet Mein Leben! Vielen Dank! – L93

+0

return parent hat immer noch die Ausnahme –

1

Hier ist meine Lösung (in jedem der Fragmente verwendet), die sowohl Glätte ermöglicht und vermeidet Probleme mit dem Speicher:

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

Wenn Sie mit FragmentPagerAdapter arbeiten, verwenden Sie einfach die destroyItem Methode in FragmentPagerAdapter.

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

setOffscreenPageLimit (int limit) verbraucht mehr Speicher und in einigen Fällen funktioniert es ist nicht perfekt. sein beibehalten Zustand auf jeder Seite siehe Beschreibung. setOffscreenPageLimit (int limit) - Legen Sie die Anzahl der Seiten fest, die auf jeder Seite der aktuellen Seite in der Ansichtshierarchie im Leerlauf gehalten werden sollen.

0

// Wenn die hinzuzufügende untergeordnete Ansicht bereits an ein übergeordnetes Element gebunden ist, entfernen Sie das untergeordnete Element aus dem übergeordneten Element und fügen Sie es anschließend erneut dem Container hinzu.

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