ListView 項目含 Button A/B,點擊 Button A 隱藏它。滾動後,其他項目的 Button A 也莫名隱藏,或隱藏狀態錯亂。
ListView 回收 convertView,同一視圖對象被重用於不同位置setVisibility),複用時狀態隨視圖移動getView 時根據模型恢復視圖狀態
// 1. 數據模型增加狀態字段
class TaskItem {
String title;
boolean isButtonAVisible = true; // 默認可見
}
// 2. Adapter 綁定時恢復狀態
public class TaskAdapter extends BaseAdapter {
private List items;
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_task, parent, false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
TaskItem item = items.get(position);
holder.tvTitle.setText(item.title);
// 關鍵:根據模型設置 Button 狀態
holder.btnA.setVisibility(item.isButtonAVisible ? View.VISIBLE : View.GONE);
// 關鍵:點擊更新模型,刷新單項
holder.btnA.setOnClickListener(v -> {
item.isButtonAVisible = false;
notifyItemChanged(position); // BaseAdapter 用 notifyDataSetChanged()
});
return convertView;
}
}
若不想修改模型類,用獨立映射存儲狀態:
private SparseBooleanArray buttonAVisibleMap = new SparseBooleanArray();
// 初始化默認 true
for (int i = 0; i < items.size(); i++) buttonAVisibleMap.put(i, true);
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// ...
boolean visible = buttonAVisibleMap.get(position, true);
holder.btnA.setVisibility(visible ? View.VISIBLE : View.GONE);
holder.btnA.setOnClickListener(v -> {
buttonAVisibleMap.put(position, false);
notifyDataSetChanged(); // 或局部刷新
});
}
class TaskAdapter extends ListAdapter
extends ListAdapter(DIFF_CALLBACK) {
static final DiffUtil.ItemCallback DIFF_CALLBACK =
new DiffUtil.ItemCallback() {
@Override boolean areItemsTheSame(TaskItem old, TaskItem n) {
return old.id == n.id;
}
@Override boolean areContentsTheSame(TaskItem old, TaskItem n) {
return old.equals(n); // 包含 isButtonAVisible 比較
}
};
class VH extends RecyclerView.ViewHolder {
Button btnA;
VH(View v) { super(v); btnA = v.findViewById(R.id.btnA); }
void bind(TaskItem item) {
btnA.setVisibility(item.isButtonAVisible ? View.VISIBLE : View.GONE);
btnA.setOnClickListener(v -> {
// 創建新對象觸發 DiffUtil 更新
TaskItem updated = new TaskItem(item.id, item.title, false);
// 假設列表在 ViewModel 中,通過 LiveData 更新
viewModel.updateItem(updated);
});
}
}
}
notifyDataSetChanged() 導致閃爍