package com.adafruit.bluefruit.le.connect.ui.keyboard; import android.app.Activity; import android.inputmethodservice.Keyboard; import android.inputmethodservice.KeyboardView; import android.os.Build; import android.text.Editable; import android.text.InputType; import android.text.Layout; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.RelativeLayout; import com.adafruit.bluefruit.le.connect.R; public class CustomKeyboard { // Keys constants private static final int kKeyDelete = -1; private static final int kKeyReturn = -2; // Data private KeyboardView mKeyboardView; private Activity mActivity; private int mCurrentKeyboardId; public CustomKeyboard(Activity activity) { mActivity = activity; // Create the keyboard view mKeyboardView = new KeyboardView(activity, null); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT); // Select a parent for the keyboard. First search for a R.id.keyboardContainer viewgroup. If not found, use the rootWindow as parent ViewGroup keyboardContainer = (ViewGroup) activity.findViewById(R.id.keyboardContainer); ViewGroup parentViewGroup; if (keyboardContainer != null) { parentViewGroup = keyboardContainer; } else { int currentapiVersion = android.os.Build.VERSION.SDK_INT; // Get the root view to add the keyboard subview ViewGroup rootView; if (currentapiVersion > Build.VERSION_CODES.KITKAT) { // Workaround for devices with softkeys. We cant not use getRootView() because the keyboard would be below the softkeys. rootView = (ViewGroup) activity.findViewById(android.R.id.content); } else { rootView = (ViewGroup) activity.getWindow().getDecorView().getRootView(); } // Create a dummy relative layout to align the keyboardView to the bottom ViewGroup relativeLayout = new RelativeLayout(activity); relativeLayout.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT)); rootView.addView(relativeLayout); params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); // Align to the bottom of the relativelayout parentViewGroup = relativeLayout; } mKeyboardView.setLayoutParams(params); mKeyboardView.setFocusable(true); mKeyboardView.setFocusableInTouchMode(true); mKeyboardView.setVisibility(View.GONE); parentViewGroup.addView(mKeyboardView); // Configure keyboard view mKeyboardView.setPreviewEnabled(false); KeyboardView.OnKeyboardActionListener mOnKeyboardActionListener = new KeyboardView.OnKeyboardActionListener() { @Override public void onKey(int primaryCode, int[] keyCodes) { View focusCurrent = mActivity.getWindow().getCurrentFocus(); if (focusCurrent != null && (focusCurrent instanceof EditText)) { EditText edittext = (EditText) focusCurrent; Editable editable = edittext.getText(); int start = edittext.getSelectionStart(); if (primaryCode == kKeyDelete) { if (editable != null && start > 0) editable.delete(start - 1, start); } else if (primaryCode == kKeyReturn) { View nextFocusView = edittext.focusSearch(View.FOCUS_DOWN); if (nextFocusView != null && (nextFocusView instanceof EditText)) { nextFocusView.requestFocus(); } else { hideCustomKeyboard(); } } else { editable.insert(start, Character.toString((char) primaryCode)); } } } @Override public void onPress(int arg0) { } @Override public void onRelease(int primaryCode) { } @Override public void onText(CharSequence text) { } @Override public void swipeDown() { } @Override public void swipeLeft() { } @Override public void swipeRight() { } @Override public void swipeUp() { } }; mKeyboardView.setOnKeyboardActionListener(mOnKeyboardActionListener); // Hide the standard keyboard initially activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); } public void attachToEditText(final EditText editText, int keyboardLayoutId) { // Keyboard layout is saved into the editText tag (to reuse the same keyboardView with different keyboard layouts) editText.setTag(keyboardLayoutId); // Attach custom keyboard to onFocusChange editText.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View view, boolean hasFocus) { if (hasFocus) { showCustomKeyboard(view); } else { hideCustomKeyboard(); } } }); // Attach custom keyboard to onClick editText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { showCustomKeyboard(view); } }); // Fix for cursor movement (based on http://forum.xda-developers.com/showthread.php?t=2497237) editText.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent event) { if (!isCustomKeyboardVisible() || mCurrentKeyboardId != (Integer)(view.getTag())) { view.requestFocus(); showCustomKeyboard(view); } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: EditText editText = (EditText) view; Layout layout = ((EditText) view).getLayout(); if (layout != null) { float x = event.getX() + editText.getScrollX(); int offset = layout.getOffsetForHorizontal(0, x); if (offset > 0) { if (x > layout.getLineMax(0)) editText.setSelection(offset); else editText.setSelection(offset - 1); } } break; } /* 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 */ return true; } }); // Disable suggestions editText.setInputType(editText.getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); } public void hideCustomKeyboard() { mKeyboardView.setVisibility(View.GONE); mKeyboardView.setEnabled(false); } public void showCustomKeyboard(View view) { EditText editText = (EditText) view; final int keyboardId = (Integer) editText.getTag(); if (mCurrentKeyboardId != keyboardId) { Keyboard keyboard = new Keyboard(mActivity, keyboardId); mKeyboardView.setKeyboard(keyboard); mCurrentKeyboardId = keyboardId; } mKeyboardView.setVisibility(View.VISIBLE); mKeyboardView.setEnabled(true); ((InputMethodManager) mActivity.getSystemService(Activity.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(view.getWindowToken(), 0); } public boolean isCustomKeyboardVisible() { return mKeyboardView.getVisibility() == View.VISIBLE; } }