如何制作Android自定义键盘?

时间:2012-03-06 02:57:59

标签: android keyboard

我想制作一个自定义键盘。我不知道如何在xml和activity中做到这一点。这张照片是我的键盘型号。它只需要数字。

enter image description here

9 个答案:

答案 0 :(得分:71)

首先,您需要一个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 drawable并将其放在res / drawable-ldpi文件夹中,其大小非常小(如18x18像素)

然后在您希望使用的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"(通常键盘会显示在屏幕的底部)

然后,您需要在处理要将键盘附加到onCreate的{​​{1}} Activity的{​​{1}}函数中添加以下代码

TextView

**请注意, // 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); mKeyboard是您必须创建的私有类变量。

然后你需要以下功能来打开键盘(你必须通过mKeyboardView xml属性将它与TextView相关联)

onClick

最后,您需要处理事件的 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

希望有所帮助!!!

大多数代码都找到here

答案 1 :(得分:48)

系统键盘

此答案说明如何制作可在用户手机上安装的任何应用中使用的自定义系统键盘。如果您想制作一个仅在您自己的应用中使用的键盘,请see my other answer

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

enter image description here

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

1。启动一个新的Android项目

我将我的项目命名为#34; Custom Keyboard&#34;。随便打电话给你。这里没有什么特别的。我将离开MainActivity和&#34; Hello World!&#34;布局原样。

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

键预览是按键盘键时弹出的布局。它只显示你正在按下的键(如果你的大指,胖指覆盖它)。这不是一个多选弹出窗口。为此,您应该查看Candidates view

<?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并选择新建&gt;目录。)

然后将以下两个xml文件添加到其中。 (右键单击xml文件夹,然后选择新建&gt; XML资源文件。)

  • number_pad.xml
  • method.xml

<强> number_pad.xml

这是它开始变得更有趣的地方。这个Keyboard定义了keys的布局。

<?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表示每个键占据 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设置&gt;语言和输入&gt; “当前键盘”&gt;选择键盘。
  • 您应该会在列表中看到自定义键盘。启用它。
  • 返回并再次选择当前键盘。您应该在列表中看到自定义键盘。选择它。

现在,您应该可以在键入Android的任何位置使用键盘。

进一步研究

上面的键盘是可用的,但要创建其他人想要使用的键盘,您可能需要添加更多功能。研究下面的链接,了解如何。

继续

不喜欢标准KeyboardView的外观和行为?我当然不会。从Android 2.0开始,它看起来还没有更新。 Play商店中的所有自定义键盘怎么样?它们看起来不像上面的丑陋键盘。

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

  1. 创建您自己的子类ViewGroup的自定义键盘视图。您可以使用Button填充它,甚至可以创建自己的自定义键视图View。如果您使用弹出视图,则note this
  2. 在键盘中添加custom event listener界面。为onKeyClicked(String text)onBackspace()
  3. 之类的内容调用其方法
  4. 您不需要添加上述说明中描述的keyboard_view.xmlkey_preview.xmlnumber_pad.xml,因为这些都是标准KeyboardView。您将在自定义视图中处理所有这些UI方面。
  5. MyInputMethodService类中,实现您在键盘类中定义的自定义键盘侦听器。这取代了KeyboardView.OnKeyboardActionListener,不再需要它。
  6. MyInputMethodService班级onCreateInputView()方法中,创建并返回自定义键盘的实例。别忘了将键盘的自定义监听器设置为this

答案 2 :(得分:30)

使用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中定义了键盘的布局。有关此文件的详细信息,请查看此处:KeyboardKeyboard.RowKeyboard.Key

答案 3 :(得分:23)

应用程序内键盘

此答案说明如何使自定义键盘在您的应用中独占使用。如果您想制作可在任何应用中使用的系统键盘,请see my other answer

示例将如下所示。您可以针对任何键盘布局对其进行修改。

enter image description here

1。启动一个新的Android项目

我将我的项目命名为InAppKeyboard。无论你想要什么,都可以打电话给你。

2。添加布局文件

键盘布局

将布局文件添加到res/layout文件夹。我打电话给我keyboard。键盘将是一个自定义的compound view,我们将从这个xml布局文件中膨胀。您可以使用您喜欢的任何布局来排列键,但我使用的是LinearLayout。请注意merge标记。

RES /布局/ 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 /布局/ 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。添加Keyboard 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);
    }
}

如果您的Activity有多个EditTexts,那么您需要编写代码以将正确的EditText InputConnection传递给键盘。 (您可以通过向EditTexts添加OnFocusChangeListenerOnClickListener来执行此操作。有关此问题的讨论,请参阅this article。)您可能还希望在适当的时间隐藏或显示键盘。

完成

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

注释

  • 在xml布局文件中,如果您想让键看起来更好,您还可以使用TextView而不是Button。然后只需使背景成为可绘制的,在按下时改变外观状态。
  • 高级自定义键盘:为了提高键盘外观和键盘切换的灵活性,我现在正在创建子类View的自定义键视图和子类ViewGroup的自定义键盘。键盘以编程方式显示所有键。密钥使用接口与键盘通信(类似于片段与活动的通信方式)。如果您只需要一个键盘布局,则不需要这样做,因为xml布局可以正常工作。但是,如果您想查看我一直在处理的示例,请查看所有Key*Keyboard*here。请注意,我还使用容器视图,其功能是将键盘插入和移出。

答案 4 :(得分:14)

以下是软键盘的示例项目。

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

你的内容应该采用不同的布局。

编辑: 如果您只需要在您的应用程序中使用键盘,它非常简单! 创建具有垂直方向的线性布局,并在其内部以水平方向创建3个线性布局。 然后将每行的按钮放在每个水平线性布局中,并将权重属性分配给按钮。

使用android:layout_weight = 1来表示所有这些内容

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

答案 5 :(得分:7)

我找到的最好的记录示例之一。

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

提供了

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

答案 6 :(得分:1)

有同样的问题。我首先使用了表格布局,但按下按钮后布局不断变化。发现这个页面非常有用。 http://mobile.tutsplus.com/tutorials/android/android-user-interface-design-creating-a-numeric-keypad-with-gridlayout/

答案 7 :(得分:1)

最近,当我试图决定使用哪种方法来创建自己的自定义键盘时,我碰到了这篇文章。我发现Android系统API非常有限,因此我决定制作自己的应用内键盘。以Suragch's answer作为研究的基础,我继续设计my own keyboard component。它以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会处理其余部分!

我已经使用Number,NumberDecimal和QWERTY键盘进行了滚动。随时下载它并创建自己的布局和控制器。看起来像这样:

android custom keyboard gif landscape

enter image description here

即使这不是您决定采用的体系结构,希望它对于查看工作中的应用内键盘的源代码也会有所帮助。

同样,这是项目的链接:Custom In-App Keyboard

答案 8 :(得分:0)

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

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

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

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

资源    布局-> xml文件,描述应用程序的外观                    电话。类似于html的形状                    网页在浏览器上显示。允许                    您的应用可以相应地显示在屏幕上。

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

drawable-> pics {jpeg,png,...};给他们命名                         任何东西。

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

xml->更多xml文件。

src            ->行为类似于html中的JavaScript。布局                              文件将启动初始视图                              并且您的java文件将动态                              控制标签元素并触发                              事件。活动也可以被激活                              直接在layout.xml中,就像在                              html。

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

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

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

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

  1. 如上所述,创建文件和文件夹。我的目录如下所示:

    • 数字键盘
      • AndroidManifest.xml
      • src
        • 萨拉格
          • num_pad
            • MyInputMethodService.java
      • res
        • 可绘制
          • Suragch_NumPad_icon.png
        • 布局
          • key_preview.xml
          • keyboard_view.xml
        • xml
          • method.xml
          • number_pad.xml
          • colors.xml
          • strings.xml
          • styles.xml

请记住,如果您使用的是Android Studio这样的工具,那么它可能会有一个项目文件。

  1. 写文件。

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

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

<resources>

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

</resources>

H:Numpad / AndroidManifest.xml

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

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

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

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

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

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

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

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

以下是正确编辑的版本。我只是碰巧碰到一些提示,把我带到正确的地方来学习确切要导入的内容。

package Saragch.num_pad;

import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.KeyboardView;
import android.inputmethodservice.Keyboard;

import android.text.TextUtils;
import android.view.inputmethod.InputConnection;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;


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);
            }

            ic.deleteSurroundingText(1, 0);
            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() { }
}
  1. 编译并签名项目。

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

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

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