我想制作一个自定义键盘。我不知道如何使用XML和Java。下图是我要制作的键盘模型。它只需要数字。



评论

[使用Android设备的XML布局创建自己的自定义键盘](tutorials-android.blogspot.com/2011/06/…)

Tuts有一个很好的教程:link

Google有一个示例“ SoftKeyboard”项目,或者在这里链接了很多资源:customkeyboarddetails.blogspot.com/2019/02/…

#1 楼

首先,您需要一个keyboard.xml文件,该文件将放置在res/xml文件夹中(如果该文件夹不存在,则创建该文件)。
<?xml version="1.0" encoding="utf-8"?> 
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="15%p"
    android:keyHeight="15%p" >

    <Row>
        <Key android:codes="1"    android:keyLabel="1" android:horizontalGap="4%p"/>
        <Key android:codes="2"    android:keyLabel="2" android:horizontalGap="4%p"/>
        <Key android:codes="3"    android:keyLabel="3" android:horizontalGap="4%p" />
        <Key android:codes="4"    android:keyLabel="4" android:horizontalGap="4%p" />
        <Key android:codes="5"    android:keyLabel="5" android:horizontalGap="4%p" />
    </Row>
    <Row>
        <Key android:codes="6"    android:keyLabel="6" android:horizontalGap="4%p"/>
        <Key android:codes="7"    android:keyLabel="7" android:horizontalGap="4%p"/>
        <Key android:codes="8"    android:keyLabel="8" android:horizontalGap="4%p" />
        <Key android:codes="9"    android:keyLabel="9" android:horizontalGap="4%p" />
        <Key android:codes="0"    android:keyLabel="0" android:horizontalGap="4%p" />
    </Row>

    <Row>
        <Key android:codes="-1"    android:keyIcon="@drawable/backspace" android:keyWidth="34%p" android:horizontalGap="4%p"/>
        <Key android:codes="100"    android:keyLabel="Enter" android:keyWidth="53%p" android:horizontalGap="4%p"/>
    </Row>
 </Keyboard>

**请注意,您必须创建backspace可绘制对象并将其放置在具有很小尺寸(例如18x18像素)的res / drawable-ldpi文件夹中
然后在要使用它的xml文件(TextView所在的位置)中,应添加以下代码:
<RelativeLayout
 ...
>

        .....


        <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>

**请注意,要放置android.inputmethodservice.KeyboardView的XML文件必须是RelativeLayout才能设置alignParentBottom="true"(通常,键盘位于屏幕底部)
然后您需要在处理要连接键盘的onCreateActivityTextView函数中添加以下代码
    // Create the Keyboard
    mKeyboard= new Keyboard(this,R.xml.keyboard);

    // Lookup the KeyboardView
    mKeyboardView= (KeyboardView)findViewById(R.id.keyboardview);
    // Attach the keyboard to the view
    mKeyboardView.setKeyboard( mKeyboard );
    
    // Do not show the preview balloons
    //mKeyboardView.setPreviewEnabled(false);
    
    // Install the key handler
    mKeyboardView.setOnKeyboardActionListener(mOnKeyboardActionListener);

**请注意,mKeyboardmKeyboardView是私有类您必须创建的变量。
然后,需要以下功能来打开键盘(必须关联通过onClick xml属性与TextView一起使用)
    public void openKeyboard(View v)
    {
       mKeyboardView.setVisibility(View.VISIBLE);
       mKeyboardView.setEnabled(true);
       if( v!=null)((InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(), 0);
    }

最后,您需要可以处理事件的OnKeyboardActionListener
private OnKeyboardActionListener mOnKeyboardActionListener = new OnKeyboardActionListener() {
    @Override public void onKey(int primaryCode, int[] keyCodes) 
    {
         //Here check the primaryCode to see which key is pressed 
         //based on the android:codes property
         if(primaryCode==1)
         {
            Log.i("Key","You just pressed 1 button");
         }
    }

    @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() {
    }
};

希望有帮助!!!
在此处找到的大多数代码
____________________________________________________________-
编辑:
由于KeyboardView自API级别29开始就被贬值,因此在实现键盘之前,您可以在此网站上找到其代码并在您的代码中创建一个类。如上所述。

评论


如果我不希望键盘位于屏幕底部怎么办? (例如,我希望用户能够对其进行拖动)。那是我可以通过键盘应用程序控制的事情,还是由android系统处理?

–user3294126
16 Mar 2 '16 at 21:05

键盘宽度未填满屏幕我应该怎么做才能使其填满所有屏幕

–乔治·托马斯(George Thomas)
16年8月9日在7:31

KeyboardView所在的父布局是什么?还您检查过KeyboardView的layout_width吗?

– Pontios
16年8月9日在12:37

请注意,自API级别29开始,Google已弃用KeyboardView和Keyboard类。因此,如果您必须定位到较新的API级别,则此解决方案将来将不再起作用。

–maex
19年11月14日在7:03

Google反对使用keyboardView。什么是新解决方案?

–tohidmahmoudvand
7月25日下午3:04

#2 楼

系统键盘

此答案告诉您如何制作可在用户手机上安装的任何应用程序中使用的自定义系统键盘。如果您想制作只在自己的应用程序中使用的键盘,请参阅我的其他答案。

下面的示例如下所示。您可以为任何键盘布局修改它。



以下步骤显示了如何创建有效的自定义系统键盘。我尽可能地尝试删除任何不必要的代码。如果您还需要其他功能,我将在最后提供指向更多帮助的链接。

1。开始一个新的Android项目

我将我的项目命名为“自定义键盘”。随便叫什么。这里没有什么特别的。我将只留下MainActivity和“ Hello World!”保持原样。

2。添加布局文件

将以下两个文件添加到应用程序的res/layout文件夹中:


keyboard_view.xml
key_preview.xml

keyboard_view.xml

该视图就像一个可以容纳我们键盘的容器。在此示例中,只有一个键盘,但是您可以添加其他键盘,然后将其换入KeyboardView中。

<?xml version="1.0" encoding="utf-8"?>
<android.inputmethodservice.KeyboardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/keyboard_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:keyPreviewLayout="@layout/key_preview"
    android:layout_alignParentBottom="true">

</android.inputmethodservice.KeyboardView>


key_preview.xml

按键预览是当您按下键盘键时弹出的布局。它只是显示您正在按下的键(以防大而粗的手指遮住了它)。这不是多选弹出窗口。为此,您应该查看“候选人”视图。

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:background="@android:color/white"
    android:textColor="@android:color/black"
    android:textSize="30sp">
</TextView>


3。添加支持的xml文件

xml文件夹中创建一个res文件夹。 (右键单击res,然后选择“新建”>“目录”。)然后将以下两个xml文件添加到其中。 (右键单击xml文件夹,然后选择“新建”>“ XML资源文件”。)


number_pad.xml
method.xml

number_pad.xml

这是开始变得更有趣的地方。该Keyboard定义了按键的布局。

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="20%p"
    android:horizontalGap="5dp"
    android:verticalGap="5dp"
    android:keyHeight="60dp">

    <Row>
        <Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left"/>
        <Key android:codes="50" android:keyLabel="2"/>
        <Key android:codes="51" android:keyLabel="3"/>
        <Key android:codes="52" android:keyLabel="4"/>
        <Key android:codes="53" android:keyLabel="5" android:keyEdgeFlags="right"/>
    </Row>

    <Row>
        <Key android:codes="54" android:keyLabel="6" android:keyEdgeFlags="left"/>
        <Key android:codes="55" android:keyLabel="7"/>
        <Key android:codes="56" android:keyLabel="8"/>
        <Key android:codes="57" android:keyLabel="9"/>
        <Key android:codes="48" android:keyLabel="0" android:keyEdgeFlags="right"/>
    </Row>

    <Row>
        <Key android:codes="-5"
             android:keyLabel="DELETE"
             android:keyWidth="40%p"
             android:keyEdgeFlags="left"
             android:isRepeatable="true"/>
        <Key android:codes="10"
             android:keyLabel="ENTER"
             android:keyWidth="60%p"
             android:keyEdgeFlags="right"/>
    </Row>

</Keyboard>


这里有一些注意事项:



keyWidth:这是每个键的默认宽度。 20%p表示每个密钥应占用父密钥宽度的20%。但是,可以用单个键来覆盖它,就像您看到的第三行的Delete和Enter键一样。

keyHeight:这里是硬编码的,但是您可以使用类似@dimen/key_height的东西来为不同的屏幕尺寸动态设置它。

Gap:水平和垂直间隙表明键之间要留多少空间。即使将其设置为0px,仍然存在很小的间隙。

codes:这可以是Unicode或自定义代码值,用于确定按下键时会发生什么或输入了什么。如果要输入更长的Unicode字符串,请参见keyOutputText

keyLabel:这是键上显示的文本。

keyEdgeFlags:这表明键应与哪个边缘对齐。

isRepeatable:如果按住键,它将继续重复输入。

method.xml

此文件告诉系统可用的输入法子类型。我在这里只是一个最小版本。

<?xml version="1.0" encoding="utf-8"?>
<input-method
    xmlns:android="http://schemas.android.com/apk/res/android">

    <subtype
        android:imeSubtypeMode="keyboard"/>

</input-method>


4。添加Java代码以处理键输入

创建一个新的Java文件。我们称之为MyInputMethodService。该文件将所有内容捆绑在一起。它处理从键盘接收的输入,并将其发送到接收它的任何视图(例如EditText)。

public class MyInputMethodService extends InputMethodService implements KeyboardView.OnKeyboardActionListener {

    @Override
    public View onCreateInputView() {
        // get the KeyboardView and add our Keyboard layout to it
        KeyboardView keyboardView = (KeyboardView) getLayoutInflater().inflate(R.layout.keyboard_view, null);
        Keyboard keyboard = new Keyboard(this, R.xml.number_pad);
        keyboardView.setKeyboard(keyboard);
        keyboardView.setOnKeyboardActionListener(this);
        return keyboardView;
    }

    @Override
    public void onKey(int primaryCode, int[] keyCodes) {

        InputConnection ic = getCurrentInputConnection();
        if (ic == null) return;
        switch (primaryCode) {
            case Keyboard.KEYCODE_DELETE:
                CharSequence selectedText = ic.getSelectedText(0);
                if (TextUtils.isEmpty(selectedText)) {
                    // no selection, so delete previous character
                    ic.deleteSurroundingText(1, 0);
                } else {
                    // delete the selection
                    ic.commitText("", 1);
                }
                break;
            default:
                char code = (char) primaryCode;
                ic.commitText(String.valueOf(code), 1);
        }
    }

    @Override
    public void onPress(int primaryCode) { }

    @Override
    public void onRelease(int primaryCode) { }

    @Override
    public void onText(CharSequence text) { }

    @Override
    public void swipeLeft() { }

    @Override
    public void swipeRight() { }

    @Override
    public void swipeDown() { }

    @Override
    public void swipeUp() { }
}


注意:


OnKeyboardActionListener监听键盘输入。此示例中还需要所有这些空方法。
InputConnection用于将输入发送到另一个视图,例如EditText

5。更新清单

我把这放在最后而不是放在第一位,因为它指的是我们上面已经添加的文件。要将自定义键盘注册为系统键盘,您需要在AndroidManifest.xml文件中添加一个service部分。将其放在application之后的activity部分中。

<manifest ...>
    <application ... >
        <activity ... >
            ...
        </activity>

        <service
            android:name=".MyInputMethodService"
            android:label="Keyboard Display Name"
            android:permission="android.permission.BIND_INPUT_METHOD">
            <intent-filter>
                <action android:name="android.view.InputMethod"/>
            </intent-filter>
            <meta-data
                android:name="android.view.im"
                android:resource="@xml/method"/>
        </service>

    </application>
</manifest>


就这样!您现在应该可以运行您的应用了。但是,只有在设置中启用键盘后,您才能看到太多内容。

6。在“设置”中启用键盘

每个想要使用您的键盘的用户都必须在Android设置中启用它。有关如何执行此操作的详细说明,请参见以下链接:


如何在Android手机上设置默认键盘

以下是摘要:


转到Android设置>语言和输入>当前键盘>选择键盘。
您应该在列表上看到“自定义键盘”。启用它。
返回并再次选择“当前键盘”。您应该在列表上看到“自定义键盘”。选择它。

现在,您应该可以在可以在Android中键入的任何地方使用键盘。

进一步研究

上面的键盘是可用,但是要创建其他人想要使用的键盘,您可能必须添加更多功能。请研究以下链接以了解操作方法。



创建输入法(Android文档)

SoftKeyboard(来自Android的自定义演示源代码键盘)

构建自定义Android键盘(教程)(源代码)

在Android上创建自定义键盘(tutsplus教程)

如何为android创建自定义键盘(YouTube视频:这是无声的,但接下来是我第一次学习如何做到这一点。)

继续

不喜欢标准的KeyboardView的外观和行为?我当然不会。自Android 2.0以来似乎尚未更新。 Play商店中的所有这些自定义键盘怎么样?它们看起来不像上面的丑陋键盘。

好消息是您可以完全自定义自己键盘的外观和行为。您将需要执行以下操作:


创建子类ViewGroup的自定义键盘视图。您可以用Button填充它,甚至可以创建属于View子类的自定义键视图。如果使用弹出视图,请注意这一点。
在键盘中添加自定义事件侦听器界面。为诸如onKeyClicked(String text)onBackspace()之类的东西调用其方法。您将在自定义视图中处理所有这些UI方面。
keyboard_view.xml类中,实现在键盘类中定义的自定义键盘侦听器。这代替了不再需要的key_preview.xml
number_pad.xml类的KeyboardView方法中,创建并返回自定义键盘的实例。不要忘记将键盘的自定义侦听器设置为MyInputMethodService


#3 楼

应用内键盘

此答案告诉您如何制作自定义键盘以专门在您的应用中使用。如果要制作可在任何应用程序中使用的系统键盘,请参阅我的其他答案。

示例如下所示。您可以为任何键盘布局进行修改。



1。开始一个新的Android项目

我将我的项目命名为InAppKeyboard。随便叫什么。

2。添加布局文件

键盘布局

将布局文件添加到res/layout文件夹。我叫我keyboard。键盘将是一个自定义复合视图,我们将从该xml布局文件中对其进行充气。您可以使用任何喜欢的布局来安排键,但是我使用的是LinearLayout。请注意merge标签。

res / layout / keyboard.xml

<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@+id/button_1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="1"/>

            <Button
                android:id="@+id/button_2"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="2"/>

            <Button
                android:id="@+id/button_3"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="3"/>

            <Button
                android:id="@+id/button_4"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="4"/>

            <Button
                android:id="@+id/button_5"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="5"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@+id/button_6"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="6"/>

            <Button
                android:id="@+id/button_7"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="7"/>

            <Button
                android:id="@+id/button_8"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="8"/>

            <Button
                android:id="@+id/button_9"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="9"/>

            <Button
                android:id="@+id/button_0"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="0"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@+id/button_delete"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:text="Delete"/>

            <Button
                android:id="@+id/button_enter"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="3"
                android:text="Enter"/>

        </LinearLayout>
    </LinearLayout>

</merge>


活动布局

用于演示目的我们的活动只有一个EditText,键盘位于底部。我将自定义键盘视图称为MyKeyboard。 (我们将很快添加此代码,因此暂时忽略该错误。)将所有键盘代码放入单个视图中的好处是,它易于在其他活动或应用程序中重用。

res / layout / activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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="com.example.inappkeyboard.MainActivity">

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#c9c9f1"
        android:layout_margin="50dp"
        android:padding="5dp"
        android:layout_alignParentTop="true"/>

    <com.example.inappkeyboard.MyKeyboard
        android:id="@+id/keyboard"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_alignParentBottom="true"/>

</RelativeLayout>


3。添加键盘Java文件

添加新的Java文件。我叫我的MyKeyboard

这里要注意的最重要的一点是,没有任何EditTextActivity的硬链接。这样可以轻松地将其插入需要它的任何应用程序或活动中。此自定义键盘视图还使用InputConnection,它模仿系统键盘与EditText进行通信的方式。这就是避免硬链接的方法。

MyKeyboard是一种复合视图,可以扩大我们在上面定义的视图布局。

MyKeyboard.java

public class MyKeyboard extends LinearLayout implements View.OnClickListener {

    // constructors
    public MyKeyboard(Context context) {
        this(context, null, 0);
    }

    public MyKeyboard(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyKeyboard(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    // keyboard keys (buttons)
    private Button mButton1;
    private Button mButton2;
    private Button mButton3;
    private Button mButton4;
    private Button mButton5;
    private Button mButton6;
    private Button mButton7;
    private Button mButton8;
    private Button mButton9;
    private Button mButton0;
    private Button mButtonDelete;
    private Button mButtonEnter;

    // This will map the button resource id to the String value that we want to 
    // input when that button is clicked.
    SparseArray<String> keyValues = new SparseArray<>();

    // Our communication link to the EditText
    InputConnection inputConnection;

    private void init(Context context, AttributeSet attrs) {

        // initialize buttons
        LayoutInflater.from(context).inflate(R.layout.keyboard, this, true);
        mButton1 = (Button) findViewById(R.id.button_1);
        mButton2 = (Button) findViewById(R.id.button_2);
        mButton3 = (Button) findViewById(R.id.button_3);
        mButton4 = (Button) findViewById(R.id.button_4);
        mButton5 = (Button) findViewById(R.id.button_5);
        mButton6 = (Button) findViewById(R.id.button_6);
        mButton7 = (Button) findViewById(R.id.button_7);
        mButton8 = (Button) findViewById(R.id.button_8);
        mButton9 = (Button) findViewById(R.id.button_9);
        mButton0 = (Button) findViewById(R.id.button_0);
        mButtonDelete = (Button) findViewById(R.id.button_delete);
        mButtonEnter = (Button) findViewById(R.id.button_enter);

        // set button click listeners
        mButton1.setOnClickListener(this);
        mButton2.setOnClickListener(this);
        mButton3.setOnClickListener(this);
        mButton4.setOnClickListener(this);
        mButton5.setOnClickListener(this);
        mButton6.setOnClickListener(this);
        mButton7.setOnClickListener(this);
        mButton8.setOnClickListener(this);
        mButton9.setOnClickListener(this);
        mButton0.setOnClickListener(this);
        mButtonDelete.setOnClickListener(this);
        mButtonEnter.setOnClickListener(this);

        // map buttons IDs to input strings
        keyValues.put(R.id.button_1, "1");
        keyValues.put(R.id.button_2, "2");
        keyValues.put(R.id.button_3, "3");
        keyValues.put(R.id.button_4, "4");
        keyValues.put(R.id.button_5, "5");
        keyValues.put(R.id.button_6, "6");
        keyValues.put(R.id.button_7, "7");
        keyValues.put(R.id.button_8, "8");
        keyValues.put(R.id.button_9, "9");
        keyValues.put(R.id.button_0, "0");
        keyValues.put(R.id.button_enter, "\n");
    }

    @Override
    public void onClick(View v) {

        // do nothing if the InputConnection has not been set yet
        if (inputConnection == null) return;

        // Delete text or input key value
        // All communication goes through the InputConnection
        if (v.getId() == R.id.button_delete) {
            CharSequence selectedText = inputConnection.getSelectedText(0);
            if (TextUtils.isEmpty(selectedText)) {
                // no selection, so delete previous character
                inputConnection.deleteSurroundingText(1, 0);
            } else {
                // delete the selection
                inputConnection.commitText("", 1);
            }
        } else {
            String value = keyValues.get(v.getId());
            inputConnection.commitText(value, 1);
        }
    }

    // The activity (or some parent or controller) must give us 
    // a reference to the current EditText's InputConnection
    public void setInputConnection(InputConnection ic) {
        this.inputConnection = ic;
    }
}


4。将键盘指向EditText

对于系统键盘,Android使用InputMethodManager将键盘指向重点突出的EditText。在此示例中,该活动将通过提供从EditText到我们的自定义键盘的链接来代替。

由于我们不使用系统键盘,因此需要禁用它以使其免受当我们触摸EditText时弹出。其次,我们需要从InputConnection中获取EditText并将其提供给键盘。

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EditText editText = (EditText) findViewById(R.id.editText);
        MyKeyboard keyboard = (MyKeyboard) findViewById(R.id.keyboard);

        // prevent system keyboard from appearing when EditText is tapped
        editText.setRawInputType(InputType.TYPE_CLASS_TEXT);
        editText.setTextIsSelectable(true);

        // pass the InputConnection from the EditText to the keyboard
        InputConnection ic = editText.onCreateInputConnection(new EditorInfo());
        keyboard.setInputConnection(ic);
    }
}


如果您的活动具有多个EditText,那么您将需要编写代码以将正确的EditText的InputConnection传递给键盘。 (您可以通过在EditTexts中添加OnFocusChangeListenerOnClickListener来实现此目的。有关此内容的讨论,请参见本文。)您可能还想在适当的时候隐藏或显示键盘。

完成

就是这样。您应该能够立即运行示例应用程序,并根据需要输入或删除文本。下一步是修改所有内容以适合您自己的需求。例如,在我的某些键盘中,我使用了TextViews而不是Buttons,因为它更易于自定义。

注释


在xml布局文件中,如果您想使按键看起来更好,也可以使用TextView而不是Button。然后只需将背景设为可绘制的背景即可,按下该按钮即可更改外观状态。
高级自定义键盘:为了在键盘外观和键盘切换方面具有更大的灵活性,我现在制作子类View的自定义键视图和子类ViewGroup的自定义键盘。键盘以编程方式布置所有键。按键使用接口与键盘进行通信(类似于片段与活动进行通信的方式)。如果您只需要一个键盘布局,则这不是必需的,因为xml布局可以正常工作。但是,如果您想查看我正在从事的工作的示例,请在此处查看所有Key*Keyboard*类。请注意,我还在那里使用了一个容器视图,该视图的功能是交换键盘的内容。


评论


您的答案很好,但是如何设置在原始键盘和新键盘之间切换。

– Kishan Donga
18 Mar 20 '18在6:35

@KishanDonga,您可以在键盘上添加按键来切换键盘。当用户按下时,调用InputMethodManager#showInputMethodPicker()。但是,如果原始键盘没有这样的键,则用户切换到键盘的唯一方法是在系统设置中手动进行操作。在这方面,Apple优于Android,因为Apple要求所有键盘都必须具有键盘切换键。

– Suragch
18-3-20在7:56



@KishanDonga,我刚刚意识到,这个答案是关于应用内键盘的,而不是系统键盘。如果要在两个自定义键盘之间交换,则可以以编程方式在容器视图内外进行交换。只需在两个键盘上添加交换键盘键即可。请参阅我的“高级自定义键盘”注释和上面答案中的链接。

– Suragch
18 Mar 20 '18在8:02

如果要在键盘和系统键盘之间切换,请隐藏系统键盘并在适当的时间显示键盘(反之亦然)。

– Suragch
18年3月20日在8:04

@MarekTakac,您将需要禁用系统键盘,并在每个活动中添加自定义键盘。如果活动具有多个EditText,则需要向它们添加onFocusChangedListener,以便在它们获得焦点时可以将InputConnection从当前EditText分配给自定义键盘。

– Suragch
18年7月15日在10:58



#4 楼

使用KeyboardView

KeyboardView kbd = new KeyboardView(context);
kbd.setKeyboard(new Keyboard(this, R.xml.custom));

kbd.setOnKeyboardActionListener(new OnKeyboardActionListener() {
    ....
}


现在您有了kbd,这是正常视图。

这样做的好处是R.xml.custom指的是/res/xml/custom.xml,它在xml中定义键盘的布局。有关此文件的更多信息,请参见此处:Keyboard,Keyboard.Row,Keyboard.Key。

评论


我正在使用KeyboardView类,但是从API 29开始,现在已弃用。

–阿比吉特
5月2日下午3:47

#5 楼

这是软键盘的示例项目。

https://developer.android.com/guide/topics/text/creating-input-method.html

应该在同一行中使用不同的布局。

编辑:
如果仅在应用程序中需要键盘,则非常简单!
创建垂直方向的线性布局,并在其中以水平方向创建3个线性布局。
然后将每行的按钮放置在每个水平线性布局中,并将weight属性分配给按钮。全部使用android:layout_weight = 1,这样它们之间的间距相等。

这将解决。如果您没有得到期望的结果,请在此处发布代码,我们将在这里为您提供帮助!

评论


该编辑实际上是错误的,因为这将意味着始终显示键盘并且其行为不会像普通的Android键盘那样。

–m0skit0
18年9月11日14:32在

#6 楼

我找到的最好的有据可查的例子之一。

http://www.fampennings.nl/maarten/android/09keyboard/index.htm

KeyboardView相关的XML文件和提供的源代码。

评论


现在不推荐使用KeyboardView

– Alberto M
6月22日14:34

#7 楼

我最近在尝试决定使用哪种方法来创建自己的自定义键盘时碰到了这篇文章。我发现Android系统API非常有限,因此我决定制作自己的应用内键盘。使用Suragch的答案作为研究的基础,我继续设计了自己的键盘组件。它以MIT许可证发布在GitHub上。希望这将为其他人节省很多时间和头痛。
该体系结构非常灵活。有一个主视图(CustomKeyboardView),您可以使用所需的任何键盘布局和控制器进行注入。
您只需要在活动xml中声明CustomKeyboardView(也可以以编程方式进行操作):
    <com.donbrody.customkeyboard.components.keyboard.CustomKeyboardView
    android:id="@+id/customKeyboardView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true" />

然后用它注册您的EditText,并告诉它应该使用哪种类型的键盘:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val numberField: EditText = findViewById(R.id.testNumberField)
    val numberDecimalField: EditText = findViewById(R.id.testNumberDecimalField)
    val qwertyField: EditText = findViewById(R.id.testQwertyField)

    keyboard = findViewById(R.id.customKeyboardView)
    keyboard.registerEditText(CustomKeyboardView.KeyboardType.NUMBER, numberField)
    keyboard.registerEditText(CustomKeyboardView.KeyboardType.NUMBER_DECIMAL, numberDecimalField)
    keyboard.registerEditText(CustomKeyboardView.KeyboardType.QWERTY, qwertyField)
}

CustomKeyboardView可以处理其余的键盘!
我用一个数字,NumberDecimal和QWERTY键盘。随时下载它并创建自己的布局和控制器。看起来像这样:


即使这不是您决定采用的体系结构,希望它对于查看工作中的应用内键盘的源代码也会有所帮助。再次,这是该项目的链接:自定义应用内键盘
编辑:我不再是Android开发人员,并且不再维护此GitHub项目。此时可能会有更多现代方法和架构,但是如果您愿意并分叉它,请随时参考GitHub项目。

#8 楼

到目前为止,Suragch给出了最好的答案,但是他跳过了一些对编译应用程序很重要的小事情。

我希望通过改善他的答案来比Suragch做出更好的答案。我将添加他没有放的所有缺少的元素。

我使用android应用APK Builder 1.1.0编译了我的apk。因此,让我们开始吧。

要构建Android应用,我们需要几个文件和文件夹,它们以某种格式组织并相应地大写。


res
布局-> xml文件,描述了应用程序在手机上的外观。类似于html如何塑造
网页在浏览器中的外观。允许您的应用程序相应地适合屏幕。

值->常量数据,例如colors.xml,
strings.xml,styles.xml。这些文件必须
正确拼写。

drawable->图片{jpeg,png,...};将它们命名为
任何东西。

mipmap->更多图片。用于应用程序图标?

xml->更多xml文件。

->类似于html中的JavaScript。 layout
文件将启动初始视图
,而您的java文件将动态
控制标签元素和触发器
事件。也可以直接在layout.xml中激活事件,就像在
html中一样。

AndroidManifest.xml->
该文件注册您的应用程序有关的内容。应用程序名称,程序类型,所需的权限等。这似乎使Android变得相当安全。程序实际上不能执行清单中未要求的功能。

现在有4种类型的Android程序,即活动,服务,内容提供商和广播接收者。我们的键盘将是一项服务,可使其在后台运行。它不会出现在要启动的应用程序列表中。但可以将其卸载。

要编译您的应用,需要使用gradle和apk签名。您可以对其进行研究,也可以使用APK Builder for Android。超级简单。

现在我们了解Android开发,让我们创建文件和文件夹。



将文件和文件夹创建为我在上面讨论过。我的目录如下所示:


NumPad


AndroidManifest.xml
src


/> Saragch


num_pad


MyInputMethodService.java







res


可绘制


Suragch_NumPad_icon.png


布局


key_preview.xml
keyboard_view.xml


xml



方法。 xml
number_pad.xml





colors.xml
styles.xml









请记住,如果您使用的是Android之类的工具Studio中可能有一个项目文件。


编写文件。

A:NumPad / res / layout / key_preview.xml

<?xml version="1.0" encoding="utf-8"?>
   <TextView
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:gravity="center"
      android:background="@android:color/white"
      android:textColor="@android:color/black"
      android:textSize="30sp">
</TextView>


B:NumPad / res / layout / keyboard_view.xml

<?xml version="1.0" encoding="utf-8"?>
<android.inputmethodservice.KeyboardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/keyboard_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:keyPreviewLayout="@layout/key_preview"
    android:layout_alignParentBottom="true">

</android.inputmethodservice.KeyboardView>


C:NumPad / res / xml / method.xml

<?xml version="1.0" encoding="utf-8"?>
<input-method  xmlns:android="http://schemas.android.com/apk/res/android">
    <subtype  android:imeSubtypeMode="keyboard"/>
</input-method>


D:数字键/res/xml/number_pad.xml

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="20%p"
    android:horizontalGap="5dp"
    android:verticalGap="5dp"
    android:keyHeight="60dp">

    <Row>
        <Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left"/>
        <Key android:codes="50" android:keyLabel="2"/>
        <Key android:codes="51" android:keyLabel="3"/>
        <Key android:codes="52" android:keyLabel="4"/>
        <Key android:codes="53" android:keyLabel="5" android:keyEdgeFlags="right"/>
    </Row>

    <Row>
        <Key android:codes="54" android:keyLabel="6" android:keyEdgeFlags="left"/>
        <Key android:codes="55" android:keyLabel="7"/>
        <Key android:codes="56" android:keyLabel="8"/>
        <Key android:codes="57" android:keyLabel="9"/>
        <Key android:codes="48" android:keyLabel="0" android:keyEdgeFlags="right"/>
    </Row>

    <Row>
        <Key android:codes="-5"
             android:keyLabel="DELETE"
             android:keyWidth="40%p"
             android:keyEdgeFlags="left"
             android:isRepeatable="true"/>
        <Key android:codes="10"
             android:keyLabel="ENTER"
             android:keyWidth="60%p"
             android:keyEdgeFlags="right"/>
    </Row>

</Keyboard>


当然,您可以根据自己的喜好轻松对其进行编辑。您甚至可以使用图像来代替标签中的lf字。

Suragch并未演示values文件夹中的文件,并假设我们可以访问Android Studio;自动创建它们。我有APK构建器是一件好事。

E:NumPad / res / values / colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>
</resources>


F:NumPad / res / values /strings.xml

<resources>
    <string name="app_name">Suragch NumPad</string>
</resources>


G:NumPad / res / values / styles.xml

Q:Numpad / AndroidManifest.xml

确实需要扩展的文件。在这里,我觉得我永远也不会编译我的程序。哭泣。哭泣。如果您检查Suracgh的答案,您会看到他将第一组字段留空,并在该文件中添加了活动标签。如我所说,Android程序有四种类型。活动是带有启动器图标的常规应用。这个数字键盘不是活动!此外,他没有执行任何活动。

我的朋友不包含活动标签。您的程序将编译,并且在您尝试启动时将崩溃!至于xmlns:android和using-sdk;我不能在那帮你。只要可以尝试我的设置即可。

您会看到有一个服务标签,该标签将其注册为服务。同样,service.android:name必须是我们的java文件中公共类扩展服务的名称。必须将其相应地大写。包也是我们在java文件中声明的包的名称。

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
        <!-- Customize your theme here. -->
    </style>

</resources>


I:NumPad / src / Saragch / num_pad / MyInputMethodService.java

注意:我认为Java是src的替代方法。

这是另一个问题文件,但不如清单文件那样有争议。据我所知,Java足以知道什么是什么,什么不是。我几乎不了解xml及其与Android开发的关系!

这里的问题是他没有导入任何东西!我的意思是,他给了我们一个“完整的”文件,该文件使用了无法解析的名称! InputMethodService,键盘等。Suragch先生,这是一种不好的做法。感谢您的帮助,但是如果无法解析名称,您希望代码如何编译?

以下是正确编辑的版本。我只是碰巧碰到一些提示,把我带到正确的地方,以了解要确切输入什么。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="Saragch.num_pad">

    <uses-sdk
        android:minSdkVersion="12"
        android:targetSdkVersion="27" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/Suragch_NumPad_icon"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <service
            android:name=".MyInputMethodService"
            android:label="Keyboard Display Name"
            android:permission="android.permission.BIND_INPUT_METHOD">

            <intent-filter>
                <action android:name="android.view.InputMethod"/>
            </intent-filter>

            <meta-data
                android:name="android.view.im"
                android:resource="@xml/method"/>

        </service>

    </application>
</manifest>




编译并签名您的项目。

作为Android开发人员的新手,在这里我一无所知。我想手动学习它,因为我相信真正的程序员可以手动编译。


我认为gradle是用于apk编译和打包的工具之一。 apk似乎就像一个jar文件或zip文件的rar。然后有两种类型的签名。调试密钥(不允许在游戏商店中使用)和私钥。

好好帮萨拉格奇先生。感谢您观看我的视频。喜欢,订阅。

#9 楼

有同样的问题。我最初使用的是表格布局,但是按下按钮后布局一直在变化。发现此页面非常有用。 http://mobile.tutsplus.com/tutorials/android/android-user-interface-design-creating-a-numeric-keypad-with-gridlayout/

评论


不知道在哪里找到意大利面。示例仅具有实现onCreate的5行代码。

– Glenn
13-10-16在4:02