0

我正在为我的应用程序设计自定义键盘。我有一个 edittext.with 自定义键盘我必须在按 Enter 时执行一些操作(或者说完成按钮)在此处输入图像描述

Enter(Done) 在右下角。

该键盘的布局如下

 <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
          android:horizontalGap="1px"
          android:keyHeight="80dp"
          android:keyWidth="30%p"
          android:verticalGap="1px">

    <Row>
        <Key
            android:codes="49"
            android:keyEdgeFlags="left"
            android:keyLabel="1"/>
        <Key
            android:codes="50"
            android:keyLabel="2"/>
        <Key
            android:codes="51"
            android:keyLabel="3"/>

        <Key
            android:codes="-5"
            android:isRepeatable="true"
            android:keyEdgeFlags="right"
            android:keyIcon="@drawable/backspace"
            android:keyWidth="30%p"/>


    </Row>
    <Row>

        <Key
            android:codes="52"
            android:keyEdgeFlags="left"
            android:keyLabel="4"/>

        <Key
            android:codes="53"
            android:keyLabel="5"/>


        <Key
            android:codes="54"
            android:keyLabel="6"/>

        <Key
            android:codes="46"
            android:keyLabel="."
            android:keyWidth="30%p"/>


    </Row>
    <Row>

        <Key
            android:codes="55"
            android:keyEdgeFlags="left"
            android:keyLabel="7"/>
        <Key
            android:codes="56"
            android:keyLabel="8"/>
        <Key
            android:codes="57"
            android:keyLabel="9"/>

        <Key
            android:codes="47"
            android:keyEdgeFlags="right"
            android:keyLabel="/"
            android:keyWidth="30%p"/>

    </Row>
    <Row android:rowEdgeFlags="bottom">

        <Key
            android:codes="1100"
            android:isRepeatable="true"
            android:keyEdgeFlags="left"
            android:keyLabel="ABC"
            />

        <Key
            android:codes="48"
            android:keyLabel="0"/>


        <Key
            android:codes="55007"
            android:isRepeatable="true"
            android:keyIcon="@drawable/hide_key"
            android:keyWidth="30%p"/>

        <Key
            android:codes="-4"
            android:isRepeatable="true"
            android:keyEdgeFlags="right"
            android:imeOptions="actionDone"
            android:keyIcon="@drawable/sym_keyboard_done"
            />
    </Row>

</Keyboard>

我正在处理输入按钮按下如下

     if (primaryCode == Keyboard.KEYCODE_DONE) {
                Log.d("Gajanand", "onKey:connection " + connection);
//                connection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
                final int options = getCurrentInputEditorInfo().imeOptions;
                final int actionId = options & EditorInfo.IME_MASK_ACTION;

                switch (actionId) {
                    case EditorInfo.IME_ACTION_SEARCH:
                        sendDefaultEditorAction(true);
                        break;
                    case EditorInfo.IME_ACTION_GO:
                        sendDefaultEditorAction(true);
                        break;
                    case EditorInfo.IME_ACTION_SEND:
                        sendDefaultEditorAction(true);
                        break;
                    default:
                        connection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
                }


            }

我的自定义键盘类

   /**
 * Copyright 2013 Maarten Pennings
 * <p/>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * <p/>
 * If you use this software in a product, an acknowledgment in the product
 * documentation would be appreciated but is not required.
 */

package com.example.manvish.customkeybrd;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.os.Build;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.AppCompatEditText;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.widget.AutoCompleteTextView;

/**
 * When an activity hosts a keyboardView, this class allows several EditText's
 * to register for it.
 *
 * @author Maarten Pennings
 * @date 2012 December 23
 */

public class CustomKeyboard extends InputMethodService {

    //constant for defining the time duration between the click that can be considered as double-tap
    static final int MAX_DURATION = 100;
    int touchPosition;
    int id;
    Boolean longpressded = false;
    int clickCount = 0;
    //variable for storing the time of first click
    long startTime;
    //variable for calculating the total time
    long duration;
    boolean pressed = false;
    /**
     * A link to the KeyboardView that is used to render this CustomKeyboard.
     */
    private KeyboardView mKeyboardView;
    /**
     * A link to the activity that hosts the {@link #mKeyboardView}.
     */
    private AppCompatActivity mHostActivity;
    private Keyboard mKeyBoard;
    private View mInflater;
    private long mLastClickTime = 0;




    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;

        public final static int CodeDone = 55007;
        public final static int CodeCaps = -1;
        public final static int QwertNumberKeypad = 1100;
        public final static int QwertNumericKeypad = 1101;
//        public final static int CodeBackSpace = -4;

        private boolean caps = false;



        @SuppressLint("ClickableViewAccessibility")
        @Override
        public void onKey(final int primaryCode, int[] keyCodes) {

            Log.d("Gajanand", "onKey: " + primaryCode);
            InputConnection connection = getCurrentInputConnection();

            View focusCurrent = mHostActivity.getWindow().getCurrentFocus();
            if (focusCurrent == null
                    || focusCurrent.getClass() != AppCompatEditText.class)
                return;
            final AppCompatEditText edittext = (AppCompatEditText) focusCurrent;

            edittext.addTextChangedListener(new TextWatcher() {

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

                    String searchString = s.toString();
                    int textLength = searchString.length();
//                    edittext.setSelection(textLength);
                }

                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                public void afterTextChanged(Editable s) {

                }

            });

            Editable editables = edittext.getText();
            int start = edittext.getSelectionStart();
            int end = edittext.getSelectionEnd();

            // Apply the key to the edittext
            if (primaryCode == CodeCancel) {
                hideCustomKeyboard();
            } else if (primaryCode == CodeDelete) {
                if (editables != null && start > 0) {
                    editables.delete(start - 1, start);
                    edittext.setSelection(start - 1);
                }
            } else if (primaryCode == CodeClear) {
                if (editables != null)
                    editables.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 == CodeDone) {
                hideCustomKeyboard();

            }

            // for capslock

            else if (primaryCode == CodeCaps) {
                caps = !caps;
                mKeyBoard.setShifted(caps);
                mKeyboardView.invalidateAllKeys();

//                edittext.setInputType(InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS);
//
//                edittext.setFilters(new InputFilter[]{new
//                        InputFilter.AllCaps()});

            } else { // insert character

                if (primaryCode != QwertNumericKeypad && primaryCode != QwertNumberKeypad) {
                    char code = (char) primaryCode;
                    if (Character.isLetter(code) && caps) {
                        code = Character.toUpperCase(code);
                    }
                    editables.insert(start, Character.toString((char) code));

                }
            }

            if (primaryCode == QwertNumberKeypad) {
                mKeyboardView.invalidateAllKeys();
                mKeyboardView.setKeyboard(new Keyboard(mHostActivity,
                        R.xml.qwerty));

                Log.d("Gajanand", "onKey:in number keypad " + caps);
            }
            if (primaryCode == QwertNumericKeypad) {
                mKeyboardView.invalidateAllKeys();
                mKeyboardView.setKeyboard(new Keyboard(mHostActivity,
                        R.xml.qwerty_numbers));
                Log.d("Gajanand", "onKey:in numeric keypad " + caps);
            }

            if (primaryCode == Keyboard.KEYCODE_DONE) {
                Log.d("Gajanand", "onKey:connection " + connection);
//                connection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
                final int options = getCurrentInputEditorInfo().imeOptions;
                final int actionId = options & EditorInfo.IME_MASK_ACTION;

                switch (actionId) {
                    case EditorInfo.IME_ACTION_SEARCH:
                        sendDefaultEditorAction(true);
                        break;
                    case EditorInfo.IME_ACTION_GO:
                        sendDefaultEditorAction(true);
                        break;
                    case EditorInfo.IME_ACTION_SEND:
                        sendDefaultEditorAction(true);
                        break;
                    default:
                        connection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
                }


            }

        }



        @Override
        public void onPress(int arg0) {
//            Log.d("Gajanand", "onPress:GK ");
//            mLastClickTime = SystemClock.elapsedRealtime();
            pressed = true;

            Log.d("Gajanand", "onPress: " + longpressded);
        }

        @Override
        public void onRelease(int primaryCode) {
//            Log.d("Gajanand", "onRelease: GK");
//            mLastClickTime=0;
            pressed = false;

            Log.d("Gajanand", "onRelease: " + longpressded);
        }

        @Override
        public void onText(CharSequence text) {
        }

        @Override
        public void swipeDown() {
        }

        @Override
        public void swipeLeft() {
        }

        @Override
        public void swipeRight() {
        }

        @Override
        public void swipeUp() {
        }

    };

//    public CustomKeyboard(Context context, AttributeSet attrs) {
//        super(context, attrs);
//    }

    /**
     * The key (code) handler.
     */

//    @Override
//    protected boolean onLongPress(Keyboard.Key popupKey) {
//
//        pressed = true;
//        longpressded = true;
//        Log.d("Gajanand", "onLongPress: " + longpressded);
//        mKeyboardView.setEnabled(false);
//
//        return false;
//    }

//    @Override
//    protected void onSelectionChanged(int selStart, int selEnd) {
//        super.onSelectionChanged(selStart, selEnd);
//
//        Log.d("Gajanand", "onSelectionChanged: yes changed");
//    }

    /**
     * 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(AppCompatActivity host, int viewid, int layoutid) {

        mHostActivity = host;
        mKeyboardView = (KeyboardView) mHostActivity.findViewById(viewid);
        mKeyBoard = new Keyboard(mHostActivity, layoutid);
        mKeyboardView.setKeyboard(mKeyBoard);
        mKeyboardView.setPreviewEnabled(false); // NOTE Do not show the preview
        // balloons
        mKeyboardView.setOnKeyboardActionListener(mOnKeyboardActionListener);
        // Hide the standard keyboard initially
        mHostActivity.getWindow().setSoftInputMode(
                WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
    }

    public CustomKeyboard() {

    }

    public CustomKeyboard(AppCompatActivity host, View inflater, int viewid, int layoutid) {

        mHostActivity = host;
        mInflater = inflater;
        mKeyboardView = (KeyboardView) mInflater.findViewById(viewid);

        mKeyBoard = new Keyboard(mHostActivity, layoutid);
        mKeyboardView.setKeyboard(mKeyBoard);
        mKeyboardView.setPreviewEnabled(false); // NOTE Do not show the preview
        // balloons
        mKeyboardView.setOnKeyboardActionListener(mOnKeyboardActionListener);
        // Hide the standard keyboard initially
        mHostActivity.getWindow().setSoftInputMode(
                WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
    }

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

//    @Override
//    public boolean onTouchEvent(MotionEvent me) {
//        return super.onTouchEvent(me);
//    }

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

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

        sendStatusToActivity("hide");
    }

    private void sendStatusToActivity(String msg) {

        Intent intent = new Intent("KEYPAD");
        intent.putExtra("Status", msg);
        LocalBroadcastManager.getInstance(mHostActivity).sendBroadcast(intent);
//        stopservice();
    }

    /**
     * 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.
     */
    @SuppressLint("ClickableViewAccessibility")
    public void registerEditText(int resid) {
        // Find the EditText 'resid'
        AppCompatEditText edittext;

        /*View focusCurrent = mHostActivity.getWindow().getCurrentFocus();
        if (focusCurrent == null
                || focusCurrent.getClass() != AppCompatEditText.class)
            return;
        final AppCompatEditText edittext = (AppCompatEditText) focusCurrent;*/

        edittext = (AppCompatEditText) mHostActivity.findViewById(resid);
        if (edittext == null) {
            edittext = (AppCompatEditText) mInflater.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) {
                Log.d("kishan", "onClick: keypad");
                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) {
                Log.d("kishan", "onTouch: keypad");
                showCustomKeyboard(v);
                AppCompatEditText edittext = (AppCompatEditText) v;

                float x = event.getX();
                float y = event.getY();
                touchPosition = edittext.getOffsetForPosition(x, y);
                if (touchPosition > 0) {
                    edittext.setSelection(touchPosition);
                }

                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; // Consume touch event
            }
        });
        // Disable spell check (hex strings look like words to Android)
        edittext.setInputType(edittext.getInputType()
                | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
    }

    public void registerAutoCompleteEditText(int resid) {
        // Find the EditText 'resid'
        System.out.println("hello ");
        AutoCompleteTextView autoCompleteTextView;

        autoCompleteTextView = (AutoCompleteTextView) mHostActivity.findViewById(resid);
        if (autoCompleteTextView == null) {
            autoCompleteTextView = (AutoCompleteTextView) mInflater.findViewById(resid);
        }

        System.out.println("hello 1");
        // Make the custom keyboard appear
        autoCompleteTextView.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) {
                System.out.println("hello 2");
                if (hasFocus)
                    showCustomKeyboard(v);
                else
                    hideCustomKeyboard();
            }
        });
        autoCompleteTextView.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 )
        autoCompleteTextView.setOnTouchListener(new View.OnTouchListener() {
            @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                AutoCompleteTextView edittext = (AutoCompleteTextView) v;

                float x = event.getX();
                float y = event.getY();
                touchPosition = edittext.getOffsetForPosition(x, y);
                if (touchPosition > 0) {
                    edittext.setSelection(touchPosition);
                }

                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; // Consume touch event
            }
        });
        // Disable spell check (hex strings look like words to Android)
        System.out.println("hello 5");
        autoCompleteTextView.setInputType(autoCompleteTextView.getInputType()
                | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
    }

}

// NOTE How can we change the background color of some keys (like the
// shift/ctrl/alt)?
// NOTE What does android:keyEdgeFlags do/mean

但 getCurrentInputEditorInfo() 抛出空值?如何处理这个?或者它是错误的方式来实现我必须做的任何事情。

4

0 回答 0