在RecyclerView中改变单个可绘制对象的颜色将改变所有可绘制对象



我只是试图改变我的可绘制的颜色在我的行取决于一个值,但不是一个可绘制的适配器改变了他们所有。

这是我的适配器:

public class ReportAdapter extends RecyclerView.Adapter<ReportAdapter.ReportViewHolder> {
    DataBaseHelper dataBase;
    private LayoutInflater inflater;
    List<ChoosedSubject> data = Collections.emptyList();
    Context context;
    OnItemClickListener itemClickListener;
    public ReportAdapter(Context context, List<ChoosedSubject> data, OnItemClickListener itemClickListener) {
        inflater = LayoutInflater.from(context);
        this.data = data;
        this.context = context;
        this.itemClickListener = itemClickListener;
    }
    @Override
    public ReportViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = inflater.inflate(R.layout.report_cell, parent, false);
        ReportViewHolder holder = new ReportViewHolder(view);
        dataBase = new DataBaseHelper(context);
        return holder;
    }
    //Set Data inside RecyclerView
    @Override
    public void onBindViewHolder(ReportViewHolder holder, int position) {
        ChoosedSubject current = data.get(position);
        Grades grades = new Grades(context);
        Resources resources = context.getResources();
        int iconColor;
        Drawable icon;
        icon = ContextCompat.getDrawable(context, dataBase.getSpecificChoosedSubjectAppendingToName(current.getName()).get(0).getChoosedIcon());
        if (dataBase.getSpecificChoosedSubjectAppendingToName(current.getName()).get(0).getChoosedIcon() != R.drawable.subject_default) {
            iconColor = resources.getColor(dataBase.getSpecificChoosedSubjectAppendingToName(current.getName()).get(0).getChoosedColor());
            icon.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN);
            holder.icon.setBackground(icon);
        } else {
            holder.icon.setImageResource(R.drawable.subject_default);
        }
        holder.subject.setText(current.getName().toString());
        NumberFormat formatter = NumberFormat.getNumberInstance();
        formatter.setMinimumFractionDigits(0);
        formatter.setMaximumFractionDigits(0);
        String output = formatter.format(dataBase.getSpecificChoosedSubjectAppendingToName(current.getName()).get(0).getAverage());
        int formattedValue = Integer.valueOf(output);

        //CHANGING COLOR DEPENDING ON VALUE
        int boxColor = 0;
        Drawable box = ContextCompat.getDrawable(context, R.drawable.markbox);
        Drawable boxBorder = ContextCompat.getDrawable(context, R.drawable.markbox_border);
        if (formattedValue >= 10) {
            boxColor = resources.getColor(R.color.positive);
        } else if (formattedValue >= 4 && formattedValue <= 9) {
            boxColor = resources.getColor(R.color.neutral);
        } else if (formattedValue < 4) {
            boxColor = resources.getColor(R.color.negative);
        }
        box.setAlpha(204);
        box.setColorFilter(boxColor, PorterDuff.Mode.SRC_IN);
        boxBorder.setColorFilter(boxColor, PorterDuff.Mode.SRC_IN);
        holder.markbox.setImageDrawable(box);
        holder.markboxBorder.setImageDrawable(boxBorder);

        holder.average.setText(output);
        holder.average.setTypeface(EasyFonts.robotoBlack(context));
    }
    @Override
    public int getItemCount() {
        return data.size();
    }

    public class ReportViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        TextView subject;
        ImageView icon;
        ImageView markbox;
        ImageView markboxBorder;
        TextView average;
        public ReportViewHolder(View itemView) {
            super(itemView);
            subject = (TextView) itemView.findViewById(R.id.report_subject);
            icon = (ImageView) itemView.findViewById(R.id.report_icon);
            markbox = (ImageView) itemView.findViewById(R.id.report_markbox);
            markboxBorder = (ImageView) itemView.findViewById(R.id.report_markbox_border);
            average = (TextView) itemView.findViewById(R.id.report_average);
            itemView.setOnClickListener(this);
        }
        @Override
        public void onClick(View v) {
            itemClickListener.onItemClick(v, this.getAdapterPosition());
        }
    }
}

谁知道该怎么做?谢谢你的帮助!!

这是一种缓存。来自Android文档:

如果你从相同的图像资源实例化两个Drawable对象,然后改变其中一个Drawables的属性(比如alpha),那么它也会影响另一个。所以当处理一个图像资源的多个实例时,你应该执行一个渐变动画,而不是直接转换Drawable。

Drawable.mutate()在创建后应该可以解决这个问题。

一个可变的可绘制对象保证不与任何其他可绘制对象共享其状态。当您需要修改从资源加载的可绘制对象的属性时,这尤其有用。默认情况下,从同一资源加载的所有drawables实例共享一个公共状态;如果你修改了一个实例的状态,所有其他实例都会收到同样的修改。

像这样:

Drawable box = ContextCompat.getDrawable(context, R.drawable.markbox).mutate();
Drawable boxBorder = ContextCompat.getDrawable(context, R.drawable.markbox_border).mutate();

感谢Sergey,他引导我找到了解决方案。我分享了我在onBindViewHolder方法中所做的。

final Drawable drawable = ContextCompat.getDrawable(mContext, R.drawable.ic_icon).mutate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    holder.image.setBackground(drawable);
} else {
    holder.image.setBackgroundDrawable(drawable);
}

如果你担心性能,仍然想要一些缓存,使用TintedIconCache——一个你可以从这个要点中抓取的类。

TintedIconCache cache = TintedIconCache.getInstance();
Drawable coloredIcon = cache.fetchTintedIcon(context, R.drawable.ic, R.color.color));

TintedIconCache是如何工作的?

它管理一个缓存,这样只有一个唯一着色的drawable实例被保存在内存中。它应该快速,并且内存高效

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

查看这个答案了解更多细节。


最新更新