Rufen Sie zuerst removeView () für das übergeordnete Element des Kindes auf

Zuerst ein kleiner Hintergrund:

Ich habe ein Layout in einem Scrollview. Wenn der Benutzer zunächst auf dem Bildschirm scrollt, scrollt die Bildlaufansicht. Nach einer gewissen Anzahl von Scrolls sollte ich den Scroll in der Scroll-Ansicht deaktivieren und den “scroll focus” auf ein Webview innerhalb des Child-Layouts verschieben. Auf diese Weise werden die ScrollView-Sticks und alle Scroll-Ereignisse in das Webview in diesem Bereich verschoben.

Wenn also der Scroll-Schwellenwert erreicht ist, entferne ich das Child-Layout aus der Scrollview und lege es in den übergeordneten scrollview (und mache den scrollview unsichtbar).

// Remove the child view from the scroll view scrollView.removeView(scrollChildLayout); // Get scroll view out of the way scrollView.setVisibility(View.GONE); // Put the child view into scrollview's parent view parentLayout.addView(scrollChildLayout); 

Allgemeine Idee: (-> bedeutet enthält)

Vorher: parentlayout -> scrollview -> scrollChildLayout

Nachher: ​​parentLayout -> scrollChildLayout

Der obige Code gibt mir diese Ausnahme:

 java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. at android.view.ViewGroup.addViewInner(ViewGroup.java:1976) at android.view.ViewGroup.addView(ViewGroup.java:1871) at android.view.ViewGroup.addView(ViewGroup.java:1828) at android.view.ViewGroup.addView(ViewGroup.java:1808) 

Weißt du was los ist? Ich rufe removeView eindeutig auf dem Elternteil an.

Lösung:

 ((ViewGroup)scrollChildLayout.getParent()).removeView(scrollChildLayout); //scrollView.removeView(scrollChildLayout); 

Verwenden Sie das untergeordnete Element, um einen Verweis auf das übergeordnete Element zu erhalten. Übergeben Sie das übergeordnete Element an eine ViewGroup, damit Sie Zugriff auf die removeView-Methode erhalten und diese verwenden können.

Danke an @Dongshengcn für die Lösung

Versuchen Sie, scrollChildLayout zuerst aus der übergeordneten Ansicht zu entfernen?

 scrollview.removeView(scrollChildLayout) 

Oder entfernen Sie alle untergeordneten Elemente aus der übergeordneten Ansicht und fügen Sie sie erneut hinzu.

 scrollview.removeAllViews() 

In onCreate mit Aktivität oder in onCreateView mit Fragment.

  if (view != null) { ViewGroup parent = (ViewGroup) view.getParent(); if (parent != null) { parent.removeView(view); } } try { view = inflater.inflate(R.layout.fragment_main, container, false); } catch (InflateException e) { } 

Ok, nenn mich paranoid, aber ich schlage vor:

  final android.view.ViewParent parent = view.getParent (); if (parent instanceof android.view.ViewManager) { final android.view.ViewManager viewManager = (android.view.ViewManager) parent; viewManager.removeView (view); } // if 

casting ohne instanceof scheint einfach falsch. Und (danke IntelliJ IDEA für das Erzählen) removeView ist Teil der ViewManager Schnittstelle. Und wenn eine perfekt geeignete Schnittstelle zur Verfügung steht, sollte man nicht zu einer konkreten class wechseln.

Alles, was Sie tun müssen, ist post () ein Runnable, das die addView () ausführt.

Ich rief parentView.RemoveView (ChildView) und ChildView wurde noch angezeigt. Irgendwann wurde mir klar, dass eine Methode zweimal ausgetriggers wurde und die childView zweimal zur parentView hinzugefügt wurde.

Verwenden Sie also parentView.getChildCount (), um zu ermitteln, wie viele untergeordnete Elemente das übergeordnete Element hat, bevor Sie eine Ansicht hinzufügen und anschließend. Wenn das untergeordnete Element zu oft hinzugefügt wird, wird das oberste untergeordnete Element entfernt, und die Kopie untergeordnetes Objekt bleibt erhalten – was aussieht, als ob removeView funktioniert, selbst wenn dies der Fall ist.

Außerdem sollten Sie View.GONE nicht verwenden, um eine Ansicht zu entfernen. Wenn es wirklich entfernt wird, dann müssen Sie es nicht verstecken, sonst ist es immer noch da und Sie verstecken es nur vor sich selbst 🙁

In meinem Fall habe ich BaseFragment und alle anderen Fragment-Erben von diesem.

Also meine Lösung war diese Zeilen in OnDestroyView() -Methode hinzufügen

 @Override public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (mRootView == null) { mRootView = (inflater == null ? getActivity().getLayoutInflater() : inflater).inflate(mContentViewResourceId, container, false); } ....//// } @Override public void onDestroyView() { if (mRootView != null) { ViewGroup parentViewGroup = (ViewGroup) mRootView.getParent(); if (parentViewGroup != null) { parentViewGroup.removeAllViews(); } } super.onDestroyView(); } 

Sie können dies auch tun, indem Sie prüfen, ob die Methode ‘indexOfView’ von View angezeigt wird, wenn die Methode ‘indexOfView’ -1 zurückgibt.

ViewLroups detachViewFromParent (v); gefolgt von ViewGroups removeDetachedView (v, true / false);

Was ich falsch gemacht habe, so dass ich diesen Fehler bekommen habe, ist, dass ich das dynamische Layout nicht instanziiert habe und childs dazu hinzugefügt habe, also habe ich diesen Fehler bekommen

Hier ist meine Lösung.

Nehmen wir an, Sie haben zwei TextViews und legen sie auf ein LinearLayout (namens ll ). Sie werden dieses LinerLayout auf ein anderes LinerLayout .

 < lm Linear Layout> < ll Linear Layout>       

Wenn Sie diese Struktur erstellen möchten, müssen Sie übergeordnete Elemente als inheritance angeben.

Wenn Sie es in einer onCreate Methode verwenden onCreate , reicht this aus.

Sonst ist hier die Lösung:

 LinerLayout lm = new LinearLayout(this); // You can use getApplicationContext() also LinerLayout ll = new LinearLayout(lm.getContext()); TextView name = new TextView(ll.getContext()); TextView surname = new TextView(ll.getContext());