web-dev-qa-db-fra.com

Android: requestLayout () incorrectement appelé

L'erreur suivante se produit lorsque je tente de gonfler une mise en page dans une ListView:

requestLayout() improperly called by Android.widget.TextView{...} during layout: running second layout pass

J'essaie de gonfler une mise en page dans une ListView comme suit:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if(convertView == null){
        LayoutInflater inflater = (LayoutInflater) musicActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.list_item, parent, false);
        ...
    }else{...}
}

La disposition en cours de gonflage peut avoir l’air aussi simple que ce qui suit et va toujours produire l’erreur

<TextView
    Android:id="@+id/txt"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:textSize="@dimen/txt_size"/>

J'ai examiné des questions similaires et aucune solution trouvée ne semble fonctionner Question 1 , Question 2 , Question 3

Est-ce que quelqu'un sait ce qui cause ce type d'erreur? Un conseil de dépannage? Pour plus de contexte, cette ListView est affichée dans une Fragment dans une ViewPager

METTRE À JOUR

Voici la mise en page XML complète (moins un groupe d'attributs), ce qui entraîne toujours le problème

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
 Android:layout_width="match_parent"
 Android:layout_height="match_parent">

 <TextView
    Android:id="@+id/txt1"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content" />

 <TextView
    Android:id="@+id/txt2"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content" />

 <TextView
    Android:id="@+id/txt3"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content" />

<TextView
    Android:id="@+id/txt4"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"/>

</RelativeLayout>

Sur cette base, je penserais que le XML lui-même n’est pas un problème, sauf s’il s’agit du fait que j’utilise un ViewPager et des fragments.

42
Daiwik Daarun

Ce problème semble être un bogue dans l'implémentation Android. Veuillez consulter: https://code.google.com/p/Android/issues/detail?id=75516

L'activation de la fonction de défilement rapide d'une ListView dans votre code via ListView.setFastScrollEnabled(true) déclenchera ce bogue et vous commencerez à voir le 

requestLayout () appelé à tort par Android.widget.TextView {...} pendant la mise en page: exécution de la deuxième passe de mise en page

message dans votre console.

Ce bogue doit avoir été introduit dans l'une des mises à jour de KitKat (4.4.x), car je ne l'avais pas vu avec la version initiale de KitKat (4.4.0). Mis à part le spam de la console laide avec le message de débogage d'en haut, il semble n'y avoir aucun autre impact (peut-être les performances dans certains cas, que je n'ai pas testées).

À votre santé

PS: ce n'est pas la première fois que la fonction de défilement rapide est boguée, par exemple. https://code.google.com/p/Android/issues/detail?id=63545 , 63545 a été corrigé dans KitKat 4.4.3 mais 75516 est apparu par la suite -> semble être un sujet vexé pour Google ;-)

EDIT 12 mai 2015:

J'ai mis à jour mon Nexus 7 vers Android 5.1 il y a quelques minutes (en cours d'exécution 5.0 auparavant) et j'ai cessé de voir ce problème dans cette nouvelle version. Comme l'apparence de l'indicateur FastScroll a également changé dans la version 5.1, je suppose que Google a corrigé ce problème ou tout au moins commenté ces vilaines lignes qui spammaient la console ...

75516 & 82461 sont toujours "non résolus", mais je suppose que ceux-ci se rapportent au même problème, qui est maintenant résolu en 5.1.

41
darksaga

Le problème est que, alors que la méthode getView() de votre adaptateur affiche votre présentation, un autre code tente d'accéder à cette vue pour l'afficher, ce qui entraîne une collision. 

Notez que certaines méthodes, que vous ne prenez peut-être pas en charge (comme setScale(), setTypeFace()), appellent en effet requestLayout(). Il serait donc intéressant de savoir ce que vous faites après votre déclaration inflate.

15
axl coder

J'ai résolu ce problème en désactivant fastScroll sur le ListView dans le fichier XML.

<ListView
    Android:id="@+id/mListview"
    Android:layout_width="wrap_content"
    Android:layout_height="match_parent"

    Android:fastScrollEnabled="false"
/>
5
Joaquin Iurchuk

Pour moi, ce problème se produisait lors d’un appel setLayoutParams(). La solution affichait un runnable sur le boucleur comme indiqué ici

4
VladimirVip

J'ai eu le même problème avec KitKat 4.4.4 sur Motorola X avec Genymotion. Dans mon cas, l'élément de liste est un simple CheckedTextView et l'erreur est survenue dans AppCompatCheckedTextView.

En tant qu'implémentation normale, j'ai gonflé l'élément à partir d'un fichier de présentation XML comme ci-dessous:

if (convertView == null) {
  convertView = inflater.inflate(R.layout.checkable_list_entry, parent, false);
}

Après quelques tentatives, j'ai découvert que cela avait quelque chose à voir avec l'inflation XML. Je ne connais pas la cause fondamentale, mais en guise de solution, j'ai décidé de gonfler l'élément de liste par code et de définir toutes les propriétés par code.

Cela a fini comme ça:

CheckedTextView view;
if (convertView == null) {
  view = new CheckedTextView(parent.getContext());
  view.setMinHeight(getResources().getDimensionPixelSize(R.dimen.default_touch_height));
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    view.setTextAppearance(R.style.SectionEntry);
  } else {
    view.setTextAppearance(parent.getContext(), R.style.SectionEntry);
  }
  view.setBackgroundResource(R.drawable.form_element);
  view.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
  view.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT));
} else {
  view = (CheckedTextView) convertView;
}
1
Thomas R.

Cela peut arriver si vous utilisez une extension tierce de ListView. Remplacez-le par ListView standard et vérifiez s'il génère toujours l'erreur. 

J'ai eu le même problème. S'il vous plaît vérifier mise en page Android: en cours d'exécution deuxième passage et ma réponse.

1
ksarmalkar

Dans mon cas (Samsung Galaxy S4, API 21), cela s’est produit dans ListView avec EditTexts. J'ai un auditeur pour la validation du champ. Quelque chose comme:

edit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            error.setVisibility(View.INVISIBLE);
            error.setText("");
        } else {
            String s = edit.getText().toString();
            if (s.isEmpty()) {
                error.setText("Error 1");
            } else if (s.length() < 2 || s.length() > 100) {
                error.setText("Error 2");
            }
            error.setVisibility(View.VISIBLE);
        }
    }
});

Après avoir défini le focus dans l’un de ces EditTexts, une vérification ci-dessus est appelée. Après cela, un TextView va changer (le TextView contient un message d'erreur et repose sur le texte d'édition) . La définition du focus sur le deuxième ou le troisième texte d'édition a conduit à une demande permanente du premier texte d'édition et à son retour à la valeur courante. Une application s'exécute en boucle infinie de demandes (focus edittext 1, unfocus edittext 1, focus 3, unfocus 3, focus 1, etc.).

J'ai essayé de définir listView.setFastScrollEnabled (false). Aussi, j'ai essayé un requestLayout () de certains éléments comme dans https://github.com/sephiroth74/HorizontalVariableListView/issues/93 sans aucune chance . Actuellement, j'ai créé TextView de largeur et hauteur fixes en XML :

<TextView
    Android:id="@+id/error"
    Android:layout_width="match_parent" (or "200dp", but not "wrap_content")
    Android:layout_height="20dp"
    .../>

Après quelques expériences, j'ai remarqué qu'une hauteur de 20dp peut être remplacée par "wrap_content". Mais si un texte trop long se divise en 2 lignes, l'application intercepte à nouveau dans la boucle infinie. Donc, Android:singleLine="true" aidera. Il est obsolète, mais étonnamment Android:maxLines="1" avec Android:lines="1" ne nous aide pas car ils demandent à nouveau la mise en page . Finalement, nous avons:

<TextView
    Android:id="@+id/error"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:singleLine="true"
    Android:textColor="#f00"
    Android:textSize="20sp"
    tools:text="Error message"/>

Ce n'est pas une bonne solution, mais au moins cela casse la boucle infinie.

1
CoolMind

Dans mon cas, cet avertissement a empêché un bouton d'apparaître dans les périphériques API 21. La visibilité du bouton était précédemment définie sur GONE.

La seule solution que j'ai trouvée était de définir INVISIBLE au lieu de GONE pour API 21. Ce n'était pas une solution réelle mais acceptable pour moi.

Je poste seulement ceci parce que cela peut être utile de quelqu'un.

if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Lollipop) {
    theButton.setVisibility(View.INVISIBLE);
}
else {
    theButton.setVisibility(View.GONE);
}
1
Javier Torón

Parfois, vous avez peut-être déjà résolu le problème, mais le problème est toujours conservé. Vous devez donc fermer Visual Studio, supprimer tous les dossiers bin et obj de vos projets, puis désinstaller l'application de l'émulateur. alors walah !! tout va bien 

0
A. Almazidi

Essayez de supprimer textSize du fichier XML et de le définir en code Java. Je pense que cela fait qu'il soit aménagé deux fois.

0
Gabe Sechan