如何在 Android 中制作自定义键盘?

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

enter image description here

258163 次浏览

下面是一个软键盘的示例项目。

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

你的应该在相同的线条,不同的布局。

编辑: 如果你只需要在你的应用程序键盘,它非常简单! 创建一个垂直方向的线性布局,并在其中创建3个水平方向的线性布局。 然后将每一行的按钮放置在每一个水平线性布局中,并将权重属性分配给按钮。对所有这些文件都使用 android: lay _ weight = 1,这样它们的间距就相等了。

这会解决的。如果您没有得到预期的,请在这里发布代码,我们是来帮助您的!

使用 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 中定义了键盘的布局。关于这个文件的更多信息,请看这里: 键盘键盘,划键盘,钥匙

也有同样的问题。起初我使用了表格布局,但是在按下按钮之后布局一直在变化。不过我觉得这页很有用。http://mobile.tutsplus.com/tutorials/android/android-user-interface-design-creating-a-numeric-keypad-with-gridlayout/

这是我发现的最好的文档化的例子之一。

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

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

首先,您将需要一个 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可绘制文件,并将其放置在 res/draable-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"(通常键盘显示在屏幕底部)

然后,需要在 ActivityonCreate函数中添加以下代码,该函数处理要连接键盘的 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);

* * 注意,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之后就被折旧了,因此您可以在 本网站中找到它的代码,并在实现上述键盘之前在代码中创建一个类。

系统键盘

这个答案告诉我们如何制作一个定制的系统键盘,可以在用户安装在手机上的任何应用程序中使用。如果你想制作一个只能在你自己的应用程序中使用的键盘,那么 看看我的另一个答案

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

enter image description here

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

1. 开始一个新的 Android 项目

我把我的项目命名为“自定义键盘”。随便你怎么说。这里没什么特别的。我会离开 MainActivity和“你好世界!”布局就是这样。

2. 添加布局文件

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

  • Key _ view. xml
  • Key _ view. xml

Key _ 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 _ view. 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 文件

res文件夹中创建一个 xml文件夹(右键单击 res并选择 新增 > 目录)

然后向其中添加以下两个 xml 文件(右键单击 xml文件夹并选择 新增 > XML 资源档案)

  • Number _ pad. xml
  • 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意味着每个键应该占据 P的宽度的20% 。但是,它可以被单个键覆盖,正如您在第三行中看到的 Delete 和 Enter 键所发生的情况一样。
  • keyHeight : 这里对它进行了硬编码,但是您可以使用类似于 @dimen/key_height的东西来为不同的屏幕大小动态设置它。
  • Gap : 水平和垂直间隙表示键之间的空间。即使你把它设置为 0px仍然有一个小的差距。
  • codes : 这可以是一个 Unicode 或自定义代码值,用于确定按下键时发生的情况或输入的内容。如果要输入较长的 Unicode 字符串,请参见 keyOutputText
  • keyLabel : 这是键上显示的文本。
  • keyEdgeFlags : 这表示键应该对齐到哪个边。
  • isRepeatable : 如果你按住键,它会不断重复输入。

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节。把它放在 activity之后的 application部分。

<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 中输入的地方使用你的键盘了。

进一步研究

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

继续

不喜欢标准 KeyboardView的外观和行为?我当然不知道。看起来 Android 2.0之后就没更新过了。游戏商店里那些定制的键盘怎么样?它们看起来一点也不像上面那个丑陋的键盘。

好消息是,您可以完全自定义您自己的键盘的外观和行为。你需要做以下事情:

  1. 创建自己的子类 ViewGroup的自定义键盘视图。您可以用 Button填充它,甚至可以制作自己的子类 View的自定义键视图。如果使用弹出视图,则 注意这个
  2. 在键盘上添加一个 自定义事件侦听器接口。调用它的方法来处理像 onKeyClicked(String text)或者 onBackspace()这样的东西。
  3. 您不需要添加上述方向中描述的 keyboard_view.xmlkey_preview.xmlnumber_pad.xml,因为这些都是针对标准 KeyboardView的。您将在自定义视图中处理所有这些 UI 方面。
  4. MyInputMethodService类中,实现在键盘类中定义的自定义键盘侦听器。这代替了不再需要的 KeyboardView.OnKeyboardActionListener
  5. MyInputMethodService类的 onCreateInputView()方法中,创建并返回自定义键盘的实例。不要忘记将键盘的自定义侦听器设置为 this

嵌入式键盘

这个答案告诉我们如何制作一个自定义键盘专门用于您的应用程序。如果你想制作一个可以在任何应用程序中使用的系统键盘,那么 看看我的另一个答案

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

enter image description here

1. 开始一个新的 Android 项目

我把我的项目命名为 InAppKeyboard。你想叫什么就叫什么。

2. 添加布局文件

键盘布局

将布局文件添加到 res/layout文件夹。我叫我的 keyboard。键盘将是一个定制的 复合视图,我们将从这个 xml 布局文件充气。您可以使用任何布局,您喜欢安排的关键,但我使用的是 LinearLayout。请注意 merge标记。

Res/layp/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/layp/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 文件。

这里需要注意的最重要的一点是,没有到任何 EditTextActivity的硬链接。这使得将它插入任何需要它的应用程序或活动变得很容易。这个自定义键盘视图还使用 InputConnection,它模仿系统键盘与 EditText通信的方式。这就是我们如何避免硬链接。

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

将键盘指向 EditText

对于系统键盘,Android 使用 InputMethodManager 输入法管理器将键盘指向集中的 EditText。在此示例中,该活动将通过提供从 EditText到我们的自定义键盘到。

由于我们不使用系统键盘,我们需要禁用它,以防止它弹出时,我们触摸的 EditText。其次,我们需要从 EditText获得 InputConnection,并将其交给我们的键盘。

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 有多个 EditText,那么您需要编写代码将右边的 EditText 的 InputConnection传递给键盘。(可以通过向 EditText 添加 OnFocusChangeListenerOnClickListener来实现这一点。有关这一点的讨论,请参见 这篇文章。)您可能还希望在适当的时候隐藏或显示键盘。

结束了

就是这样。您现在应该能够运行示例应用程序并根据需要输入或删除文本。您的下一步是修改一切以适应您自己的需要。例如,在我的一些键盘中,我使用了 TextView 而不是 Buttons,因为这样更容易定制它们。

笔记

  • 在 xml 布局文件中,如果希望使键看起来更好,也可以使用 TextView而不是 Button。然后只要使背景成为一个可绘制的,当按下时改变外观状态。
  • 高级自定义键盘: 为了在键盘外观和键盘切换方面获得更大的灵活性,我现在制作了子类 View的自定义键视图和子类 ViewGroup的自定义键盘。键盘以编程方式布局所有键。键使用一个接口与键盘通信(类似于片段与活动的通信方式)。如果您只需要一个单一的键盘布局,那么这是不必要的,因为 xml 布局可以很好地满足这一要求。但是,如果你想看到一个例子,我一直在工作,检查所有的 Key*Keyboard*给你。注意,我还使用了一个容器视图,其功能是交换键盘进出。

最近,当我试图决定用什么方法来创建自己的自定义键盘时,偶然发现了这篇文章。我发现 Android 系统的 API 非常有限,所以我决定制作自己的应用内键盘。使用 苏拉奇的回答作为我研究的基础,我继续设计 我自己的键盘组件。发布在 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

即使这不是您决定使用的体系结构,希望查看应用程序内键盘的源代码会有所帮助。

同样,这里是到该项目的链接: 自定义应用程序内键盘

编辑: 我不再是一个 Android 开发者,我也不再维护这个 GitHub 项目。目前可能有更多的现代方法和体系结构,但是如果您愿意,请随时参考 GitHub 项目。

苏拉奇给出了迄今为止最好的答案,但是他跳过了一些对编译应用程序很重要的小细节。

我希望通过改进苏拉格的答案,得到一个比他更好的答案。我会添加所有他没有放入的缺失元素。

我使用 android 应用程序 APK Builder 1.1.0编译了我的 APK。

要构建一个 Android 应用程序,我们需要将文件和文件夹按照一定的格式组织起来,并相应地大写。

保留意见 布局-> xml 文件,描述应用程序的外观 类似于 html 的形状 网页浏览器。允许 你的应用程序,以适应屏幕相应。

Value-> 常量数据,例如 Colors.xml, Xml,styles.xml。这些文件必须 正确拼写。

{ jpeg,png,... } ; 命名它们 什么都行。

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

Xml-> 更多的 xml 文件。

- > 就像 html 中的 JavaScript 文件将启动起始视图 你的 java 文件将会动态地 控制标记元素和触发器 事件。事件也可以被激活 直接放在 layout.xml 中,就像 Html.

Xml-> 此文件注册您的应用程序是关于什么的。应用程序名称、程序类型、所需权限等。这似乎让 Android 变得相当安全。程序实际上不能做它们在清单中没有要求的事情。

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

要编译你的应用程序,需要 gradle 和 apk 签名。您可以研究一个或使用 APK 生成器的机器人。超级简单。

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

  1. 按照上面讨论的方式创建文件和文件夹:

    • 床垫
      • AndroidManifest.xml
      • Src
        • 萨拉奇
          • Num _ pad
            • MyInputMethodService.java
      • 保留意见
        • 可以画的
          • Suragch _ NumPad _ icon. png
        • 布局
          • Key _ view. xml
          • Key _ view. xml
        • Xml
          • Xml
          • Number _ pad. xml
        • 价值观
          • Xml
          • Xml
          • Xml

请记住,如果您使用的是像 Android Studio 这样的 IDE,它可能有一个项目文件。

  1. 写文件。

A: NumPad/res/layp/key _ view. 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/layp/key _ 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: Numpad/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>

当然,这可以很容易地编辑到您的喜好。你甚至可以使用图像代替如果标签的话。

Suragch 没有演示 value 文件夹中的文件,并假定我们可以访问 Android Studio; 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 的答案,您会看到他将第一组字段保留为空,并在该文件中添加 activity 标记。正如我所说,Android 程序有四种类型。一个活动是一个带有启动器图标的普通应用程序。这个数字板不是一个活动!此外,他没有实施任何活动。

我的朋友不包括活动标签。您的程序将编译,当您尝试启动它将崩溃!至于 xmlns: android 和 use-sdk; 我在这方面帮不上忙。试试我的设置,如果有用的话。

如您所见,有一个 service 标记,它将其注册为服务。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 开发联系在一起的!

问题是他没有进口任何东西!我的意思是,他给了我们一个“完整”的文件,其中使用的名称无法解决!输入法服务,键盘等。这是个坏习惯,苏拉奇先生。谢谢你帮助我,但是如果名字不能解决,你怎么期望代码编译?

以下是正确编辑的版本。我只是偶然发现了一些提示,让我找到了正确的地方来学习到底要导入什么。

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 开发者的无知之处。我想手动学习它,因为我相信真正的程序员可以手动编译。

我认为分级是编译和打包 apk 的工具之一。Apk 看起来像是一个 jar 文件或者一个 zip 文件的 rar。然后有两种类型的签名。不允许在播放存储和私有密钥上使用的调试密钥。

好了,让我们给 Saragch 先生一个手。并感谢您看我的视频。喜欢,订阅。