Android RecyclerView 未以编程方式更改第一项的背景颜色
Android RecyclerView not changing background color on first item programmatically
我正在创建一个包含 RecyclerView
的列表。
每个列表项都是来自用户的 post(现在已硬编码)。
每个 post 的背景都是从 drawable 文件夹中的 layer-list
XML 文件加载的。
文本等一切都按预期工作,但我正在尝试以编程方式更改背景颜色。它改变了每个项目的背景颜色,除了第一个项目,我不知道为什么。
第一项始终获得由 item
中 shape
的 solid
颜色指定的背景颜色,在 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()
从图层移动到形状来稍微简化。
我正在创建一个包含 RecyclerView
的列表。
每个列表项都是来自用户的 post(现在已硬编码)。
每个 post 的背景都是从 drawable 文件夹中的 layer-list
XML 文件加载的。
文本等一切都按预期工作,但我正在尝试以编程方式更改背景颜色。它改变了每个项目的背景颜色,除了第一个项目,我不知道为什么。
第一项始终获得由 item
中 shape
的 solid
颜色指定的背景颜色,在 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()
从图层移动到形状来稍微简化。