web-dev-qa-db-fra.com

Appelez removeView () sur le parent de l'enfant en premier

D'abord un petit fond

J'ai une mise en page à l'intérieur d'un scrollview. Au début, lorsque l'utilisateur fait défiler l'écran, la vue défilement défile. Cependant, après une certaine quantité de défilement, je devais désactiver le défilement sur la vue défilement pour déplacer le "focus de défilement" sur une vue Web à l'intérieur de la présentation enfant. De cette façon, les barres de défilement et tous les événements de défilement vont à la vue Web à l'intérieur.

Donc, pour une solution, lorsque le seuil de défilement est atteint, je supprime la présentation enfant de la vue de défilement et la place dans le parent de la vue de défilement (et rend la vue de défilement invisible).

// 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);

Idée générale: (-> signifie contient)

Avant: parentlayout -> scrollview -> scrollChildLayout

Après: parentLayout -> scrollChildLayout

Le code ci-dessus me donne cette exception:

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)

Savez-vous ce qui se passe? J'appelle clairement removeView sur le parent.

133
kasgoku

Solution:

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

Utilisez l'élément enfant pour obtenir une référence au parent. Convertissez le parent dans un ViewGroup pour pouvoir accéder à la méthode removeView et l'utiliser.

Merci à @ Dongshengcn pour la solution

284
kasgoku

Essayez de supprimer scrollChildLayout de sa vue parente en premier?

scrollview.removeView(scrollChildLayout)

Ou supprimez tous les enfants de la vue parent et ajoutez-les à nouveau.

scrollview.removeAllViews()
21
dongshengcn

Dans onCreate avec activité ou dans onCreateView avec 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) {

}
19
Cabezas

Ok, appelez-moi paranoïaque mais je suggère:

  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 sans instanceof semble faux. Et (merci IntelliJ IDEA de me l'avoir dit) removeView fait partie de l'interface ViewManager. Et il ne faut pas se lancer dans une classe concrète lorsqu'une interface parfaitement adaptée est disponible.

16
Martin

Tout ce que vous avez à faire est de poster () un Runnable qui effectue addView ().

3
Romain Guy

J'appelais parentView.removeView (childView) et childView était toujours affiché. J'ai finalement réalisé qu'une méthode était en quelque sorte déclenchée deux fois et j'ai ajouté le childView au parentView deux fois.

Utilisez donc parentView.getChildCount () pour déterminer le nombre d’enfants que possède le parent avant d’ajouter une vue et par la suite. Si l'enfant est ajouté trop souvent, le plus grand des enfants est supprimé et la copie childView reste, ce qui donne l'impression que removeView fonctionne même s'il est actif.

En outre, vous ne devriez pas utiliser View.GONE pour supprimer une vue. Si c'est vraiment supprimé, vous n'aurez pas besoin de le cacher, sinon il est toujours là et vous le cachez :(

1
Chris Sprague

Dans mon cas, j'ai BaseFragment et tous les autres fragments en héritent.

Donc, ma solution a été d'ajouter ces lignes dans la méthode OnDestroyView()

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

Vous pouvez également le faire en vérifiant si la méthode indexOfView de View si la méthode indexOfView renvoie -1, nous pouvons l'utiliser.

DetachViewFromParent (v) de ViewGroup; suivi de removeDetachedView de ViewGroup (v, true/false);

0
Arun Gupta

Ce que je faisais mal alors j'ai eu cette erreur, c'est que je n'instanciais pas la mise en page dynamique et que je n'y ajoutais pas d'enfants, alors j'ai eu cette erreur

0
blackHawk

Voici ma solution.

Disons que vous avez deux TextViews et les mettez sur un LinearLayout (nommé ll). Vous allez mettre ceci LinerLayout sur un autre 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> 

Lorsque vous voulez créer cette structure, vous devez donner le parent en héritage.

Si vous voulez l'utiliser dans une méthode onCreate, this suffira.

Sinon, voici la 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());
0
ishak O.