4

我正在创建一个带有RecyclerView. 每个列表项都是来自用户的帖子(现在是硬编码)。每篇文章的背景都是从layer-list可绘制文件夹中的 XML 文件加载的。

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

第一项总是获取XML 文件中调用solidshape内部颜色指定的背景颜色,因此不会更改,但以下各项获取颜色。itemshape_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));
        }

    }

}

为什么第一项的背景没有改变,而文本却改变了?

先感谢您!

4

3 回答 3

4

在您的onBindViewHolder,获取您的视图(从持有人),您需要更改背景颜色并获取其当前背景(可绘制气泡,您已经在 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"));
于 2016-12-29T05:36:52.503 回答
4

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

但是 holderView 没有刷新。

也许你应该打电话

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

刷新 holderView

于 2016-12-29T05:46:44.997 回答
3

你在这里有两个不同的问题。

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

第二 - 你改变 R.drawable.bubble 静态。即使在突变之后,Android 也可以缓存和重用它。当您开始为不同的项目使用不同的颜色时,它可能会导致另一个问题。

要解决第二个问题,您必须android.graphics.drawable.Drawable#mutate每次都先调用它,然后再对其进行变异。

默认情况下,从同一资源加载的所有可绘制实例共享一个公共状态;如果您修改一个实例的状态,所有其他实例将收到相同的修改。

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

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()通过从层移动到形状可以稍微简化。

于 2016-12-29T16:10:23.127 回答