首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

Android Scroller 實現 ListView 項目滑動刪除(QQ 風格)

     編輯:C++ 入門

設計思路

  • Item 內部用 Scroller 處理水平滑動(前景 + 背景刪除按鈕)。
  • ListView 攔截觸摸事件:判斷是垂直滾動列表還是水平滑動 Item。
  • 點擊事件傳遞:dispatchTouchEvent 中檢測 ACTION_UP 且未被消費,手動調用 performItemClick 觸發 OnItemClickListener。

Item View (ListItemDelete) 關鍵代碼

public class ListItemDelete extends LinearLayout {
    private Scroller mScroller;
    private float mLastMotionX, downX;
    private int backWidth; // 背景視圖寬度(刪除按鈕區域)

    @Override protected void onMeasure(...) { // 測量背景寬度
        for (int i=0; i backWidth/2) smoothScrollTo(backWidth, 0); // 彈開
                else smoothScrollTo(0, 0); // 彈回
                return Math.abs(x - downX) >= 5; // 小於5視為點擊,返回false讓ListView處理
            case MotionEvent.ACTION_CANCEL: smoothScrollTo(0, 0); break;
        }
        return true;
    }

    private void smoothScrollTo(int destX, int destY) {
        mScroller.startScroll(getScrollX(), 0, destX - getScrollX(), 0, 300);
        invalidate();
    }

    @Override public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
        }
    }

    @Override protected void onLayout(...) { // 水平排列子View
        int left = 0;
        for (View v : children) if (v.getVisibility() != GONE) {
            v.layout(left, 0, left + v.getMeasuredWidth(), v.getMeasuredHeight());
            left += v.getMeasuredWidth();
        }
    }
}

ListView (ScrollListviewDelete) 觸摸分發

@Override public boolean onInterceptTouchEvent(MotionEvent ev) {
    return isIntercept(ev); // 返回true攔截給Item,false給ListView滾動
}

@Override public boolean dispatchTouchEvent(MotionEvent ev) {
    boolean handled = super.dispatchTouchEvent(ev);
    if (ev.getAction() == MotionEvent.ACTION_UP && !handled) {
        int pos = pointToPosition((int)ev.getX(), (int)ev.getY());
        View v = getChildAt(pos);
        performItemClick(v, pos, v.getId()); // 手動觸發ItemClick
    }
    return handled;
}

private boolean isIntercept(MotionEvent ev) {
    float x = ev.getX(), y = ev.getY();
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN: lastX=x; lastY=y; break;
        case MotionEvent.ACTION_MOVE:
            if (!isLock) {
                if (Math.abs(x-lastX) > Math.abs(y-lastY) && Math.abs(x-lastX) > 10) {
                    isLock = true; return false; // 攔截給Item水平滑動
                }
            } else return false;
            break;
        case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: isLock=false; break;
    }
    return true; // 默認不攔截,ListView垂直滾動
}

XML 佈局結構

<ListItemDelete ...>
    <LinearLayout android:id="@+id/front" ...> <!-- 前景內容 --> </LinearLayout>
    <LinearLayout ...> <!-- 背景刪除按鈕 -->
        <Button android:id="@+id/btnDelete" ... />
    </LinearLayout>
</ListItemDelete>

效果演示

滑動刪除動圖

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