Najpierw małe tło:
Mam układ w przewijanym widoku. Na początku, gdy użytkownik przewija ekran, przewija się widok scrollview. Jednak po pewnym czasie przewijania musiałem wyłączyć przewijanie w widoku przewijania, aby przenieść „fokus przewijania” na widok sieciowy w układzie potomnym. W ten sposób przewijane drążki i wszystkie zdarzenia przewijania trafiają do znajdującego się w nim widoku internetowego.
Tak więc, aby znaleźć rozwiązanie, po osiągnięciu progu przewijania usuwam układ potomny z widoku scrollview i umieszczam go w elemencie nadrzędnym scrollview (i sprawiam, że scrollview jest niewidoczny).
// 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);
Ogólna idea: (-> oznacza zawiera)
Przed: parentlayout -> scrollview -> scrollChildLayout
Po: parentLayout -> scrollChildLayout
Powyższy kod daje mi ten wyjątek:
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)
Czy wiesz, co się dzieje? Wyraźnie wzywam removeView na rodzica.
źródło
scrollView.removeView(scrollChildLayout)
próbuje usunąć element potomny scrollView, a nie usuwać samego scrollView z jego nadrzędnej ViewGroupif (mAdView.getParent()!=null) ((ViewGroup) mAdView.getParent()).removeView(mAdView);
Spróbuj najpierw usunąć scrollChildLayout z jego widoku nadrzędnego?
Lub usuń całe dziecko z widoku rodzica i dodaj je ponownie.
źródło
W onCreate z aktywnością lub w onCreateView z fragmentem.
źródło
Ok, nazwij mnie paranoikiem, ale proponuję:
rzucanie bez
instanceof
po prostu wydaje się złe. I (dzięki IntelliJ IDEA za poinformowanie mnie)removeView
jest częściąViewManager
interfejsu. I nie należy rzucać na konkretną klasę, gdy dostępny jest idealnie odpowiedni interfejs.źródło
Wszystko, co musisz zrobić, to wysłać () element Runnable, który wykona addView ().
źródło
Wołałem parentView.removeView (childView), a childView wciąż się wyświetlało. W końcu zdałem sobie sprawę, że metoda została w jakiś sposób wyzwolona dwukrotnie i dwukrotnie dodałem childView do parentView.
Tak więc, użyj parentView.getChildCount (), aby określić, ile dzieci ma rodzic przed dodaniem widoku i później. Jeśli element podrzędny zostanie dodany zbyt wiele razy, zostanie usunięty najbardziej górny element podrzędny, a kopia childView pozostanie - która wygląda na to, że removeView działa nawet wtedy, gdy jest.
Nie należy również używać View.GONE do usuwania widoku. Jeśli jest naprawdę usunięty, nie musisz go ukrywać, w przeciwnym razie nadal tam jest i po prostu ukrywasz go przed sobą :(
źródło
W moim przypadku mam BaseFragment i wszystkie inne fragmenty dziedziczą z tego.
Więc moim solytionem było dodanie tych linii w
OnDestroyView()
metodzieźródło
Rozwiązanie Kotlin
Kotlin upraszcza rzutowanie rodzica za pomocą
as?
, zwracając wartość null, jeśli lewa strona jest pusta lub rzutowanie nie powiedzie się.Rozszerzenie Kotlin
Jeśli chcesz to jeszcze bardziej uprościć, możesz dodać to rozszerzenie.
Bezpiecznie nic nie zrobi, jeśli ten widok ma wartość null, widok nadrzędny ma wartość null lub widok nadrzędny nie jest grupą widoków
źródło
Możesz to również zrobić, sprawdzając, czy metoda indexOfView View, jeśli metoda indexOfView zwraca -1, wtedy możemy użyć.
ViewGroup's detachViewFromParent (v); po którym następuje removeDetachedView ViewGroup (v, prawda / fałsz);
źródło
To, co robiłem źle, więc otrzymałem ten błąd, to nie utworzyłem instancji układu dynamicznego i nie dodałem do niego elementów podrzędnych, więc otrzymałem ten błąd
źródło
Oto moje rozwiązanie.
Powiedzmy, że masz dwa
TextViews
i umieść je naLinearLayout
(nazwanell
). Położysz toLinerLayout
na innymLinerLayout
.Jeśli chcesz stworzyć taką strukturę, musisz przekazać rodzicowi jako dziedziczenie.
Jeśli chcesz, użyj go w
onCreate
metodziethis
, wystarczy.W przeciwnym razie tutaj jest rozwiązanie:
źródło