RecyclerView中用于低于Android 5.0版本的Drawable颜色调整

3

我正在尝试在我的RecyclerView中使用以下代码来使用可绘制着色

Drawable likeDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.ic_thumb_up);
Drawable likeWrappedDrawable = DrawableCompat.wrap(likeDrawable);
DrawableCompat.setTint(likeWrappedDrawable,ContextCompat.getColor(getActivity(), android.R.color.white));
holder.ivLike.setImageDrawable(likeWrappedDrawable);

现在所有这些都在RecyclerView适配器的onBindViewHolder方法中完成。

我根据列表项的状态将此着色更改为三种颜色。这在Lolipop及以上版本中运行良好,但在此版本以下,列表项的颜色是不可预测的。有时它会显示正确的颜色,但在刷新列表时,有时会变成其他颜色。

我做错了什么或者在早期版本的着色处理在这种情况下仍无法使用?

更新

包含我onBindViewHolder方法的代码:

@Override
public void onBindViewHolder(ViewHolder holder, int position) {

    Drawable likeDrawable =
        ContextCompat.getDrawable(getActivity(), R.drawable.ic_thumb_up);

    Drawable likeWrappedDrawable = DrawableCompat.wrap(likeDrawable);

    holder.tvLikeCount.setTextColor(ResUtil.getColor(R.color.light_font,
        getActivity()));

    DrawableCompat.setTint(likeWrappedDrawable,
        ContextCompat.getColor(getActivity(), android.R.color.white));

    if (tweetModel.isFavorited()) {
        DrawableCompat.setTint(likeWrappedDrawable,
            ContextCompat.getColor(getActivity(), android.R.color.holo_blue_light));
    }

    holder.ivLike.setImageDrawable(likeWrappedDrawable);

}

ic_thumb_up是什么类型的drawable?只是一个PNG还是基于XML的drawable? - alanv
我们可以有onBindViewHolder的完整代码吗? - Inder Kumar Rathore
今天会发布代码。 - Kshitij Aggarwal
已更新我的问题并附上了所请求的代码。遗憾的是我无法提供更多信息。 - Kshitij Aggarwal
你可以尝试我的答案,链接如下:https://stackoverflow.com/questions/58499495/dynamically-tint-drawable-in-adapter-change-color-for-all/63283675#63283675 - Abhijeet
你可以试着使用我的答案进行检查:https://stackoverflow.com/questions/58499495/dynamically-tint-drawable-in-adapter-change-color-for-all/63283675#63283675 - Abhijeet
2个回答

12

1
我上次尝试使用它,但效果不太好。我会再试一次。 - Kshitij Aggarwal

0

TL;DR. 如果你担心效率问题,可以使用TintedIconCache,这是一个单独的类,你可以从this gist中获取。

TintedIconCache cache = TintedIconCache.getInstance();
Drawable myTintedDrawable = cache.fetchTintedIcon(context, R.drawable.icon_01, R.color.color_01));

需要做更多的事情,而不仅仅是.mutate()

正如@Vladimir所说,您必须调用drawable.mutate()来获取隔离状态,否则对可绘制属性所做的任何更改都将反映在共享相同状态的所有其他可绘制对象上。

实际上,这种行为有很好的原因之一是内存效率,有些情况下您可能希望保持这种效率。

例如,您可能具有使用相同可绘制对象但根据某些属性(例如成功、失败、警告、信息等)以不同方式着色的项目的RecyclerView。如果您处于这种情况下,则为每个项目突变可绘制对象并不是最佳解决方案。您可以考虑创建所有可能的可绘制对象,具有所有可能的色调,但您可能会创建无用的对象。如果您处于这种情况下,我已经为您准备好了!

进入TintedIconCache

更好的解决方案是拥有某种可绘制对象缓存,只有在需要时才创建每个唯一着色的可绘制对象,然后有效地缓存以供后续需要,直到您不再需要它或系统需要占用的内存。

我已经在TintedIconCache中实现了这个功能。使用起来很简单:

// Get an instance
TintedIconCache cache = TintedIconCache.getInstance();

// Will be fetched from the resources
Drawable backIcon = cache.fetchTintedIcon(context, R.drawable.icon, R.color.black));

// Will be fetched from the resources as well
Drawable bleuIcon = cache.fetchTintedIcon(context, R.drawable.icon, R.color.bleu));
   
// Will be fetched from the cache!!!
Drawable backIconTwo = cache.fetchTintedIcon(context, R.drawable.icon, R.color.back));

考虑查看gist,以了解它在幕后的工作原理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接