2012-03-12 20 views
7

Tôi đang tạo softkeyboard cho Android 2.2 trở lên. mọi thứ đều ổn nhưng khi tôi gõ thực sự nhanh thì một thời gian phương pháp ACTION_DOWN của tôi không gọi. dòng chảy thực tế của phương pháp gọi là sẽ giống nhưSoftKeyboard cho android

    1) motionEvent.ACTION_DOWN 
        2) OnPress() 
        3) motionEvent.ACTION_UP 
        4) OnRelease() and repeat same order for next word. 

nếu tôi gõ ở tốc độ bình thường sau đó nó hoạt động tốt nhưng nếu tôi gõ nhanh sau đó trên tự thực hiện phương pháp trông giống như

    1) motionEvent.ACTION_DOWN 
       2) OnPress() 
       3) OnRelease() 
       4) motionEvent.ACTION_UP and for next word OnPress and OnRelease() methods are being called. 

bất cứ đề nghị?

Sửa Lớp học của tôi LatinKeyboardView chứa MotionActionEvents

enter code here @Override 
public boolean onTouchEvent(MotionEvent me) { 
    // Moved next line and added lines to help solve reentrant problem. 
    int action = me.getAction(); 
    // next 2 lines required for multitouch Andr 2+ 
    int act = action & MotionEvent.ACTION_MASK; 
    final int ptrIndex = (act & MotionEvent.ACTION_POINTER_ID_MASK) //Renamed to ACTION_POINTER_INDEX_MASK in later Andro versions 
    >> MotionEvent.ACTION_POINTER_ID_SHIFT;//Renamed to ACTION_POINTER_INDEX_SHIFT in later Andro versions 

//  currentX = me.getX(); 
//  currentY = me.getY(); 
     calcMinSlide(); 

//  int act = me.getAction(); 
     if (act == android.view.MotionEvent.ACTION_DOWN) { 
      Log.v(tag, "ANGLE_ACTION_DOWN : "); 


     if (pw != null) { 
      pw.dismiss(); 
      pw = null; 
     } 
     lastDirection = direction = 0; 
     touchDownPoint.set(me.getX(), me.getY()); 

     // Will added next two lines 
     touchDragPoint.set(me.getX(), me.getY()); 
     thresholdPoint.set(me.getX(), me.getY()); 
     // Will6 added to improve accuracy 
     thresholdPoint1_5 = false; 
     // Will7 added next 4 for Andro 2+ 
     currentX = me.getX(); 
     currentY = me.getY(); 
     // Save the ID of this first pointer (touch) down 
     currentPointerID = me.getPointerId(0); 
     nextPointerID = INVALID_POINTER_ID; 

     previousDownTime = me.getEventTime(); 
     me.setLocation(touchDownPoint.x, touchDownPoint.y); 
     // start timer on touch down 
     startTimer(me, 300); // 150); Will7 changed this and removed method: checkLongPress 

    } else if (act == android.view.MotionEvent.ACTION_UP 
       || act == android.view.MotionEvent.ACTION_MOVE) { 

     Log.v(tag, "ANGLE_ACTION_UP : "); 
     //touchdragPoint and previoustouchPoint for calculating velocity 
     PointF previousTouchPoint = new PointF(touchDragPoint.x,touchDragPoint.y); 

     //Will7 added next if for Andro 2+: Find the index of the active pointer and fetch its position 
     if (act == android.view.MotionEvent.ACTION_MOVE && me.getPointerId(ptrIndex) != currentPointerID) { 
      //Log.v(tag, "Cancel ATION_MOVE!! ID: "+me.getPointerId(ptrIndex)); 
      return super.onTouchEvent(me); 
     } 
     touchDragPoint.set(me.getX(), me.getY());   
     dy = me.getY() - touchDownPoint.y; 
     dx = me.getX() - touchDownPoint.x; 

     // added for Andro 2+ 
     currentX = touchDragPoint.x; 
     currentY = touchDragPoint.y; 

     //calculate time interval from down time to current time 
     long timeInterval = me.getEventTime() - previousDownTime; 
     previousDownTime = me.getEventTime(); 
     velocityThresDir = VELOCITY_THRESHOLD; 
     float touchVelocity = Math.abs(distanceBetweenPoints(touchDragPoint, previousTouchPoint)/timeInterval); 

     if (distanceFromCenter(dx,dy) > minSlide) { 
//    Log.v(tag, "direction to detect angle....after... dx..."+dx+" dy "+dy); 
       //Log.v(tag, "ANGLE angle.... after..."+distanceFromCenter(dx,dy)+" slide distance "+ minSlide); 


      /* cancel the timer*/ 
      if (cDownTimer != null) { 
       cDownTimer.cancel(); 
       cDownTimer = null; 
      } 
      /* coding for calculating velocity threshold*/   
      float angleThreshold = 0.0f; 
      if ((thresholdPoint.x == touchDownPoint.x) && (thresholdPoint.y == touchDownPoint.y)){ 
       thresholdPoint.set(touchDragPoint.x, touchDragPoint.y); 
      } 
      else { 
       //Will6 - added next if to improve accuracy 
       if ((distanceFromCenter(dx,dy) > (minSlide * 1.5)) && !thresholdPoint1_5){ 
        thresholdPoint.set(me.getX(),me.getY()); 
        thresholdPoint1_5 = true; 
       } 
       float angleP1= calcAngle(touchDownPoint, thresholdPoint); 
       float angleP2= calcAngle(previousTouchPoint, touchDragPoint); 
       angleThreshold = Math.abs(angleP1 - angleP2); 
       if (angleThreshold > Math.PI) angleThreshold = (float) (2.0 * Math.PI) - angleThreshold; 
      } 
//    velocityThresDir = (float) Math.abs((Math.cos(angleThreshold) * touchVelocity*1000)); 
       velocityThresDir = (float) (Math.cos(angleThreshold) * touchVelocity*1000); 

      //end of calculation for velocity threshold 


      double angle = newM(touchDownPoint.x, touchDownPoint.y, touchDragPoint.x, touchDragPoint.y); 
//    Log.v(tag, "ANGLE_FIRST_X "+touchDownPoint.x+"FIRST_Y "+touchDownPoint.y); 
//    Log.v(tag, "ANGLE_SECOND_X "+touchDragPoint.x+"SECOND_Y "+touchDragPoint.y); 
//    Log.v(tag, "ANGLE_FIRST"+angle); 

      if ((touchDownPoint.x != thresholdPoint.x) || (touchDownPoint.y != thresholdPoint.y)) { 
       double angleThresh = newM(touchDownPoint.x, touchDownPoint.y, thresholdPoint.x, thresholdPoint.y); 
       double angleBetween = Math.abs(angle - angleThresh); 
       if(angleBetween < 45 || angleBetween > 315){ 
        if(angleBetween > 315) { 
         if (angle < angleThresh) { 
          angle += 360; 
         } 
         else if (angle > angleThresh) { 
          angleThresh += 360; 
         } 
         angle = Math.abs((angle - angleThresh)%360)/2.0; 
//       Log.v(tag, "ANGLE_SECOND"+angle); 
         } 
         else { 
          angle = (angle + angleThresh * 1.0)/2.0; 
//       Log.v(tag, "ANGLE_THIRD"+angle); 
         } 
        } 
       } 

      if (angle > 337.5){ 
       direction = 3; 
      }else if (angle > 292.5){ 
       direction = 5; 
      }else if (angle > 247.5){ 
       direction = 4; 
      }else if (angle > 202.5){ 
       direction = 6; 
      }else if (angle > 157.5){ 
       direction = 1; 
      }else if (angle > 112.5){ 
       direction = 7; 
      }else if (angle > 67.5){ 
       direction = 2; 
      }else if (angle > 22.5){ 
       direction = 8; 
      }else{ 
       direction = 3; 
      } 

      /* start timer if velocity is below velocity threshold*/  
      if ((velocityThresDir < VELOCITY_THRESHOLD) && 
        (act == android.view.MotionEvent.ACTION_MOVE) && (cDownTimer == null) && 
        (pw == null)) { //"&& cDownTimer" can be removed I think 
       /* start timer with motionEvent and time in ms as a parameter */ 
       // added next two lines 
       callOnLongPress(me); 
       startTimerShowPopup(me,100);//Will changed from 150 
      }   
     } else { 
      direction = 0; 
     } 

     if (act == android.view.MotionEvent.ACTION_MOVE) { 
      return true; 
     } else if (act == android.view.MotionEvent.ACTION_UP) { 
      if (cDownTimer != null) { 
       cDownTimer.cancel(); 
       cDownTimer = null; 
      } 
      if (pw != null) 
       pw.dismiss(); 
      if (longPressedKey) { 
       SoftKeyboard.mComposing 
         .append(charset[mappedKey][direction]); 
       popUpTextEntryScheme = true; 
      } 

      longPressedKey = false; 
      currentPointerID = INVALID_POINTER_ID; 
     } 
    } 

    else if (act == android.view.MotionEvent.ACTION_POINTER_DOWN) { 
     //   if (me.getPointerCount() > 1) { //Should always be true, I think 
      nextPointerID = me.getPointerId(ptrIndex); 
      nextTouchDownPoint.set(me.getX(ptrIndex),me.getY(ptrIndex)); 
//   } 
     } 
     else if (act == android.view.MotionEvent.ACTION_CANCEL) { 
      currentPointerID = INVALID_POINTER_ID; 
      nextPointerID = INVALID_POINTER_ID; 

    } 
    else if (act == android.view.MotionEvent.ACTION_POINTER_UP) { 
     // Extract the index of the pointer that left the touch sensor 
     final int pointerId = me.getPointerId(ptrIndex); 
     if (pointerId == currentPointerID) { 
      // This was our active pointer going up. Choose a new 
      // active pointer and adjust accordingly. 
      final int newPointerIndex = ptrIndex == 0 ? 1 : 0; 
      currentPointerID = nextPointerID;//(0); 
      touchDownPoint.set(nextTouchDownPoint.x,nextTouchDownPoint.y); 
      if (cDownTimer != null) { 
       cDownTimer.cancel(); 
       cDownTimer = null; 
      } 
      if (pw != null) { 
       pw.dismiss(); 
       pw = null; 
      } 
      if (longPressedKey) { 
       SoftKeyboard.mComposing 
         .append(charset[mappedKey][direction]); 
       popUpTextEntryScheme = true; 
      } 
      longPressedKey = false; 
      lastDirection = direction = 0; // keysAtOnce=0; 

      touchDragPoint.set(me.getX(newPointerIndex),me.getY(newPointerIndex)); 
      thresholdPoint.set(nextTouchDownPoint.x,nextTouchDownPoint.y); 
      //added to improve accuracy 
      thresholdPoint1_5 = false; 
      // added next 3 for Andro 2+ 
      currentX = touchDragPoint.x; 
      currentY = touchDragPoint.y; 
      // Save the ID of this first pointer (touch) down 

      previousDownTime = me.getEventTime(); 
      me.setLocation(touchDownPoint.x, touchDownPoint.y); 
      //start timer on touch down  
      startTimer(me,300); //150); Will7 changed this and removed method: checkLongPress 
     } else { //Second pointer up before first. (Not handling 3 or more pointers yet!) 

//    nextPointerID = INVALID_POINTER_ID; 
      } 
     } //else 



    return super.onTouchEvent(me); // after we return here the service will get notified, etc 
//  return true; 
    } 

và lớp SoftKeyboard tôi ..

public void onPress(int primaryCode) { 
     Log.v("SoftKeyboard", "ANGLE_ACTION_ON_PRESS : "); 

     // added next section for repeating backspace 
     if (RepeatBSTimer != null) { 
      RepeatBSTimer.cancel(); 
      RepeatBSTimer = null; 
     } 
     if (mp != null) { // /Will7 moved this from just above keystroke 
          // statement 
      mp.release(); 
      mp = null; 
     } 

     // added for Andro 2+ multitouch 
     if (primaryCode == pressedCode 
       && LatinKeyboardView.nextPointerID != LatinKeyboardView.INVALID_POINTER_ID) { 
      // I need to look up the real primaryCode here. (Not sure how!) 
      // Android gives wrong values when touches overlap. 
      wrongPrimaryCode = true; 
      return; 
     } else 
      wrongPrimaryCode = false; 

     pressedCode = primaryCode; 

     // added next section for repeating backspace 
     if (primaryCode == Keyboard.KEYCODE_DELETE) { 
      RepeatBSTimer = new CountDownTimer(1500000, 75) { 
       @Override 
       public void onTick(long millisUntilFinished) { 
        int primaryCode2; 
        if (LatinKeyboardView.longPressedKey 
          || (1500000 - millisUntilFinished > 500)) { 
         primaryCode2 = getCharFromKey(pressedCode, 
           LatinKeyboardView.direction, mInputView 
             .getKeyboard()); 
         if (primaryCode2 == Keyboard.KEYCODE_DELETE) { 
          repeating = true; 
          handleBackspace(); 
         } else if (primaryCode2 == KEYCODE_DELETEWORD 
           && (millisUntilFinished % 150) < 75) { 
          repeating = true; 
          deleteLastWord(); 
         } 
        } 
       } 

       @Override 
       public void onFinish() { 
       } 
      }; 
      RepeatBSTimer.start(); 
     } 
     // added section for repeating backspace 

     Uri uri = Uri.parse("android.resource://" + getPackageName() + "/" 
       + R.raw.keystroke);// Play Key Click 
     try { 
      mp = new MediaPlayer(); 
      mp.setDataSource(this, uri); 
      mp.prepare(); 
      mp.start(); 
     } catch (IllegalArgumentException e) { 
      e.printStackTrace(); 
     } catch (SecurityException e) { 
      e.printStackTrace(); 
     } catch (IllegalStateException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
} 

public void onRelease(int primaryCode) { 

     // Will7 added next line if for Andro 2+ multitouch 
     if (wrongPrimaryCode 
       && LatinKeyboardView.nextPointerID != LatinKeyboardView.INVALID_POINTER_ID) { 

      return; 
     } 
     // else pressedCode = primaryCode; 


     // added next sections for repeating backspace 
     primaryCode = getCharFromKey(pressedCode, LatinKeyboardView.direction,mInputView.getKeyboard()); 
     if (primaryCode == Keyboard.KEYCODE_DELETE && !repeating) 
      handleBackspace(); 
     if (primaryCode == KEYCODE_DELETEWORD && !repeating) 
      deleteLastWord(); 
     repeating = false; 

     if (RepeatBSTimer != null) { 
      RepeatBSTimer.cancel(); 
      RepeatBSTimer = null; 
     } 
     // moved all the rest of this method from onKey() 
     int[] keyCodes; 

     // added this var for Andro 2+ multitouch 
     keyCodes = keyCodesSave; 

     commitTyped(getCurrentInputConnection()); 


     if (isWordSeparator(primaryCode) && (char) primaryCode != '.' 

       && (char) primaryCode != '!' && (char) primaryCode != '?') { 
      // Handle separator 
      if (mComposing.length() > 0) { 
       commitTyped(getCurrentInputConnection()); 
      } 
      sendKey(primaryCode); 
      updateShiftKeyState(getCurrentInputEditorInfo()); 
     } else if (primaryCode == Keyboard.KEYCODE_DELETE) { 
      // commented out next line for repeating backspace 
      // handleBackspace(); 
     } else if (primaryCode == Keyboard.KEYCODE_SHIFT || primaryCode == -1) { 
      handleShift(); 
     } else if (primaryCode == Keyboard.KEYCODE_CANCEL) { 
      handleClose(); 
      return; 
     } else if (primaryCode == KEYCODE_ESCAPE) { 
      // Do nothing on Escape key 
     } else if (primaryCode == LatinKeyboardView.KEYCODE_OPTIONS) { 
      // Show a menu or something 
     } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE 
       && mInputView != null) { 
      Keyboard current = mInputView.getKeyboard(); 
      if (current == mSymbolsKeyboard 
        || current == mSymbolsShiftedKeyboard) { 
       getCurrentInputConnection().finishComposingText(); 
       current = mQwertyKeyboard; 
      } else { 
       getCurrentInputConnection().finishComposingText(); 
       current = mSymbolsKeyboard; 
      } 
      mInputView.setKeyboard(current); 
      if (current == mSymbolsKeyboard) { 
       current.setShifted(false); 
      } 
     } else if (primaryCode == KEYCODE_CAPSLOCK)// handle caps lock 
     { 
      if (mInputView.getKeyboard() == mQwertyKeyboard 
        || mInputView.getKeyboard() == mSymbolsKeyboard) { 
       mInputView.setKeyboard(mQwertyKeyboardUpperCase); 
       mQwertyKeyboardUpperCase.setShifted(true); 
       mCapsLock = true; 
      } else { 
       mQwertyKeyboard.setShifted(false); 
       mInputView.setKeyboard(mQwertyKeyboard); 
       mCapsLock = false; 
      } 
     } else if (primaryCode == KEYCODE_DELETEWORD) { 
      // commented out next line for repeating backspace 
      // deleteLastWord(); 
     } else if (primaryCode == KEYCODE_FULL_STOP_AND_SPACE) { 
      // added next line 
      backspaceIfSpaceLeft(); 
      getCurrentInputConnection().finishComposingText(); 

      handleCharacter((int) '.', keyCodes); 
      handleCharacter((int) ' ', keyCodes); 
      handleShift(); 

     } 
     // added next 5 KEYCODES 
     else if (primaryCode == KEYCODE_EXCLAMATION) { 
      // added next line 
      backspaceIfSpaceLeft(); 
      getCurrentInputConnection().finishComposingText(); 

      handleCharacter((int) '!', keyCodes); 
      handleCharacter((int) ' ', keyCodes); 
      handleShift(); 

     } else if (primaryCode == KEYCODE_QUESTION_MARK) { 
      // added next line 
      backspaceIfSpaceLeft(); 
      getCurrentInputConnection().finishComposingText(); 

      handleCharacter((int) '?', keyCodes); 
      handleCharacter((int) ' ', keyCodes); 
      handleShift(); 

     } else if (primaryCode == KEYCODE_COMMA) { 
      // added next line 
      backspaceIfSpaceLeft(); 
      getCurrentInputConnection().finishComposingText(); 

      handleCharacter((int) ',', keyCodes); 
      handleCharacter((int) ' ', keyCodes); 

     } else if (primaryCode == KEYCODE_COLON) { 
      // added next line 
      backspaceIfSpaceLeft(); 
      getCurrentInputConnection().finishComposingText(); 

      handleCharacter((int) ':', keyCodes); 
      handleCharacter((int) ' ', keyCodes); 

     } else if (primaryCode == KEYCODE_SEMICOLON) { 
      // added next line 
      backspaceIfSpaceLeft(); 
      getCurrentInputConnection().finishComposingText(); 

      handleCharacter((int) ';', keyCodes); 
      handleCharacter((int) ' ', keyCodes); 

     } else { 
      handleCharacter(primaryCode, keyCodes); 
     } 
} 

Cảm ơn ..

+2

mà không thấy mã ur không ai có thể gợi ý cho bạn bất cứ điều gì, vì vậy hãy đăng phần chính của mã ur ... – himanshu

Trả lời

2

Đây là một onTouchEvent xử lý rất lâu, tôi khuyên bạn nên tách nó ra thành các bước hợp lý hơn. Tôi cũng đã có vấn đề dường như "out-of-order" sự kiện khi cố gắng để xử lý màn hình cảm ứng.

Tôi thấy rằng tôi đã không xử lý các sự kiện cho mỗi ID con trỏ một cách chính xác. Tôi muốn kiểm tra để chắc chắn rằng bạn đang xử lý nhiều con trỏ như mong đợi. Các thiết bị tôi kiểm tra với (N1) chỉ hỗ trợ hai con trỏ, nhưng những người khác hỗ trợ nhiều hơn, và những người cần được tính toán.

Để xử lý màn hình cảm ứng "nút mềm" dưới dạng sự kiện onTouchEvent, tôi thấy hữu ích khi tạo lớp máy trạng thái. Sử dụng các tham số MotionEvent làm các sự kiện đầu vào cho máy trạng thái và gây ra các chuyển đổi trạng thái để kích hoạt các sự kiện bạn muốn. Một cách tiếp cận rõ ràng, do nhà nước định hướng sẽ cung cấp cho bạn các kết quả mong đợi mà bạn đang tìm kiếm.