如何在我的应用程序特定键盘中显示建议视图

时间:2017-04-18 11:13:48

标签: android keyboard autosuggest custom-keyboard

我已实施this。我想添加建议,类似于其他键盘提供的建议,但是我找不到如何实现它的解决方案。我的键盘是特定于应用程序的,因此我的自定义键盘类不会扩展InputServiceMethod,因此我非常感谢如何在没有InputServiceMethod的情况下实现此键盘。

我的CustomKeyboard.java类如下。

CustomKeyBoard.java

package com.example.wpa2.applicationspecifickeyboard;

import android.app.Activity;
import android.content.Context;
import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.view.textservice.SentenceSuggestionsInfo;
import android.view.textservice.SpellCheckerSession;
import android.view.textservice.SuggestionsInfo;
import android.view.textservice.TextInfo;
import android.view.textservice.TextServicesManager;
import android.widget.EditText;

import java.util.ArrayList;
import java.util.List;

public class CustomKeyBoard {

   String translateWord = "";
   Editable edit;
  /**
   * A link to the KeyboardView that is used to render this CustomKeyboard.
   */
private KeyboardView mKeyboardView;
private LatinKeyboardView mInputView;
private CandidateView mCandidateView;
private LatinKeyboard mSymbolsKeyboard;
private LatinKeyboard mSymbolsShiftedKeyboard;
private LatinKeyboard mQwertyKeyboard;
private boolean mCompletionOn;
private boolean mPredictionOn;
private CompletionInfo[] mCompletions;
/**
 * A link to the activity that hosts the {@link #mKeyboardView}.
 */
private Activity mHostActivity;
private InputMethodManager inputMethodManager;
private InputConnection ic;
private StringBuilder mComposing = new StringBuilder();
private String mWordSeparators;
private boolean mCapsLock;
private long mLastShiftTime;
private long mMetaState;
//private SpellCheckerSession mScs;
private List<String> mSuggestions;
  /**
 * The key (code) handler.
 */
private KeyboardView.OnKeyboardActionListener mOnKeyboardActionListener = new KeyboardView.OnKeyboardActionListener() {

    public final static int CodeDelete = -5; // Keyboard.KEYCODE_DELETE
    public final static int CodeCancel = -3; // Keyboard.KEYCODE_CANCEL
    public final static int CodePrev = 55000;
    public final static int CodeAllLeft = 55001;
    public final static int CodeLeft = 55002;
    public final static int CodeRight = 55003;
    public final static int CodeAllRight = 55004;
    public final static int CodeNext = 55005;
    public final static int CodeClear = 55006;

    @Override
    public void onKey(int primaryCode, int[] keyCodes) {
        // NOTE We can say '<Key android:codes="49,50" ... >' in the xml file; all codes come in keyCodes, the first in this list in primaryCode
        // Get the EditText and its Editable

        View focusCurrent = mHostActivity.getWindow().getCurrentFocus();
        //if (focusCurrent == null || focusCurrent.getClass() != EditText.class) return;
        if (focusCurrent == null) {
            return;
        } else {
            EditText edittext = (EditText) focusCurrent;
            Editable editable = edittext.getText();
            int start = edittext.getSelectionStart();

            edit = editable;
            // Apply the key to the edittext
            if (primaryCode == CodeCancel) {
                hideCustomKeyboard();
            } else if (primaryCode == CodeDelete) {
                if (editable != null && start > 0) editable.delete(start - 1, start);
            } else if (primaryCode == CodeClear) {
                if (editable != null) editable.clear();
            } else if (primaryCode == CodeLeft) {
                if (start > 0) edittext.setSelection(start - 1);
            } else if (primaryCode == CodeRight) {
                if (start < edittext.length()) edittext.setSelection(start + 1);
            } else if (primaryCode == CodeAllLeft) {
                edittext.setSelection(0);
            } else if (primaryCode == CodeAllRight) {
                edittext.setSelection(edittext.length());
            } else if (primaryCode == CodePrev) {
                View focusNew = edittext.focusSearch(View.FOCUS_BACKWARD);
                if (focusNew != null) focusNew.requestFocus();
            } else if (primaryCode == CodeNext) {
                View focusNew = edittext.focusSearch(View.FOCUS_FORWARD);
                if (focusNew != null) focusNew.requestFocus();
            } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE && mInputView != null) {
                Keyboard current = mInputView.getKeyboard();
                if (current == mSymbolsKeyboard || current == mSymbolsShiftedKeyboard) {
                    setLatinKeyboard(mQwertyKeyboard);
                } else {
                    setLatinKeyboard(mSymbolsKeyboard);
                    mSymbolsKeyboard.setShifted(false);
                }
            } else if (primaryCode == Keyboard.KEYCODE_SHIFT) {
                handleShift();
            } else { // insert character
                editable.insert(start, Character.toString((char) primaryCode));
                mComposing.append((char) primaryCode);
            }
        }

        Log.d("Test", "KEYCODE: " + primaryCode);
    }

    @Override
    public void onPress(int arg0) {

    }

    @Override
    public void onRelease(int primaryCode) {
   //inputMethodService.getCurrentInputConnection().commitText(
  //String.valueOf((char) primaryCode), 1);
  //InputConnection ic = inputMethodService.getCurrentInputConnection();
  //if (ic == null) {
      //return;
  //}
 //ic.beginBatchEdit();
        if (mComposing.length() > 0) {
          //commitTyped(ic);
            commitTyped();
        }
      //ic.endBatchEdit();
    }

    @Override
    public void onText(CharSequence text) {
    //InputConnection ic = inputMethodService.getCurrentInputConnection();
    //if (ic == null) {
      // return;
     //}
   //ic.beginBatchEdit();
        if (mComposing.length() > 0) {
           //commitTyped(ic);
            commitTyped();
        }
   //ic.commitText(text, 0);
   //ic.endBatchEdit();
    }

    @Override
    public void swipeDown() {
    }

    @Override
    public void swipeLeft() {
    }

    @Override
    public void swipeRight() {
    }

    @Override
    public void swipeUp() {
    }
};

/**
 * Create a custom keyboard, that uses the KeyboardView (with resource id <var>viewid</var>) of the <var>host</var> activity,
 * and load the keyboard layout from xml file <var>layoutid</var> (see {@link Keyboard} for description).
 * Note that the <var>host</var> activity must have a <var>KeyboardView</var> in its layout (typically aligned with the bottom of the activity).
 * Note that the keyboard layout xml file may include key codes for navigation; see the constants in this class for their values.
 * Note that to enable EditText's to use this custom keyboard, call the {@link #registerEditText(int)}.
 *
 * @param host     The hosting activity.
 * @param viewid   The id of the KeyboardView.
 * @param layoutid The id of the xml file containing the keyboard layout.
 */
public CustomKeyBoard(Activity host, int viewid, int layoutid) {
    mHostActivity = host;

    mInputView = (LatinKeyboardView) mHostActivity.findViewById(viewid);
    mInputView.setKeyboard(new Keyboard(mHostActivity, layoutid));
   //  mInputView.setPreviewEnabled(false); // NOTE Do not show the preview balloons
    mInputView.setOnKeyboardActionListener(mOnKeyboardActionListener);

    mWordSeparators = host.getResources().getString(R.string.word_separators);

    // Hide the standard keyboard initially
  mHostActivity.getWindow().
setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

    //to set other keyboard layout.
    mQwertyKeyboard = new LatinKeyboard(mHostActivity, R.xml.qwerty);
    mSymbolsKeyboard = new LatinKeyboard(mHostActivity, R.xml.symbols);
    mSymbolsShiftedKeyboard = new LatinKeyboard(mHostActivity, R.xml.symbols_shift);

    mPredictionOn = true;
    mCompletionOn = false;
    mCompletions = null;
    //final TextServicesManager tsm = (TextServicesManager) mHostActivity.getSystemService(
            Context.TEXT_SERVICES_MANAGER_SERVICE);
   // mScs = tsm.newSpellCheckerSession(null, null, this, true);
  //ic=mInputView.onCreateInputConnection();
}


/**
 * Returns whether the CustomKeyboard is visible.
 */
public boolean isCustomKeyboardVisible() {
    return mInputView.getVisibility() == View.VISIBLE;
}

/**
 * Make the CustomKeyboard visible, and hide the system keyboard for view v.
 */
public void showCustomKeyboard(View v) {
    mInputView.setVisibility(View.VISIBLE);
    mInputView.setEnabled(true);
    if (v != null)
      //v.requestFocus();
      //((InputMethodManager) mHostActivity.getSystemService(Activity.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(), 0);
        ((InputMethodManager) mHostActivity.getSystemService(Activity.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}

/**
 * Make the CustomKeyboard invisible.
 */
public void hideCustomKeyboard() {
    mInputView.setVisibility(View.GONE);
    mInputView.setEnabled(false);
}

/**
 * Register <var>EditText<var> with resource id <var>resid</var> (on the hosting activity) for using this custom keyboard.
 *
 * @param resid The resource id of the EditText that registers to the custom keyboard.
 */
public void registerEditText(int resid) {
    // Find the EditText 'resid'
    final EditText edittext = (EditText) mHostActivity.findViewById(resid);
    // Make the custom keyboard appear
    edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        // NOTE By setting the on focus listener, we can show the custom keyboard when the edit box gets focus, but also hide it when the edit box loses focus
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus) showCustomKeyboard(v);
            else hideCustomKeyboard();
        }
    });
    edittext.setOnClickListener(new View.OnClickListener() {
        // NOTE By setting the on click listener, we can show the custom keyboard again, by tapping on an edit box that already had focus (but that had the keyboard hidden).
        @Override
        public void onClick(View v) {
            showCustomKeyboard(v);
        }
    });

    // Disable standard keyboard hard way
    // NOTE There is also an easy way: 'edittext.setInputType(InputType.TYPE_NULL)' (but you will not have a cursor, and no 'edittext.setCursorVisible(true)' doesn't work )
    edittext.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            EditText edittext = (EditText) v;
            int inType = edittext.getInputType();       // Backup the input type
            edittext.setInputType(InputType.TYPE_NULL); // Disable standard keyboard
            edittext.onTouchEvent(event);               // Call native handler
            edittext.setInputType(inType);              // Restore input type
         //edittext.setCursorVisible(true);
        //edittext.requestFocus();
            return true; // Consume touch event
        }
    });

    onCreateCandidatesView();
    edittext.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }

        @Override
        public void afterTextChanged(Editable s) {
            updateCandidates();

        }
    });


    // Disable spell check (hex strings look like words to Android)
    //edittext.setInputType(edittext.getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
}

/**
 * Helper function to commit any text being composed in to the editor.
 */

private void commitTyped() {
    if (mComposing.length() > 0) {
   //mInputView.onCreateInputConnection().commitText(mComposing, mComposing.length());
        edit.append(mComposing);
        mComposing.setLength(0);
        updateCandidates();
    }
}


/**
 * Helper to send a key down / key up pair to the current editor.
 */
private void keyDownUp(int keyEventCode) {
    inputMethodService.getCurrentInputConnection().sendKeyEvent(
            new KeyEvent(KeyEvent.ACTION_DOWN, keyEventCode));
    inputMethodService.getCurrentInputConnection().sendKeyEvent(
            new KeyEvent(KeyEvent.ACTION_UP, keyEventCode));
}


/**
 * Helper to send a character to the editor as raw key events.
 */
private void sendKey(int keyCode) {
    switch (keyCode) {
        case '\n':
            keyDownUp(KeyEvent.KEYCODE_ENTER);
            break;
        default:
            if (keyCode >= '0' && keyCode <= '9') {
                keyDownUp(keyCode - '0' + KeyEvent.KEYCODE_0);
            } else {
                inputMethodService.getCurrentInputConnection().commitText(String.valueOf((char) keyCode), 1);
            }
            break;
    }
}

private String getWordSeparators() {
    return mWordSeparators;
}

public boolean isWordSeparator(int code) {
    String separators = getWordSeparators();
    return separators.contains(String.valueOf((char) code));
}

// this method not used currently anywhere.
private void handleBackspace() {
    final int length = mComposing.length();
    if (length > 1) {
        mComposing.delete(length - 1, length);
        inputMethodService.getCurrentInputConnection().setComposingText(mComposing, 1);
        updateCandidates();
    } else if (length > 0) {
        mComposing.setLength(0);
        inputMethodService.getCurrentInputConnection().commitText("", 0);
        updateCandidates();
    } else {
        keyDownUp(KeyEvent.KEYCODE_DEL);
    }
    updateShiftKeyState(inputMethodService.getCurrentInputEditorInfo());

}

/**
 * Update the list of available candidates from the current composing
 * text.  This will need to be filled in by however you are determining
 * candidates.
 */
private void updateCandidates() {
    if (!mCompletionOn) {
        if (mComposing.length() > 0) {
            ArrayList<String> list = new ArrayList<String>();
            //list.add(mComposing.toString());
            Log.d("SoftKeyboard", "REQUESTING: " + mComposing.toString());
            //mScs.getSentenceSuggestions(new TextInfo[]{new TextInfo(mComposing.toString())}, 5);
            setSuggestions(list, true, true);
        } else {
            setSuggestions(null, false, false);
        }
    }
}

public void setSuggestions(List<String> suggestions, boolean completions,
                           boolean typedWordValid) {
    if (suggestions != null && suggestions.size() > 0) {
     // this method's alternative should be used by me if available. means to show suggestion view . 
    //inputMethodService.setCandidatesViewShown(true);
        mInputView.setVerticalCorrection(1);
    } else if (inputMethodService.isExtractViewShown()) {
    //inputMethodService.setCandidatesViewShown(true);
    }
    mSuggestions = suggestions;
    if (mCandidateView != null) {
        mCandidateView.setSuggestions(suggestions, completions, typedWordValid);
    }
}

private void handleShift() {
    if (mInputView == null) {
        return;
    }

    Keyboard currentKeyboard = mInputView.getKeyboard();
    if (mQwertyKeyboard == currentKeyboard) {
        // Alphabet keyboard
        checkToggleCapsLock();
        mInputView.setShifted(mCapsLock || !mInputView.isShifted());
    } else if (currentKeyboard == mSymbolsKeyboard) {
        mSymbolsKeyboard.setShifted(true);
        setLatinKeyboard(mSymbolsShiftedKeyboard);
        mSymbolsShiftedKeyboard.setShifted(true);
    } else if (currentKeyboard == mSymbolsShiftedKeyboard) {
        mSymbolsShiftedKeyboard.setShifted(false);
        setLatinKeyboard(mSymbolsKeyboard);
        mSymbolsKeyboard.setShifted(false);
    }
}

private void checkToggleCapsLock() {
    long now = System.currentTimeMillis();
    if (mLastShiftTime + 800 > now) {
        mCapsLock = !mCapsLock;
        mLastShiftTime = 0;
    } else {
        mLastShiftTime = now;
    }
}

/**
 * Helper to update the shift state of our keyboard based on the initial
 * editor state.
 */
private void updateShiftKeyState(EditorInfo attr) {
    if (attr != null && mInputView != null && mQwertyKeyboard == mInputView.getKeyboard()) {
        int caps = 0;

    //EditorInfo ei = inputMethodService.getCurrentInputEditorInfo()
    //if (ei != null && ei.inputType != InputType.TYPE_NULL) {
   //caps= inputMethodService.getCurrentInputConnection().getCursorCapsMode(attr.inputType);
   //}

     mInputView.setShifted(mCapsLock || caps != 0);
    }
}

private void handleCharacter(int primaryCode, int[] keyCodes) {
    if (inputMethodService.isInputViewShown()) {
        if (mInputView.isShifted()) {
            primaryCode = Character.toUpperCase(primaryCode);
        }
    }
    if (mPredictionOn) {
        mComposing.append((char) primaryCode);
        inputMethodService.getCurrentInputConnection().setComposingText(mComposing, 1);
        updateShiftKeyState(inputMethodService.getCurrentInputEditorInfo());
        updateCandidates();
    } else {
        inputMethodService.getCurrentInputConnection().commitText(
                String.valueOf((char) primaryCode), 1);
    }
}

private void setLatinKeyboard(LatinKeyboard nextKeyboard) {
    mInputView.setKeyboard(nextKeyboard);
}

public void pickSuggestionManually(int index) {
    if (mCompletionOn && mCompletions != null && index >= 0
            && index < mCompletions.length) {
        CompletionInfo ci = mCompletions[index];
        mSuggestions.add(ci.toString());
      //getCurrentInputConnection().commitCompletion(ci);
        if (mCandidateView != null) {
            mCandidateView.clear();
        }
   //updateShiftKeyState(getCurrentInputEditorInfo());
    } else if (mComposing.length() > 0) {

        if (mPredictionOn && mSuggestions != null && index >= 0) {
            mComposing.replace(0, mComposing.length(), mSuggestions.get(index));
        }
        commitTyped();

    }
}

public View onCreateCandidatesView() {
    mCandidateView = new CandidateView(mHostActivity);
    mCandidateView.setService(this);
    return mCandidateView;
    }

 }

0 个答案:

没有答案
相关问题