1. 程式人生 > >仿Android 原始碼處理長按事件

仿Android 原始碼處理長按事件

專案中有個需求:當用戶長按某個鍵,當有5秒的時候,提示使用者鬆手。需求非常簡單,如何用簡單高效的方法來實現呢?

剛開始是打算用個計時器,如果計時達到了5s,就提示使用者鬆手,後面回想android button的長按點選事件,它又是如何實現的呢?

view 的長按點選事件部分原始碼:

//這是一個runnable
private CheckForLongPress mPendingCheckForLongPress;


private final class CheckForLongPress implements Runnable {
        private int mOriginalWindowAttachCount;
        private
float mX; private float mY; @Override public void run() { if (isPressed() && (mParent != null) && mOriginalWindowAttachCount == mWindowAttachCount) { if (performLongClick(mX, mY)) { mHasPerformedLongPress = true
; } } } public void setAnchor(float x, float y) { mX = x; mY = y; } public void rememberWindowAttachCount() { mOriginalWindowAttachCount = mWindowAttachCount; } } //初始化的地方: private void checkForLongClick
(int delayOffset, float x, float y) { if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { mHasPerformedLongPress = false; if (mPendingCheckForLongPress == null) { mPendingCheckForLongPress = new CheckForLongPress(); } mPendingCheckForLongPress.setAnchor(x, y); mPendingCheckForLongPress.rememberWindowAttachCount(); //關鍵是這個postDelay:500ms之後,執行runnable postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout() - delayOffset); } }

從上面原始碼中推斷出:當用戶按下的時候,過500ms post 一個runnable, 如果在500ms的時候,使用者一直都是沒有鬆手的狀態,那麼就設定longclicklistener,否則就不是長按事件。當然原始碼比這個複雜,但是大致思路是這樣的,同理,我們也仿照這個流程來做:

public class LongPressActivity extends Activity implements View.OnTouchListener{

    private Button mButton;
    private CheckForLongPress1 mCheckForLongPress1;
    private volatile boolean  isLongPressed = false;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_long_press);
        mButton = (Button) findViewById(R.id.btn_long);
        mCheckForLongPress1 = new CheckForLongPress1();
        mButton.setOnTouchListener(this);

    }


    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                Log.d("hxy","action down");
                isLongPressed = true;
                mButton.postDelayed(mCheckForLongPress1,5000);
                break;
            case MotionEvent.ACTION_MOVE:
                isLongPressed = true;
                break;
            case MotionEvent.ACTION_UP:
                isLongPressed = false;
                Log.d("hxy","action up");
                break;

        }

        return super.onTouchEvent(event);
    }

    private class CheckForLongPress1 implements Runnable{

        @Override
        public void run() {
            //5s之後,檢視isLongPressed的變數值:
            if(isLongPressed){//沒有做up事件
                Log.d("hxy","5s的事件觸發");
            }else{
                mButton.removeCallbacks(mCheckForLongPress1);
            }
        }
    }

}