Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7703733
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 31, 20262026-05-31T23:31:35+00:00 2026-05-31T23:31:35+00:00

I am creating softkeyboard for android 2.2 and higher. everything is fine but when

  • 0

I am creating softkeyboard for android 2.2 and higher. everything is fine but when i type really quick then some time my ACTION_DOWN method is not calling. Actual flow of called method should look like

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

if i type at normal speed then it works fine but if i type fast then above order of method execution looks like

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

any suggestions?

Edit
My LatinKeyboardView class that contains 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;
    }

and my SoftKeyboard class..

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

Thanks..

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-31T23:31:36+00:00Added an answer on May 31, 2026 at 11:31 pm

    This is a very long onTouchEvent handler, I suggest breaking it up into more logical steps. I also have had the issue of seemingly “out-of-order” events when trying to handle the touchscreen.

    I found that I wasn’t handling the events per pointer ID correctly. I’d check to make sure you are handling multiple pointers as expected. The device I test with (N1) only supports two pointers, but others support many more, and those should be accounted for.

    For handling touchscreen “soft-buttons” as an onTouchEvent event, I’ve found it useful to create a state machine class. Use the MotionEvent parameters as input events to the state machine, and cause state transitions to trigger your wanted events. An explicit, state-driven approach will give you the expected results you are looking for.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am looking into creating custom keyboard for Android, but I would like to
I am creating a softkeyboard for android to play around with ptrace(). I would
I followed these two exemples of developer.android (Creating an Input Method, Soft Keyboard sample).
Creating a birthday club. The database consists of clients and their pets. Some clients
Creating extensions got much easier with Vs2010, but this seems not to be the
Creating the closure is easy but using it is confusing for me. Here is
Creating an Iphone application, I used to perform INSERT QUERY on different databases. But
Creating a simple TCP server based on examples but still do not get how
Creating a web interface so our helpdesk can create users and setup some of
Creating servlet that implements contextInitializer interface in this code, then accessing file inside contextinitialized()

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.