自定义键盘隐藏了Android中的编辑框

时间:2014-01-13 17:49:46

标签: android keyboard editbox

我设计了一个只有数字键的自定义键盘。我按照以下链接: example

现在,当我触摸编辑框时,键盘正在出现。但是,如果我有10个编辑框,并且我正在触摸第10个编辑框,则会出现键盘并隐藏编辑框。如何使编辑框自动向上滚动以使其不被隐藏。

我为xml文件编写了以下布局代码:

  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >

    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <EditText
                android:id="@+id/edittext0"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="30dp"
                android:inputType="text" />

            <EditText
                android:id="@+id/edittext1"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/edittext0"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="30dp"
                android:inputType="text" />

            <EditText
                android:id="@+id/edittext2"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/edittext1"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="40dp"
                android:inputType="text" />

            <EditText
                android:id="@+id/edittext3"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/edittext2"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="40dp"
                android:inputType="text" />

            <EditText
                android:id="@+id/edittext4"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/edittext3"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="40dp"
                android:inputType="text" />
        </RelativeLayout>
    </ScrollView>

    <android.inputmethodservice.KeyboardView
        android:id="@+id/keyboardview"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:visibility="gone" />

</RelativeLayout>

这也是我的自定义键盘java类:

    class CustomKeyboard {

    /** 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 Activity mHostActivity;

    /** The key (code) handler. */
    private OnKeyboardActionListener mOnKeyboardActionListener = new OnKeyboardActionListener() {

        public final static int CodeDelete = -5; // Keyboard.KEYCODE_DELETE
        public final static int CodePrev = 55000;
        public final static int CodeNext = 55001;
        public final static int CodeDone = 55002;

        @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;
            EditText edittext = (EditText) focusCurrent;
            Editable editable = edittext.getText();
            int start = edittext.getSelectionStart();
            // Apply the key to the edittext
            if (primaryCode == CodeDone) {
                hideCustomKeyboard();
            } 
            else if (primaryCode == CodeDelete) 
            {
                if (editable != null && start > 0)
                    editable.delete(start - 1, start);
            } 
            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 { // insert character
                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() {
        }
    };

    /**
     * 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;
        mKeyboardView = (KeyboardView) mHostActivity.findViewById(viewid);
        mKeyboardView.setKeyboard(new Keyboard(mHostActivity, layoutid));
        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;
    }

    /**
     * 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(Activity.INPUT_METHOD_SERVICE))
                    .hideSoftInputFromWindow(v.getWindowToken(), 0);
    }

    /** Make the CustomKeyboard invisible. */
    public void hideCustomKeyboard() {
        mKeyboardView.setVisibility(View.GONE);
        mKeyboardView.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'
        EditText edittext = (EditText) mHostActivity.findViewById(resid);
        // Make the custom keyboard appear
        edittext.setOnFocusChangeListener(new 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 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 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
                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);
    }

}

请帮帮我!!

谢谢, 阿瑞丹姆

2 个答案:

答案 0 :(得分:5)

我有完全相同的问题,经过一整天的研究,我终于解决了它。

以下是:

我有几乎相同的xml布局,但我有多个KeyboardView,因为我需要不同的键盘用于不同的EditTexts。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:ignore="HardcodedText,TextFields" >    

<ScrollView 
    android:id="@+id/scroll_content"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true" >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:orientation="vertical"
        android:layout_gravity="center_horizontal"
        android:paddingBottom="16dp">

        <TextView
            android:id="@+id/DecLabel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Decimal" />

        <EditText
            android:id="@+id/DecText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:focusable="true"
            android:focusableInTouchMode="true" />

        <TextView
            android:id="@+id/HexLabel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="24dp"
            android:text="Hexadecimal" />

        <EditText
            android:id="@+id/HexText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:focusable="true"
            android:focusableInTouchMode="true" />

        <TextView
            android:id="@+id/BinaryLabel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="24dp"
            android:text="Binary" />

        <EditText
            android:id="@+id/BinaryText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:focusable="true"
            android:focusableInTouchMode="true" />

        <TextView
            android:id="@+id/OctalLabel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="24dp"
            android:text="Octal" />

        <EditText
            android:id="@+id/OctalText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:layout_gravity="fill" />
    </LinearLayout>

</ScrollView>

<android.inputmethodservice.KeyboardView
    android:id="@+id/keyboardview_hex"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_margin="0dp"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:keyBackground="@drawable/btn_keyboard_key_ics"
    android:visibility="gone" />

<android.inputmethodservice.KeyboardView
    android:id="@+id/keyboardview_dec"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_margin="0dp"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:keyBackground="@drawable/btn_keyboard_key_ics"
    android:visibility="gone" />

<android.inputmethodservice.KeyboardView
    android:id="@+id/keyboardview_oct"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_margin="0dp"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:keyBackground="@drawable/btn_keyboard_key_ics"
    android:visibility="gone" />

<android.inputmethodservice.KeyboardView
    android:id="@+id/keyboardview_bin"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_margin="0dp"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:keyBackground="@drawable/btn_keyboard_key_ics"
    android:visibility="gone" />

这还不够。我还需要在显示KeyboardView时设置ScrollView的android:layout_above属性,并使用界面执行此操作:

public interface OnKeyboardStateChangedListener
{
    public void OnDisplay(View currentview, KeyboardView currentKeyboard);

    public void OnHide(KeyboardView currentKeyboard);
} 

并将此接口实现到我的MainActivity以编辑ScrollView的属性:

public class MainActivity extends Activity BaseKeyboard.OnKeyboardStateChangedListener

我还将MainActivity作为参数传递并保存为OnKeyboardStateChangedListener:

private OnKeyboardStateChangedListener mStateListener;

public BaseKeyboard(Activity host, int viewid, int layoutid, OnKeyboardStateChangedListener listener) {
    ..
    ..
    mStateListener = listener;
}

在显示/隐藏键盘时调用它:

public void showCustomKeyboard( View v ) {
    mKeyboardView.setVisibility(View.VISIBLE);
    mKeyboardView.setEnabled(true);
    if( v!=null ) {
        mStateListener.OnDisplay(v, mKeyboardView);
        ((InputMethodManager)mHostActivity.getSystemService(Activity.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(), 0);
    }
}

public void hideCustomKeyboard() {
    mKeyboardView.setVisibility(View.GONE);
    mKeyboardView.setEnabled(false);
    mStateListener.OnHide(mKeyboardView);
}

最后我编辑了MainActivity中的参数:

@Override
public void OnDisplay(View currentview, KeyboardView currentKeyboard) {
    ScrollView mScroll = (ScrollView) findViewById(R.id.scroll_content);
    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
            RelativeLayout.LayoutParams.MATCH_PARENT);
    params.addRule(RelativeLayout.ABOVE,  currentKeyboard.getId());
    mScroll.setLayoutParams(params);                
    mScroll.scrollTo(0, currentview.getBaseline()); //Scrolls to focused EditText

}

@Override
public void OnHide(KeyboardView currentKeyboard) {
    ScrollView mScroll = (ScrollView) findViewById(R.id.scroll_content);
    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
            RelativeLayout.LayoutParams.WRAP_CONTENT);
    mScroll.setLayoutParams(params);

}

以下是截图:

说明:

  • 我在ScrollView中有LinearLayout而不是RelativeLayout,因为当我的键盘显示时,ScrollView会根据需要运行,但它会将最底部的View切成两半而填充或边距在这种情况下不能与RelativeLayout一起使用但是添加了paddingBottom到LinearLayout会将其推回,并且所有视图都可见。我找不到另一种解决方法。

  • 您应该尝试不同大小的填充以满足您的需求。

  • 如果需要,我可以提供完整的源代码和其他信息。

答案 1 :(得分:0)

检查并正常工作。

你的主要布局是一个RelativeLayout,它给出了一个相对布局,所以一切都在视图中相对变化

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>

<ScrollView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <EditText
            android:id="@+id/edittext0"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="30dp"
            android:inputType="text" />

        <EditText
            android:id="@+id/edittext1"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/edittext0"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="30dp"
            android:inputType="text" />

        <EditText
            android:id="@+id/edittext2"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/edittext1"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="40dp"
            android:inputType="text" />

        <EditText
            android:id="@+id/edittext3"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/edittext2"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="40dp"
            android:inputType="text" />

        <EditText
            android:id="@+id/edittext4"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/edittext3"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="40dp"
            android:inputType="text" />
    </RelativeLayout>
</ScrollView>

<android.inputmethodservice.KeyboardView
    android:id="@+id/keyboardview"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:visibility="gone" />
 </RelativeLayout>

检查此输出我刚试过

Img1 = http://i44.tinypic.com/2412r0n.png Img2 = enter link description here