在相冊應用中,默認只顯示圖片,點擊「刪除」按鈕時需要顯示覆蓋在 ImageView 上的 CheckBox。開發者使用 `gridView.getChildAt(0)` 獲取第一個 Item 視圖並操作 CheckBox 顯示,但發現第一個 Item 的 CheckBox 永遠無法顯示,而其他位置正常。
// ❌ 錯誤做法:直接操作視圖
View firstItem = gridView.getChildAt(0);
CheckBox cb = firstItem.findViewById(R.id.cb_select);
cb.setVisibility(View.VISIBLE); // 第一個 Item 經常失效
public class PhotoItem {
public String imagePath;
public boolean isSelected; // 選中狀態
public boolean isEditMode; // 編輯模式狀態
}
public class PhotoAdapter extends BaseAdapter {
private List<PhotoItem> data;
private boolean editMode = false;
public void setEditMode(boolean editMode) {
this.editMode = editMode;
notifyDataSetChanged(); // 關鍵:數據變更通知視圖更新
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.item_photo, parent, false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
PhotoItem item = data.get(position);
holder.imageView.setImageBitmap(loadImage(item.imagePath));
// 核心邏輯:根據數據模型決定 CheckBox 顯示
holder.checkBox.setVisibility(editMode ? View.VISIBLE : View.GONE);
holder.checkBox.setChecked(item.isSelected);
return convertView;
}
static class ViewHolder {
ImageView imageView;
CheckBox checkBox;
ViewHolder(View view) {
imageView = view.findViewById(R.id.iv_photo);
checkBox = view.findViewById(R.id.cb_select);
}
}
}
// 進入編輯模式
btnDelete.setOnClickListener(v -> {
adapter.setEditMode(true); // 一行代碼搞定所有 Item
btnDelete.setText("完成");
btnDelete.setTag("done");
});
// 退出編輯模式或執行刪除
btnDelete.setOnClickListener(v -> {
if ("done".equals(btnDelete.getTag())) {
// 收集選中項執行刪除
List<PhotoItem> toDelete = new ArrayList<>();
for (PhotoItem item : data) {
if (item.isSelected) toDelete.add(item);
}
data.removeAll(toDelete);
adapter.notifyDataSetChanged();
adapter.setEditMode(false);
btnDelete.setText("刪除");
btnDelete.setTag("delete");
}
});
<!-- item_photo.xml -->
<FrameLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="120dp">
<ImageView
android:id="@+id/iv_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />
<CheckBox
android:id="@+id/cb_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|end"
android:layout_margin="8dp"
android:visibility="gone" /> <!-- 默認隱藏 -->
</FrameLayout>
現代開發建議遷移至 `RecyclerView` + `GridLayoutManager`:
永遠不要使用 `getChildAt()` 直接操作列表項視圖。Android 列表視圖的設計初衷就是視圖復用和按需創建。正確的做法是:
這才是「數據驅動視圖」的正確實踐,也是避免無數顯示異常 Bug 的關鍵。