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

Android GridView 手勢滑動變色:GestureDetector + OnItemClickListener 衝突解決

     編輯:程式設計綜合問答

需求:在 GridView 上手指滑動,經過的 Item 背景顏色實時變化(如日曆選區效果)。開發者嘗試在 SimpleOnGestureListener.onScroll 中嵌套 setOnItemClickListener 並調用 adapter.getDropDownView 強制刷新,結果只有點擊有反應,滑動無效。

核心衝突分析

  • GestureDetector 攔截觸摸事件用於識別手勢,ListView/GridView 內部也需要觸摸事件處理滾動、點擊、選中。
  • 在 onScroll 中動態 setOnItemClickListener 違背單一職責,且 getDropDownView 是 Spinner 下拉視圖專用方法,GridView 不調用它。
  • Adapter 的 getView 才是列表項繪製入口,背景色必須在數據源變更後 notifyDataSetChanged() 觸發重繪。

正確實現方案:自定義 View + 觸摸事件分發

方案一:繼承 GridView 重寫 onTouchEvent(推薦)

public class SelectableGridView extends GridView {
    private int lastSelectedPos = -1;
    private OnItemSelectChangeListener listener;

    public SelectableGridView(Context context, AttributeSet attrs) { super(context, attrs); }

    @Override public boolean onTouchEvent(MotionEvent ev) {
        int action = ev.getActionMasked();
        int pos = pointToPosition((int)ev.getX(), (int)ev.getY());
        if (pos != INVALID_POSITION && pos != lastSelectedPos) {
            lastSelectedPos = pos;
            if (listener != null) listener.onItemSelected(pos);
        }
        return super.onTouchEvent(ev); // 保留原有滾動/點擊行為
    }

    public void setOnItemSelectChangeListener(OnItemSelectChangeListener l) { listener = l; }
    public interface OnItemSelectChangeListener { void onItemSelected(int position); }
}

方案二:Activity 中監聽並更新 Adapter 數據源

gridView.setOnItemSelectChangeListener(pos -> {
    // 更新數據源標記選中狀態
    for (int i = 0; i < dataList.size(); i++) {
        dataList.get(i).setSelected(i == pos);
    }
    adapter.notifyDataSetChanged(); // 觸發 getView 重繪
});

Adapter getView 中根據標記設置背景

@Override public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) { ... }
    ItemData data = getItem(position);
    holder.textView.setBackgroundColor(data.isSelected() ? Color.BLUE : Color.WHITE);
    return convertView;
}

關鍵點總結

  1. 不要在手勢回調裡套 setOnItemClickListener,職責混亂。
  2. 背景色變化 = 數據源狀態變更 + notifyDataSetChanged(),而非直接操作 View。
  3. 複雜手勢(滑動選區、長按拖拽)建議用 RecyclerView + ItemTouchHelper 或成熟庫。

掌握「數據驅動視圖」原則,觸摸事件只負責修改數據,UI 自動響應,才是 Android 列表交互的正道。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved