首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android ListView Header 防止重複點擊的正確姿勢

     編輯:程式設計綜合問答

在 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();
    }
}

為什麼 setClickable(false) 不生效?

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();
    }
}

方案二:視圖 Tag 狀態法

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();
    }
}

方案三:自訂 Header 視圖處理點擊(最徹底)

不使用 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:載入更多

關鍵點總結

  1. ListView 項目點擊攔截需在邏輯層判斷,而非視圖屬性
  2. 使用 boolean 標記或 View Tag 記錄加載狀態
  3. 異步任務完成時必須在主線程恢復狀態與 UI
  4. 考慮遷移至 RecyclerView + SwipeRefreshLayout 獲得更好體驗
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved