在RecyclerView中更改单个drawable的颜色将更改所有drawable

时间:2015-08-11 14:26:40

标签: android colors android-recyclerview android-drawable

我只是试图根据一个值改变我的行内部drawable的颜色,但是不是一个drawable,适配器改变了所有颜色。

这是我的适配器:

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

    }

}

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

3 个答案:

答案 0 :(得分:23)

它的缓存。来自Android docs

  

如果您从同一图像资源中实例化两个Drawable对象,则更改其中一个Drawable的属性(例如alpha),然后它也会影响另一个。因此,在处理图像资源的多个实例时,不应直接转换Drawable,而应执行补间动画。

创建后

Drawable.mutate()应解决问题。

  

保证不变的drawable不与任何其他drawable共享其状态。当您需要修改从资源加载的drawable的属性时,这尤其有用。默认情况下,从同一资源加载的所有drawables实例共享一个公共状态;如果修改一个实例的状态,则所有其他实例将收到相同的修改。

这样的事情:

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

答案 1 :(得分:1)

TL;DR。如果您担心性能并且仍然想要一些缓存,请使用 TintedIconCache - 您可以grab from this gist 的单个类。

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

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

查看this answer了解更多详情。


考虑查看 gist 以了解其内部工作原理。

答案 2 :(得分:0)

感谢谢尔盖指导我解决问题。我分享了我在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);
}