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