web-dev-qa-db-ja.com

setBackgroundResource()はXMLレイアウト属性を破棄します

ListViewのアイテムとして使用されるビューがあります。カスタムアダプターでは、リスト内のアイテムの位置に応じて、View.setBackgroundResource()を使用してビューの背景を変更します。 (リストの最初と最後のアイテムに別々のアセットがあります。)

これにより、期待どおりに正しい背景画像が設定されますが、ビューのXML定義で設定したすべてのパディングが完全に無視されるという厄介な副作用があります。

(XMLで背景ドロアブルを設定し、アダプターで実行時にそれを変更しようとしない場合、パディングはすべて正常に機能します。)

背景画像を変更し、パディングを保持するにはどうすればよいですか?これはバグですか?

[〜#〜] edit [〜#〜]ここで他の誰かが同じ問題を見つけたようです: 背景の変更も変更しますLinearLayoutのパディング?

69
Graham Borland

私もこの問題に遭遇しました。おそらく、LayerListリソースのドロアブルを使用していますか?それが私が使っていたものです。残念なことに、私はそれを修正する「本当の」方法を見つけませんでした。それはコードのバグのようですが、私はそれを追いかけませんでした。ただし、ビューが既に適切にレンダリングされた後に「バギー」背景を設定していたという意味で幸運だったので、背景を設定した後、パディング値を保存して復元するだけの問題でした:

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

編集:別の方法として、以前のパディングの値を使用する必要はありません。ディメンション値を使用することもできます。

  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

Dmonの提案に加えて、リソースを更新するたびにフープをジャンプする必要がないように、utilクラスにスローできる関数を次に示します。これは実際、彼のコードを関数にラップしただけです。

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

これはLollipopで修正されたため、

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

Dmonが提案したコードでパディングを取得および設定する代わりに選択した別のソリューションは、パディングを使用せず、代わりに内部要素にマージンを使用することです。

レイアウトによっては、実際には同じ量のXMLコードである可能性があり、Javaはまったく必要ありません。少し汚い感じがしますが、 Javaどこでもコード。

6