2012-03-12 16 views
7

Estoy creando un teclado para android 2.2 y superior. todo está bien, pero cuando escribo realmente rápido, entonces mi método ACTION_DOWN no ​​está llamando. corriente real de llamada método debe ser similarSoftKeyboard para android

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

si escribo a velocidad normal entonces funciona bien, pero si escribo rápido, entonces por encima de orden de ejecución del método se parece

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

alguna sugerencia?

Editar Mi clase LatinKeyboardView que contiene 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; 
    } 

y mi clase SoftKeyboard ..

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); 
     } 
} 

Gracias ..

+2

sin ver su código, nadie puede sugerirle nada, así que publique la parte principal de su código ... – himanshu

Respuesta

2

Este es un tiempo muy largo onTouchEvent manipulador, sugiero dividirlo en pasos más lógicos. También he tenido el problema de eventos aparentemente "fuera de orden" cuando trato de manejar la pantalla táctil.

Descubrí que no manejaba correctamente los eventos por identificador de puntero. Verificaría para asegurarse de que está manejando múltiples punteros como se esperaba. El dispositivo que pruebo con (N1) solo admite dos punteros, pero otros admiten muchos más, y estos deben tenerse en cuenta.

Para manejar los "botones programables" de la pantalla táctil como un evento onTouchEvent, he encontrado que es útil crear una clase de máquina de estado. Utilice los parámetros MotionEvent como eventos de entrada en la máquina de estados y haga que las transiciones de estado activen los eventos que desee. Un enfoque explícito impulsado por el estado le dará los resultados esperados que está buscando.