setBackgroundResource() 丢弃我的 XML 布局属性

发布于 2024-11-05 07:02:45 字数 489 浏览 0 评论 0原文

我有一个视图,用作 ListView 中的项目。在我的自定义适配器中,我根据列表中项目的位置使用 View.setBackgroundResource() 更改视图的背景。 (我为列表中的第一项和最后一项设置了单独的资源。)

这会按预期设置正确的背景图像,但它会产生令人讨厌的副作用,即我在视图的 XML 定义中设置的所有填充都完全消失了。被忽略。

(如果我在 XML 中设置背景可绘制对象,并且不尝试在适配器中的运行时更改它,则填充一切正常。)

如何更改背景图像并保留填充?这是一个错误吗?

编辑似乎其他人在这里发现了同样的问题:更改背景是否也会更改 LinearLayout 的填充?

I have a view which is used as an item in a ListView. In my custom adapter, I change the background of the view using View.setBackgroundResource() depending on the item's position in the list. (I have separate assets for the first and last items in the list.)

This sets the correct background image as expected, but it has the nasty side-effect that all the padding I'd set in the XML definition of the view is completely ignored.

(If I set the background drawable in the XML, and don't try to vary it at runtime in the adapter, the padding all works fine.)

How can I alter the background image, and retain the padding? Is this a bug?

EDIT it seems someone else has found the same problem here: Does changing the background also change the padding of a LinearLayout?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

自由如风 2024-11-12 07:02:45

我也遇到了这个问题。想必您正在使用 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);

I ran into this issue as well. Presumably you're using a LayerList resource drawable? That's what I was using. Unfortunately, I found no "real" way of fixing it, it seems like a bug in the code, but I didn't chase it down. However, I was lucky in the sense that I was setting the "buggy" background after my view had already been rendered properly, so it was just a matter of saving then restoring the padding values after the background is set, e.g:

  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:
As an alternative, you don't have to use the previous values of padding, you can also use a dimension value:

  int pad = resources.getDimensionPixelSize(R.dimen.linear_layout_padding);
  theView.setBackgroundResource(R.drawable.entry_bg_with_image);
  theView.setPadding(pad, pad, pad, pad);
Oo萌小芽oO 2024-11-12 07:02:45

添加到 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);
}

Adding onto what dmon has suggested, here is a function you can just throw in your util class so you don't have to jump through hoops every time you update a resource. This is really just his code wrapped in a function.

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);
}
情何以堪。 2024-11-12 07:02:45

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

This is fixed in Lollipop, so

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);
    }
}
阪姬 2024-11-12 07:02:45

我选择的另一个解决方案不是在 dmon 提出的代码中获取和设置填充,而是不使用填充,而是使用内部元素的边距。

根据您的布局,它实际上可能是相同数量的 XML 代码,并且根本不需要任何 Java。我觉得这有点脏,但还不如到处添加 Java 代码那么脏。

Another solution that I opted in for instead of getting and setting padding in the code that dmon proposed is not using padding and instead using margins for inner elements.

Depending on your layout, it may actually be the same amount of XML code and wouldn't require any Java at all. It feels a little dirtier to me, but not as dirty as adding that Java code everywhere.

つ低調成傷 2024-11-12 07:02:45

在 Monodroid 中,如果我将调用发布到 SetBackgroundResource,则顶部填充和底部填充保持不变

private EditText _etInput

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

但是,左侧填充会重置为 0!?如果未发布,则所有填充都会重置为 0。

认为这是一个值得发布的有趣发现......

In Monodroid, if I Post the call to SetBackgroundResource, then the top-padding and bottom-padding remains unaltered

private EditText _etInput

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

However, the left-padding gets reset to 0 !? If it's not posted, then all padding is reset to 0.

Thought this to be an interesting find worth posting about ...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文