仿Android 原始碼處理長按事件
阿新 • • 發佈:2019-01-06
專案中有個需求:當用戶長按某個鍵,當有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);
}
}
}
}