web-dev-qa-db-fra.com

setBackgroundResource () supprime mes attributs de disposition XML

J'ai une vue qui est utilisée comme élément dans un ListView. Dans mon adaptateur personnalisé, je modifie l'arrière-plan de la vue à l'aide de View.setBackgroundResource() selon la position de l'élément dans la liste. (J'ai des actifs distincts pour le premier et le dernier éléments de la liste.)

Cela définit l'image d'arrière-plan correcte comme prévu, mais cela a l'effet secondaire désagréable que tout le rembourrage que j'ai défini dans la définition XML de la vue est complètement ignoré.

(Si je définis l'arrière-plan comme dessinable dans le XML et que je n'essaie pas de le faire varier au moment de l'exécution dans l'adaptateur, le remplissage fonctionne correctement.)

Comment puis-je modifier l'image d'arrière-plan et conserver le rembourrage? Est-ce un bug?

[~ # ~] modifier [~ # ~] il semble que quelqu'un d'autre ait trouvé le même problème ici: Est-ce que changer l'arrière-plan change aussi le remplissage d'un LinearLayout?

69
Graham Borland

J'ai également rencontré ce problème. Vraisemblablement, vous utilisez une ressource LayerList dessinable? Voilà ce que j'utilisais. Malheureusement, je n'ai trouvé aucun moyen "réel" de le corriger, cela semble être un bug dans le code, mais je ne l'ai pas pourchassé. Cependant, j'ai eu de la chance dans le sens où je définissais l'arrière-plan "buggy" après que ma vue avait déjà été rendue correctement, il s'agissait donc simplement de sauvegarder puis de restaurer les valeurs de remplissage une fois l'arrière-plan défini, par exemple:

  if(condition) {
    int bottom = theView.getPaddingBottom();
    int top = theView.getPaddingTop();
    int right = theView.getPaddingRight();
    int left = theView.getPaddingLeft();
    theView.setBackgroundResource(R.drawable.entry_bg_with_image);
    theView.setPadding(left, top, right, bottom);
  }

EDIT: Comme alternative, vous n'avez pas à utiliser les valeurs précédentes de remplissage, vous pouvez également utiliser une valeur de dimension:

  int pad = resources.getDimensionPixelSize(R.dimen.linear_layout_padding);
  theView.setBackgroundResource(R.drawable.entry_bg_with_image);
  theView.setPadding(pad, pad, pad, pad);
106
dmon

Pour ajouter à ce que dmon a suggéré, voici une fonction que vous pouvez simplement ajouter à votre classe util afin que vous n'ayez pas à sauter à travers les cerceaux chaque fois que vous mettez à jour une ressource. C'est vraiment juste son code enveloppé dans une fonction.

public static void updateBackgroundResourceWithRetainedPadding(View view, int resourceID)
{
    int bottom = view.getPaddingBottom();
    int top = view.getPaddingTop();
    int right = view.getPaddingRight();
    int left = view.getPaddingLeft();
    view.setBackgroundResource(resourceID);
    view.setPadding(left, top, right, bottom);
}
11
Brandon Romano

Ceci est corrigé dans Lollipop, donc

public static void setBackgroundResource(@NonNull View view, @DrawableRes int resId) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop) {
        int paddingTop = view.getPaddingTop();
        int paddingLeft = view.getPaddingLeft();
        int paddingRight = view.getPaddingRight();
        int paddingBottom = view.getPaddingBottom();
        view.setBackgroundResource(resId);
        view.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
    } else {
        view.setBackgroundResource(resId);
    }
}
7
e.shishkin

Une autre solution pour laquelle j'ai opté au lieu d'obtenir et de définir le remplissage dans le code que dmon a proposé n'utilise pas de remplissage et utilise plutôt des marges pour les éléments internes.

Selon votre mise en page, il peut en fait s'agir de la même quantité de code XML et ne nécessiterait aucun Java du tout. Cela me semble un peu plus sale, mais pas aussi sale que d'ajouter ça = Java code partout.

6
Artem Russakovskii