英文:
RecyclerView Color Change Deletion Bug
问题
我正在创建一个学校计划应用程序,以便将从房间数据库中读取的作业显示在RecyclerView中。每个项目行都有作业名称、类型和截止日期,以及一个删除按钮。每个项目行的背景在作业过期时变为红色,在作业今天到期时变为绿色,在将来到期时(今天之后)保持默认颜色。我遇到的问题是,当一个具有颜色(红色或绿色)的作业位于具有不同颜色的作业之上时,删除具有颜色的作业时,下面的作业会更改为先前已删除作业的颜色。如果重新启动应用程序或启动另一个活动,然后再次拉起RecyclerView,作业将恢复到其正确的颜色。
[更新] 不知道这是否会影响问题,但我用于RecyclerView的item_row.xml
文件未使用CardView
这是我更改颜色的方法:
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
// 从数据库列表中获取当前位置处的数据库表
AssignmentTable assignmentTable = assignmentList.get(position);
// 实例化视图
String due = "截止日期:" + assignmentTable.dueDate;
String type = assignmentTable.type;
holder.txtItemName.setText(assignmentTable.name);
holder.txtItemDate.setText(due);
holder.txtItemType.setText(type);
// 将复选框设置为其保存的状态
if(assignmentTable.isCompleted == true){
holder.checkBox.setChecked(true);
}else {
holder.checkBox.setChecked(false);
}
// 获取当前截止日期并解析
Date currentDate = getCurrentDate();
String dueDateAsString = assignmentTable.dueDate;
Date dueDateOfCurrentAssignment = parseDate(dueDateAsString);
// 以编程方式更改背景颜色
if(currentDate.equals(dueDateOfCurrentAssignment)){
holder.txtItemDate.setText("截止日期:今天"); // 更改截止日期
holder.itemView.setBackgroundColor(Color.parseColor("#228b22")); // 更改颜色为绿色
Log.d("已到达", "绿色");
}
if(dueDateOfCurrentAssignment.before(currentDate)){
holder.itemView.setBackgroundColor(Color.parseColor("#8b0000")); // 背景变为红色
holder.txtItemDate.setTextColor(Color.parseColor("#ff7a7a")); // 文本变为亮红色
Log.d("已到达", "红色");
}
// 记录字段
String assignment = "\n名称:" + assignmentTable.name + "\n截止日期:" + assignmentTable.dueDate
+ "\n类型:" + assignmentTable.type + "\n已完成:" + assignmentTable.isCompleted;
Log.d("在ONBIND结束时", "\n" + assignment);
}
这是在删除按钮的onClick
上调用的方法。
@Override
public void onClick(View view) {
// 获取要删除的指定位置的数据库表
int position = getAdapterPosition();
AssignmentTable assignmentTable = assignmentList.get(position);
ItemRepository itemRepository = new ItemRepository(view.getContext());
// 从数据库中删除
itemRepository.deleteItem(assignmentTable);
itemRepository.updateItem(assignmentTable);
notifyDataSetChanged();
Toast.makeText(view.getContext(),"已删除!",Toast.LENGTH_SHORT).show();
}
英文:
I am creating a school planner app and to display the assignments I am reading from a room database into a RecyclerView. Each item row has the assignment name, type, and due date, as well as a delete button. Each item row's background turns Red if the assignment is overdue, Green if the assignment is due today, and the default color if the assignment is due in the future (past today). The bug I am running into happens when an assignment that is a color(red or green) is on top of an assignment with a different color. When the assignment that is colored is deleted, the assignment below is changed to the color of the previously deleted assignment. If the app is restarted or another activity is started and then the RecyclerView is pulled up again, the assignment is back to its correct color.
[Update] Don't know whether or not this affects the issue but my item_row.xml
file for the RecyclerView
does not use CardView
Here is the method where I change the color:
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
//Fetching the database table at the current position from database list
AssignmentTable assignmentTable = assignmentList.get(position);
//Instantiating the views
String due = "Due: "+assignmentTable.dueDate;
String type = assignmentTable.type;
holder.txtItemName.setText(assignmentTable.name);
holder.txtItemDate.setText(due);
holder.txtItemType.setText(type);
//Setting the checkboxes to their saved state
if(assignmentTable.isCompleted == true){
holder.checkBox.setChecked(true);
}else {
holder.checkBox.setChecked(false);
}
//Fetching current due date and parsing
Date currentDate = getCurrentDate();
String dueDateAsString = assignmentTable.dueDate;
Date dueDateOfCurrentAssignment = parseDate(dueDateAsString);
//changing the background color programmatically
if(currentDate.equals(dueDateOfCurrentAssignment)){
holder.txtItemDate.setText("Due: Today"); //changes due date
holder.itemView.setBackgroundColor(Color.parseColor("#228b22")); // changes color to green
Log.d("REACHED", "GREEN COLOR");
}
if(dueDateOfCurrentAssignment.before(currentDate)){
holder.itemView.setBackgroundColor(Color.parseColor("#8b0000")); // turns the background red
holder.txtItemDate.setTextColor(Color.parseColor("#ff7a7a")); // turns text bright red
Log.d("REACHED", "RED COLOR");
}
//Logging fields
String assignment = "\nName: " + assignmentTable.name + "\nDue Date: " + assignmentTable.dueDate
+ "\nType: " + assignmentTable.type + "\nCompleted: " + assignmentTable.isCompleted;
Log.d("AT END OF ONBIND", "\n" + assignment);
}```
and here is the method called on the delete buttons onClick.
@Override
public void onClick(View view) {
//Getting database table at the specified position to delete
int position = getAdapterPosition();
AssignmentTable assignmentTable = assignmentList.get(position);
ItemRepository itemRepository = new ItemRepository(view.getContext());
//Deleting from the database
itemRepository.deleteItem(assignmentTable);
itemRepository.updateItem(assignmentTable);
notifyDataSetChanged();
Toast.makeText(view.getContext(),"Deleted!",Toast.LENGTH_SHORT).show();
}```
答案1
得分: 0
在你的删除方法中调用了notifyDataSetChanged
。你还应该调用notifyItemRemoved(position)
。
关于此事,文档中的解释如下:
通知任何已注册的观察者,数据集中先前位于 position 处的项已从数据集中删除。
希望能成功!
英文:
While you are calling notifyDataSetChanged
in your delete method. You should also call notifyItemRemoved(position)
.
Here is what documentation says about it:
> Notify any registered observers that the item previously located at position has been removed from the data set.
Hope it works out!
答案2
得分: 0
修复了问题!原来我只需要在 OnBindViewHolder();
方法内添加一个额外的 else 语句。
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
// 从数据库列表中获取当前位置的数据库表
AssignmentTable assignmentTable = assignmentList.get(position);
// 实例化视图
String due = "截止日期:" + assignmentTable.dueDate;
String type = assignmentTable.type;
holder.txtItemName.setText(assignmentTable.name);
holder.txtItemDate.setText(due);
holder.txtItemType.setText(type);
// 将复选框设置为其保存的状态
if (assignmentTable.isCompleted == true) {
holder.checkBox.setChecked(true);
} else {
holder.checkBox.setChecked(false);
}
// 获取当前截止日期并解析
Date currentDate = getCurrentDate();
String dueDateAsString = assignmentTable.dueDate;
Date dueDateOfCurrentAssignment = parseDate(dueDateAsString);
// 以编程方式更改背景颜色
if (currentDate.equals(dueDateOfCurrentAssignment)) {
holder.txtItemDate.setText("截止日期:今天"); // 更改截止日期
holder.txtItemDate.setTextColor(Color.parseColor("#ff0000"));
holder.itemView.setBackgroundColor(Color.parseColor("#228b22")); // 更改颜色为绿色
Log.d("已达到", assignmentTable.name + " 绿色背景");
} else if (dueDateOfCurrentAssignment.before(currentDate)) {
holder.itemView.setBackgroundColor(Color.parseColor("#8b0000")); // 背景变为红色
holder.txtItemDate.setTextColor(Color.parseColor("#ff7a7a")); // 文本变为亮红色
Log.d("已达到", assignmentTable.name + " 红色背景");
} else {
holder.itemView.setBackgroundColor(Color.parseColor("#191970"));
holder.txtItemDate.setTextColor(Color.parseColor("#ff0000"));
Log.d("已达到", assignmentTable.name + " 常规背景");
}
// 记录字段
String assignment = "\n名称:" + assignmentTable.name + "\n截止日期:" + assignmentTable.dueDate + "\n类型:" +
assignmentTable.type + "\n已完成:" + assignmentTable.isCompleted;
Log.d("在ONBIND结束时", "\n" + assignment);
}
英文:
Fixed the issue! Turns out I just needed to add an extra else statement wihtin the OnBindViewHolder();
method
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
//Fetching the database table at the current position from database list
AssignmentTable assignmentTable = assignmentList.get(position);
//Instantiating the views
String due = "Due: "+assignmentTable.dueDate;
String type = assignmentTable.type;
holder.txtItemName.setText(assignmentTable.name);
holder.txtItemDate.setText(due);
holder.txtItemType.setText(type);
//Setting the checkboxes to their saved state
if(assignmentTable.isCompleted == true){
holder.checkBox.setChecked(true);
}else {
holder.checkBox.setChecked(false);
}
//Fetching current due date and parsing
Date currentDate = getCurrentDate();
String dueDateAsString = assignmentTable.dueDate;
Date dueDateOfCurrentAssignment = parseDate(dueDateAsString);
//changing the background color programmatically
if(currentDate.equals(dueDateOfCurrentAssignment)){
holder.txtItemDate.setText("Due: Today"); //changes due date
holder.txtItemDate.setTextColor(Color.parseColor("#ff0000"));
holder.itemView.setBackgroundColor(Color.parseColor("#228b22")); // changes color to green
Log.d("REACHED", assignmentTable.name + " GREEN COLOR");
}else if(dueDateOfCurrentAssignment.before(currentDate)){
holder.itemView.setBackgroundColor(Color.parseColor("#8b0000")); // turns the background red
holder.txtItemDate.setTextColor(Color.parseColor("#ff7a7a")); // turns text bright red
Log.d("REACHED", assignmentTable.name + " RED COLOR");
}else{
holder.itemView.setBackgroundColor(Color.parseColor("#191970"));
holder.txtItemDate.setTextColor(Color.parseColor("#ff0000"));
Log.d("REACHED", assignmentTable.name + " REGULAR BACKGROUND");
}
//Logging fields
String assignment = "\nName: " + assignmentTable.name + "\nDue Date: " + assignmentTable.dueDate + "\nType: " +
assignmentTable.type + "\nCompleted: " + assignmentTable.isCompleted;
Log.d("AT END OF ONBIND", "\n" + assignment);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论