2011-06-29 25 views
128

Najpierw małe tło:Zadzwoń removeView() na rodzica dziecka najpierw

Mam układ wewnątrz przewijania. Na początku, gdy użytkownik przewija ekran, przewijanie przewija. Jednak po pewnym przewinięciu miałem wyłączyć przewijanie w widoku przewijania i przesunąć "ognisko przewijania" na widok internetowy w układzie podrzędnym. W ten sposób przewijany widok i wszystkie zdarzenia przewijania przechodzą do widoku w środku.

Jeśli chodzi o rozwiązanie, po osiągnięciu progu przewijania usuwam układ podrzędny z przewijania i umieszczam go w elemencie nadrzędnym scrollview (i spraw, aby widok przewijania był 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: (-> środek zawiera)

Przed: parentlayout -> Scrollview -> scrollChildLayout

Po: parentLayout -> scrollChildLayout

Powyższy kod daje mi to 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 nazywam removeView na rodzica.

Odpowiedz

269

Rozwiązanie:

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

Użyj element podrzędny, aby uzyskać odwołanie do rodzica. Prześlij element nadrzędny do grupy ViewGroup, aby uzyskać dostęp do metody removeView i użyć jej.

Dzięki @Dongshengcn do rozwiązania

+14

+1 getParent() to klejnot tutaj. –

+1

Rozwiązanie jest prawidłowe, ale dlaczego "scollView.removeView (scrollChildLayout)" nie działa? Czy te dwie linie nie powinny być takie same? –

+0

@ andrea.spot, wydaje się, że 'scrollView.removeView (scrollChildLayout)' próbuje usunąć dziecko scrollView, a nie usunąć samego scrollView z jego rodzica ViewGroup –

22

Spróbuj najpierw usunąć scrollChildLayout z widoku rodzica?

scrollview.removeView(scrollChildLayout) 

Lub usuń wszystkie elementy podrzędne z widoku rodzica i dodaj je ponownie.

scrollview.removeAllViews() 
+0

jestem już nazywając removeView w kodzie w moim pytaniu powyżej. removeAllViews() również nie działa. – kasgoku

+0

Czy jesteś pewien, że to rodzic, do którego dzwonisz removeView()/removeAllViews()? Robię bardzo podobne rzeczy i to działa dla mnie. – dongshengcn

+4

Możesz spojrzeć na rodzica, patrząc na: view.getParent() http://developer.android.com/reference/android/view/View.html#getParent() – dongshengcn

2

Wszystko, co musisz zrobić, to post() Runnable, który robi addView().

+0

Nie działa. Oto, co próbowałem: scrollView.removeView (scrollChildLayout); scrollView.setVisibility (View.GONE); parentLayout.post (nowa Runnable() { @Override public void run() { parentLayout.addView (scrollChildLayout); } }); – kasgoku

0

Można również zrobić to poprzez sprawdzenie, czy View za indexOfView metoda jeśli metoda indexOfView zwraca -1 wtedy możemy użyć.

Wyświetl szczegóły od ViewGroupViewFromParent (v); , po której następuje ViewGroup's removeDetachedView (v, true/false);

15

Ok, zadzwoń do mnie paranoję ale proponuję:

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 

odlewania bez instanceof prostu wydaje się błędne. I (dzięki IntelliJ IDEA za poinformowanie mnie) removeView jest częścią interfejsu ViewManager. I nie należy rzucać do konkretnej klasy, gdy dostępny jest doskonale odpowiedni interfejs.

1

Nazywałem parentView.removeView (childView), a childView wciąż było wyświetlane. W końcu zdałem sobie sprawę, że metoda była w jakiś sposób wyzwalana dwa razy i dodawała childView do parentView dwa razy.

Użyj funkcji parentView.getChildCount(), aby określić liczbę dzieci, które rodzic ma przed dodaniem widoku, a następnie. Jeśli dziecko zostanie dodane zbyt wiele razy, usuwane jest najwyżej położone dziecko, a kopia childView pozostaje - co wygląda tak, że removeView działa nawet wtedy, gdy jest.

Nie należy również używać View.GONE do usuwania widoku. Jeśli to rzeczywiście usunięte wtedy nie będzie trzeba go ukryć, inaczej to wciąż istnieje, a ty po prostu ukrywa ją od siebie :(

18

W onCreate z działalnością lub w onCreateView z fragmentu.

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) { 

} 
0

Co robię źle, więc mam ten błąd jest nie byłem instancji dynamiczny układ i dodając do Childs tak mam ten błąd

1

W moim przypadku, mam BaseFragment i wszystkie inne fragment dziedziczy z tego.

Tak więc moją solytacją było dodanie tej linii w OnDestroyView() metoda

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

Oto moje rozwiązanie.

Powiedzmy, że masz dwa TextViews i umieścić je na LinearLayout (o nazwie ll). Umieszczasz to LinerLayout na innym LinerLayout.

< lm Linear Layout> 
     < ll Linear Layout> 
      <name Text view> 
      </name Text view> 
      <surname Text view> 
      </surname Text view> 
     </ll Linear Layout> 
</lm Linear Layout> 

Jeśli chcesz utworzyć tę strukturę, musisz nadać rodzicowi dziedziczenie.

Jeśli chcesz go użyć w trybie onCreate, wystarczy.

przeciwnym razie tutaj jest solition:

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()); 
Powiązane problemy