Android RecyclerView 未以编程方式更改第一项的背景颜色

Android RecyclerView not changing background color on first item programmatically

我正在创建一个包含 RecyclerView 的列表。 每个列表项都是来自用户的 post(现在已硬编码)。 每个 post 的背景都是从 drawable 文件夹中的 layer-list XML 文件加载的。

文本等一切都按预期工作,但我正在尝试以编程方式更改背景颜色。它改变了每个项目的背景颜色,除了第一个项目,我不知道为什么。

第一项始终获得由 itemshapesolid 颜色指定的背景颜色,在 XML 文件中称为 shape_background , 所以它没有改变,但以下项目获得颜色 #ff22ff.

这是适配器的实现:

class PostListAdapter extends RecyclerView.Adapter<PostListAdapter.PostViewHolder>{

    private LayoutInflater inflater;
    private List<PostRow> data = Collections.emptyList();

    PostListAdapter(Context context, List<PostRow> data) {
        inflater = LayoutInflater.from(context);
        this.data = data;
    }

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

        PostRow current = data.get(position);
        holder.text.setText(current.text.toUpperCase());
        holder.time.setText(current.time.toUpperCase());
        holder.answers.setText(current.answers.toUpperCase());

        try {
            // "#ff22ff" will be changed to current.color, unique color for every post
            // That string is parsed from a JSON request, hence the try-catch.
            int color = Color.parseColor("#ff22ff"); 
            holder.shape.setColor(color);
        } catch (Exception e){
            e.printStackTrace();
        }

    }

    @Override
    public PostViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = inflater.inflate(R.layout.post_row, parent, false);
        return new PostViewHolder(view);
    }

    @Override
    public int getItemCount() {
        return data.size();
    }

    class PostViewHolder extends RecyclerView.ViewHolder {

        TextView text;
        TextView time;
        TextView answers;
        GradientDrawable shape;

        PostViewHolder(View itemView) {
            super(itemView);
            text = (TextView) itemView.findViewById(R.id.text);
            time = (TextView) itemView.findViewById(R.id.time);
            answers = (TextView) itemView.findViewById(R.id.answers);
            LayerDrawable layers = (LayerDrawable) ContextCompat.getDrawable(itemView.getContext(), R.drawable.bubble);

            shape = (GradientDrawable) (layers.findDrawableByLayerId(R.id.shape_background));
        }

    }

}

为什么第一项的背景没变,文字却变了?

提前致谢!

在您的 onBindViewHolder 上,获取您的视图(来自 holder),因为您需要更改背景颜色并获取其当前背景(可绘制的气泡,您已经在 XML 属性中设置)

LayerDrawable layerDrawable = (LayerDrawable) yourView.getBackground().getCurrent();
GradientDrawable gradientDrawable = (GradientDrawable) layerDrawable.findDrawableByLayerId(R.id. shape_background).getCurrent();
// set you color based on position
gradientDrawable.setColor(Color.parseColor("#ff22ff"));

你打过电话holder.shape.setColor(color);

但是holderView没有刷新。

也许你应该打电话给

holder.itemView.setBackgroundDrawable( ContextCompat.getDrawable(itemView.getContext(), R.drawable.bubble))

刷新 holderView

这里有两个不同的问题。

首先 - 您更改可绘制对象本身但不更改视图背景。由 liubaoyua 和 Vignesh Sundar answers 解决。

其次 - 您静态更改 R.drawable.bubble。 Android 即使在变异后也可以缓存和重用它。当您开始为不同的项目使用不同的颜色时,它可能会导致其他问题。

要解决第二个问题,您必须在第一次变异之前每次调用 android.graphics.drawable.Drawable#mutate

By default, all drawables instances loaded from the same resource share a common state; if you modify the state of one instance, all the other instances will receive the same modification.

所以它应该看起来像这样:

class PostViewHolder extends RecyclerView.ViewHolder {

    TextView text;
    TextView time;
    TextView answers;
    LayerDrawable layers;
    GradientDrawable shape;

    PostViewHolder(View itemView) {
        super(itemView);

        text = (TextView) itemView.findViewById(R.id.text);
        time = (TextView) itemView.findViewById(R.id.time);
        answers = (TextView) itemView.findViewById(R.id.answers);

        layers = (LayerDrawable) ContextCompat
                .getDrawable(itemView.getContext(), R.drawable.bubble)
                .mutate();

        shape = (GradientDrawable) layers.findDrawableByLayerId(R.id.shape_background);
        itemView.setBackground(layers);
    }

    void setColor(Color color) {
        shape.setColor(color);
        itemView.setBackgroundDrawable(layers);
    }
}

可能可以通过将 .mutate() 从图层移动到形状来稍微简化。