Android RecyclerView не меняет цвет фона для первого элемента программно

Я создаю список с RecyclerView, Каждый элемент списка - это сообщение пользователя (прямо сейчас жестко запрограммировано). Фон для каждого сообщения загружается из layer-list Файл XML в папке drawable.

С текстами и т. Д. Все работает как положено, но я пытаюсь программно изменить цвет фона. Он меняет цвет фона для каждого элемента, кроме первого, и я не могу понять, почему.

Первый элемент всегда получает цвет фона, указанный solid цвет shape внутри item называется shape_background в файле XML, поэтому он не изменяется, но следующие элементы получают цвет #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));
        }

    }

}

Почему фон первого элемента не изменился, а тексты?

Заранее спасибо!

3 ответа

Решение

На ваше 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"));

Ты звонил holder.shape.setColor(color);

но держатель View не обновился.

может тебе стоит позвонить

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

обновить держатель View

У вас есть две разные проблемы здесь.

Во-первых, вы сами изменяете рисование, а не просматриваете фон. Это решается любаоюа и виньеш сундар ответами.

Второе - вы меняете R.drawable.bubble статически. Android может кешировать и повторно использовать его даже после мутации. Это может привести к другим проблемам, когда вы начнете использовать разные цвета для разных предметов.

Чтобы решить второй вопрос, вы должны позвонить android.graphics.drawable.Drawable#mutate каждый раз, прежде чем сначала мутировать его.

По умолчанию все экземпляры drawables, загруженные из одного и того же ресурса, имеют общее состояние; если вы измените состояние одного экземпляра, все остальные экземпляры получат такую ​​же модификацию.

Так это должно выглядеть примерно так:

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() от слоя к форме.

Другие вопросы по тегам