setBackgroundResource() verwirft meine XML-Layoutattribute

Lesezeit: 4 Minuten

Benutzer-Avatar
Graham Borland

Ich habe eine Ansicht, die als Element in a verwendet wird ListView. In meinem benutzerdefinierten Adapter ändere ich den Hintergrund der Ansicht mit View.setBackgroundResource() abhängig von der Position des Elements in der Liste. (Ich habe separate Assets für das erste und letzte Element in der Liste.)

Dadurch wird das richtige Hintergrundbild wie erwartet festgelegt, aber es hat den unangenehmen Nebeneffekt, dass alle Polsterungen, die ich in der XML-Definition der Ansicht festgelegt habe, vollständig ignoriert werden.

(Wenn ich den Hintergrund in XML zeichenbar einstelle und nicht versuche, ihn zur Laufzeit im Adapter zu ändern, funktioniert das Auffüllen einwandfrei.)

Wie kann ich das Hintergrundbild ändern und die Polsterung beibehalten? Ist das ein Fehler?

BEARBEITEN Es scheint, dass jemand anderes hier das gleiche Problem gefunden hat: Ändert das Ändern des Hintergrunds auch die Polsterung eines LinearLayouts?

Benutzer-Avatar
dmon

Ich bin auch auf dieses Problem gestoßen. Vermutlich verwenden Sie eine LayerList-Ressource, die gezeichnet werden kann? Das habe ich benutzt. Leider habe ich keine “richtige” Möglichkeit gefunden, es zu beheben, es scheint ein Fehler im Code zu sein, aber ich habe es nicht verfolgt. Ich hatte jedoch Glück in dem Sinne, dass ich den “fehlerhaften” Hintergrund festgelegt habe, nachdem meine Ansicht bereits ordnungsgemäß gerendert worden war, sodass es nur darum ging, die Füllwerte zu speichern und dann wiederherzustellen, nachdem der Hintergrund festgelegt wurde, z.

  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: Alternativ müssen Sie nicht die vorherigen Werte der Polsterung verwenden, Sie können auch einen Dimensionswert verwenden:

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

  • Das heilt es, danke. In meinem Fall ist das Drawable ein PNG mit neun Patches.

    – Graham Borland

    4. Mai 2011 um 22:23 Uhr

  • Ach, das ist es tatsächlich. Sehen Sie sich den Code der Ansicht an (j.mp/kxQJIJ), in setBackgroundDrawable(). Es überschreibt eindeutig die Polsterung mit der Polsterung des drawable. Aber wenn man sich die Drawable-Ressourcendokumentation ansieht, unterstützt nichts außer Formen das Auffüllen, so dass es möglicherweise kläglich fehlschlägt.

    – dmon

    4. Mai 2011 um 22:42 Uhr

  • Und es scheint, dass Romain Guy es gerade als “funktioniert wie beabsichtigt” geschlossen hat. Es gibt einen Kommentar im Code, der dieses Verhalten rechtfertigt, also war es absichtlich so. Ich denke, es wäre einfach schöner, wenn es irgendwo dokumentiert wäre.

    – dmon

    15. September 2011 um 5:01 Uhr

  • Dies ist definitiv nicht “funktioniert wie beabsichtigt”, wenn ich nur die Hintergrundressource eines Bildes und keine anderen Eigenschaften ändern möchte, indem ich setBackgroundResource() verwende, hätte ich nie erwartet, dass es sich auf das Padding des Elements auswirkt.

    – Elad Nava

    17. August 2012 um 21:15 Uhr

  • Romain sagt: „Der Grund, warum das Setzen eines Bildes die Auffüllung zurücksetzt, ist, dass 9-Patch-Bilder eine Auffüllung codieren können. Wenn sie fehlt, nehmen wir eine Auffüllung von 0 an.“ Es sollte “Falls fehlt && is9Patch()” meiner bescheidenen Meinung nach.

    – Adamport

    24. Februar 2015 um 20:28 Uhr

Ergänzend zu dem, was dmon vorgeschlagen hat, ist hier eine Funktion, die Sie einfach in Ihre util-Klasse werfen können, damit Sie nicht jedes Mal durch die Reifen springen müssen, wenn Sie eine Ressource aktualisieren. Das ist wirklich nur sein Code, der in eine Funktion verpackt ist.

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

Dies ist in Lollipop behoben, also

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

  • Nein, das ist in Lollipop nicht behoben (zumindest nicht auf meinem Lager 5.1 Moto G ROM)

    – Henrique de Sousa

    9. September 2016 um 13:59 Uhr

  • Dies ist seit KitKat behoben, daher sollte die Überprüfung erfolgen Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT.

    – David

    29. Dezember 2017 um 13:23 Uhr


  • Immer noch nicht behoben auf meinem Pixel 2 API 29

    – SCHMUTZIGER DAVE

    30. Dezember 2020 um 3:08 Uhr

Eine andere Lösung, für die ich mich entschieden habe, anstatt Padding in dem von dmon vorgeschlagenen Code abzurufen und festzulegen, besteht darin, Padding nicht zu verwenden und stattdessen Ränder für innere Elemente zu verwenden.

Abhängig von Ihrem Layout kann es tatsächlich die gleiche Menge an XML-Code sein und würde überhaupt kein Java benötigen. Es fühlt sich für mich etwas schmutziger an, aber nicht so schmutzig, als würde man diesen Java-Code überall hinzufügen.

Benutzer-Avatar
Samus

Wenn ich in Monodroid den Aufruf an SetBackgroundResource poste, bleibt das Top-Padding und das Bottom-Padding unverändert

private EditText _etInput

public void Disable()
{
    _etInput.Post(() => {
        _etInput.SetBackgroundResource(Resource.Drawable.input_field_background_disabled);
        _etInput.Clickable = false;
});

Das Left-Padding wird jedoch auf 0 zurückgesetzt !? Wenn es nicht gepostet wird, wird die gesamte Auffüllung auf 0 zurückgesetzt.

Ich hielt dies für einen interessanten Fund, über den es sich zu berichten lohnt …

1246220cookie-checksetBackgroundResource() verwirft meine XML-Layoutattribute

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy