在 ListView 的 HeaderView 中實現「點擊刷新,加載中禁用點擊,完成恢復」的交互,不能單純依賴 setClickable(false),需結合狀態標記或視圖狀態管理。
protected void onListItemClick(ListView l, View v, int position, long id) {
if (position == 0) { // Header
ProgressBar pb = v.findViewById(R.id.refresh_progress);
pb.setVisibility(View.VISIBLE);
TextView tv = v.findViewById(R.id.load);
tv.setVisibility(View.GONE);
v.setClickable(false); // 無效!ListView 不會檢查子視圖 clickable
new DownloadTask(v, "Old Message").execute();
}
}
ListView.onItemClick 是通過檢測項目視圖的點擊事件分發的,不受子視圖 clickable 屬性影響。即使設置 setEnabled(false) 也不會阻止 onListItemClick 回調。
// 成員變量記錄 Header 是否正在加載
private boolean isHeaderLoading = false;
protected void onListItemClick(ListView l, View v, int position, long id) {
if (position == 0 && !isHeaderLoading) {
isHeaderLoading = true;
// 更新 UI
ProgressBar pb = v.findViewById(R.id.refresh_progress);
pb.setVisibility(View.VISIBLE);
TextView tv = v.findViewById(R.id.load);
tv.setVisibility(View.GONE);
new DownloadTask(new DownloadCallback() {
@Override
public void onFinish() {
isHeaderLoading = false;
// 恢復 UI
runOnUiThread(() -> {
pb.setVisibility(View.GONE);
tv.setVisibility(View.VISIBLE);
});
}
}).execute();
}
}
protected void onListItemClick(ListView l, View v, int position, long id) {
if (position == 0) {
Boolean loading = (Boolean) v.getTag(R.id.tag_loading);
if (loading != null && loading) return; // 正在加載
v.setTag(R.id.tag_loading, true);
// 更新 UI...
new DownloadTask(() -> {
runOnUiThread(() -> v.setTag(R.id.tag_loading, false));
}).execute();
}
}
不使用 onListItemClick,而是在 Header 視圖內部設置 OnClickListener:
// 在 getView 或構建 Header 時
View headerView = inflater.inflate(R.layout.list_header, listView, false);
headerView.findViewById(R.id.header_click_area).setOnClickListener(v -> {
if (isHeaderLoading) return;
isHeaderLoading = true;
// 更新 UI、啟動任務...
});
listView.addHeaderView(headerView);
手動點擊 Header 刷新已非主流,建議使用:
SwipeRefreshLayout:原生下拉刷新SmartRefreshLayout:功能豐富的第三方庫RecyclerView + OnScrollListener:載入更多boolean 標記或 View Tag 記錄加載狀態RecyclerView + SwipeRefreshLayout 獲得更好體驗