spyglass/src/main/java/com/linkedin/android/spyglass/ui/MentionsEditText.java
@Override
    public boolean onTouchEvent(@NonNull MotionEvent event) {
        final MentionSpan touchedSpan = getTouchedSpan(event);

        // Android 6 occasionally throws a NullPointerException inside Editor.onTouchEvent()
        // for ACTION_UP when attempting to display (uninitialised) text handles.
        boolean superResult;
        if (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.M &&
            event.getActionMasked() == MotionEvent.ACTION_UP) {
            try {
                superResult = super.onTouchEvent(event);
            } catch (NullPointerException ignored) {
                // Ignore this (see above) - since we're now in an unknown state let's clear all
                // selection (which is still better than an arbitrary crash that we can't control):
                clearFocus();
                superResult = true;
            }
        } else {
            superResult = super.onTouchEvent(event);
        }

        if (event.getAction() == MotionEvent.ACTION_UP) {
            // Don't call the onclick on mention if MotionEvent.ACTION_UP is for long click action,
            if (!isLongPressed && touchedSpan != null) {
                // Manually click span and show soft keyboard
                touchedSpan.onClick(this);
                Context context = getContext();
                if (context != null) {
                    InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.showSoftInput(this, 0);
                }
                return true;
            }
        } else if (event.getAction() == MotionEvent.ACTION_DOWN) {
            isLongPressed = false;
            if (isLongClickable() && touchedSpan != null) {
                if (longClickRunnable == null) {
                    longClickRunnable = new CheckLongClickRunnable();
                }
                longClickRunnable.touchedSpan = touchedSpan;
                removeCallbacks(longClickRunnable);
                postDelayed(longClickRunnable, ViewConfiguration.getLongPressTimeout());
            }
        } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
            isLongPressed = false;
        }

        // Check if user clicked on the EditText while showing the suggestions list
        // If so, avoid the current prefix
        if (mAvoidPrefixOnTap
                && mSuggestionsVisibilityManager != null
                && mSuggestionsVisibilityManager.isDisplayingSuggestions()) {
            mSuggestionsVisibilityManager.displaySuggestions(false);
            String keywords = getCurrentKeywordsString();
            String[] words = keywords.split(" ");
            if (words.length > 0) {
                String prefix = words[words.length - 1];
                // Note that prefix == "" when user types an explicit character and taps the EditText
                // We must not allow the user to avoid suggestions for the empty string prefix
                // Otherwise, explicit mentions would be broken, see MOB-38080
                if (prefix.length() > 0) {
                    setAvoidedPrefix(prefix);
                }
            }
        }
        return superResult;
    }
@Override
    public boolean onTouchEvent(@NonNull MotionEvent event) {
        final MentionSpan touchedSpan = getTouchedSpan(event);

        // Android 6 occasionally throws a NullPointerException inside Editor.onTouchEvent()
        // for ACTION_UP when attempting to display (uninitialised) text handles.
        boolean superResult;
        if (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.M &&
            event.getActionMasked() == MotionEvent.ACTION_UP) {
            try {
                superResult = super.onTouchEvent(event);
            } catch (NullPointerException ignored) {
                // Ignore this (see above) - since we're now in an unknown state let's clear all
                // selection (which is still better than an arbitrary crash that we can't control):
                clearFocus();
                superResult = true;
            }
        } else {
            superResult = super.onTouchEvent(event);
        }

        if (event.getAction() == MotionEvent.ACTION_UP) {
            // Don't call the onclick on mention if MotionEvent.ACTION_UP is for long click action,
            if (!isLongPressed && touchedSpan != null) {
                // Manually click span and show soft keyboard
                touchedSpan.onClick(this);
                Context context = getContext();
                if (context != null) {
                    InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.showSoftInput(this, 0);
                }
                return true;
            }
        } else if (event.getAction() == MotionEvent.ACTION_DOWN) {
            isLongPressed = false;
            if (isLongClickable() && touchedSpan != null) {
                if (longClickRunnable == null) {
                    longClickRunnable = new CheckLongClickRunnable();
                }
                longClickRunnable.touchedSpan = touchedSpan;
                removeCallbacks(longClickRunnable);
                postDelayed(longClickRunnable, ViewConfiguration.getLongPressTimeout());
            }
        } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
            isLongPressed = false;
        }

        // Check if user clicked on the EditText while showing the suggestions list
        // If so, avoid the current prefix
        if (mAvoidPrefixOnTap
                && mSuggestionsVisibilityManager != null
                && mSuggestionsVisibilityManager.isDisplayingSuggestions()) {
            mSuggestionsVisibilityManager.displaySuggestions(false);
            String keywords = getCurrentKeywordsString();
            String[] words = keywords.split(" ");
            if (words.length > 0) {
                String prefix = words[words.length - 1];
                // Note that prefix == "" when user types an explicit character and taps the EditText
                // We must not allow the user to avoid suggestions for the empty string prefix
                // Otherwise, explicit mentions would be broken, see MOB-38080
                if (prefix.length() > 0) {
                    setAvoidedPrefix(prefix);
                }
            }
        }
        return superResult;
    }
@ Override public boolean onTouchEvent ( @ NonNull MotionEvent event ) { final MentionSpan touchedSpan = getTouchedSpan ( event ) ; // Android 6 occasionally throws a NullPointerException inside Editor.onTouchEvent() // for ACTION_UP when attempting to display (uninitialised) text handles. boolean superResult ; if ( android . os . Build . VERSION . SDK_INT == Build . VERSION_CODES . M && event . getActionMasked ( ) == MotionEvent . ACTION_UP ) { try { superResult = super . onTouchEvent ( event ) ; } catch ( NullPointerException ignored ) { // Ignore this (see above) - since we're now in an unknown state let's clear all // selection (which is still better than an arbitrary crash that we can't control): clearFocus ( ) ; superResult = true ; } } else { superResult = super . onTouchEvent ( event ) ; } if ( event . getAction ( ) == MotionEvent . ACTION_UP ) { // Don't call the onclick on mention if MotionEvent.ACTION_UP is for long click action, if ( ! isLongPressed && touchedSpan != null ) { // Manually click span and show soft keyboard touchedSpan . onClick ( this ) ; Context context = getContext ( ) ; if ( context != null ) { InputMethodManager imm = ( InputMethodManager ) context . getSystemService ( Context . INPUT_METHOD_SERVICE ) ; imm . showSoftInput ( this , 0 ) ; } return true ; } } else if ( event . getAction ( ) == MotionEvent . ACTION_DOWN ) { isLongPressed = false ; if ( isLongClickable ( ) && touchedSpan != null ) { if ( longClickRunnable == null ) { longClickRunnable = new CheckLongClickRunnable ( ) ; } longClickRunnable . touchedSpan = touchedSpan ; removeCallbacks ( longClickRunnable ) ; postDelayed ( longClickRunnable , ViewConfiguration . getLongPressTimeout ( ) ) ; } } else if ( event . getAction ( ) == MotionEvent . ACTION_CANCEL ) { isLongPressed = false ; } // Check if user clicked on the EditText while showing the suggestions list // If so, avoid the current prefix if ( mAvoidPrefixOnTap && mSuggestionsVisibilityManager != null && mSuggestionsVisibilityManager . isDisplayingSuggestions ( ) ) { mSuggestionsVisibilityManager . displaySuggestions ( false ) ; String keywords = getCurrentKeywordsString ( ) ; String [ ] words = keywords . split ( " " ) ; if ( words . length > 0 ) { String prefix = words [ words . length - 1 ] ; // Note that prefix == "" when user types an explicit character and taps the EditText // We must not allow the user to avoid suggestions for the empty string prefix // Otherwise, explicit mentions would be broken, see MOB-38080 if ( prefix . length ( ) > 0 ) { setAvoidedPrefix ( prefix ) ; } } } return superResult ; }
Called whenever the user touches this {@link EditText}. This was one of the primary reasons for overriding
EditText in this library. This method ensures that when a user taps on a {@link MentionSpan} in this EditText,
{@link MentionSpan#onClick(View)} is called before the onClick method of this {@link EditText}.

@param event the given {@link MotionEvent}

@return true if the {@link MotionEvent} has been handled
Called whenever the user touches this { @link EditText } . This was one of the primary reasons for overriding EditText in this library . This method ensures that when a user taps on a { @link MentionSpan } in this EditText { @link MentionSpan#onClick ( View ) } is called before the onClick method of this { @link EditText } .