Androidでカスタムキーボードを作成するにはどうすればよいですか?


105

カスタムキーボードを作りたいです。XMLとJavaを使用してそれを行う方法がわかりません。下の写真は作りたいキーボードのモデルです。数字だけが必要です。

ここに画像の説明を入力してください


6
[Androidデバイス用のXMLレイアウトを使用して独自のカスタムキーボードを作成する](tutorials-android.blogspot.com/2011/06/…
Jorgesys

1
Tutsに

Googleはサンプル「SoftKeyboard」プロジェクトを持っている、またはリソースのかなり多くがここにリンクがあります。customkeyboarddetails.blogspot.com/2019/02/...を
oliversisson

回答:


83

まずkeyboard.xmlres/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>

**あなたが置かれることをxmlファイルことに注意してくださいandroid.inputmethodservice.KeyboardViewでは、しなければならRelativeLayout設定できるようにするために、alignParentBottom="true"ます(通常、キーボードは画面の下部に表示されます)。

次に、キーボードを接続するを処理するのonCreate関数に次のコードを追加する必要Activityがあり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は、作成する必要があるプライベートクラス変数であることに注意してください。

次に、キーボードを開くために次の関数が必要です(onClickxmlプロパティを介して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() {
    }
};

お役に立てば幸いです!!!

ここにあるコードのほとんど


1
キーボードを画面の下部に配置したくない場合はどうすればよいですか?(たとえば、ユーザーがそれをドラッグできるようにしたい)。それはキーボードアプリを介して制御できるものですか、それともAndroidシステムによって処理されますか?
user3294126 2016年

キーボードの幅が画面に表示されないすべての画面に表示されるようにするにはどうすればよいですか
George Thomas

KeyboardViewが含まれる親レイアウトは何ですか?また、KeyboardViewのlayout_widthを確認しましたか?
Pontios

1
KeyboardViewおよびKeyboardクラスは、APIレベル29以降、Googleで非推奨になっていることに注意してください。したがって、より新しいAPIレベルをターゲットにする必要がある場合、このソリューションは今後機能しなくなります。
maex

keyboardViewはgoogleによって非推奨になりました。新しいソリューションとは何ですか?
tohidmahmoudvand

78

システムキーボード

この回答は、ユーザーが自分の電話にインストールしたすべてのアプリで使用できるカスタムシステムキーボードの作成方法を示しています。あなた自身のアプリ内でのみ使用されるキーボードを作りたい場合は、私の別の答えを見てください

以下の例はこのようになります。キーボードレイアウトに合わせて変更できます。

ここに画像の説明を入力してください

次の手順は、動作するカスタムシステムキーボードを作成する方法を示しています。できる限り不要なコードを削除しようとしました。他に必要な機能がある場合は、最後に詳細なヘルプへのリンクを提供しました。

1.新しいAndroidプロジェクトを開始する

プロジェクトに「カスタムキーボード」という名前を付けました。好きなように呼んでください。ここで特別なことは何もありません。私は残すだろうMainActivityとの「Hello World!」そのままのレイアウト。

2.レイアウトファイルを追加する

次の2つのファイルをアプリのres/layoutフォルダーに追加します。

  • keyboard_view.xml
  • key_preview.xml

keyboard_view.xml

このビューは、キーボードを保持するコンテナーのようなものです。この例ではキーボードは1つだけですが、他のキーボードを追加して、このキーボードとの間で交換することができます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を選択します。)

次に、次の2つの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%を取る必要があることを意味したpアレントを。ただし、3行目のDeleteキーとEnterキーで発生したように、個別のキーで上書きできます。
  • keyHeight:これはハードコードされていますが@dimen/key_height、さまざまな画面サイズに動的に設定するようなものを使用できます。
  • Gap:水平方向と垂直方向のギャップは、キーの間に残すスペースの量を示します。に設定して0pxも、まだ小さなギャップがあります。
  • codes:これは、キーが押されたときに何が発生するか、または何が入力されるかを決定するUnicodeまたはカスタムコード値にすることができます。keyOutputTextより長いUnicode文字列を入力するかどうかを確認してください。
  • 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.マニフェストを更新する

これは、先に追加したファイルを参照しているため、最初ではなく最後に配置しました。カスタムキーボードをシステムキーボードとして登録するserviceには、AndroidManifest.xmlファイルにセクションを追加する必要があります。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で入力できる場所ならどこでもキーボードを使用できるようになります。

さらなる研究

上記のキーボードは使用可能ですが、他のユーザーが使用したいキーボードを作成するには、おそらくさらに機能を追加する必要があります。方法については、以下のリンクをご覧ください。

続く

どのように標準が好きではありません KeyboardView外観と動作がですか?私は確かにしません。Android 2.0以降、更新されていないようです。Playストアにあるこれらすべてのカスタムキーボードはどうですか?彼らは上の醜いキーボードのようには見えません。

良いニュースは、自分のキーボードの外観と動作を完全にカスタマイズできることです。次のことを行う必要があります。

  1. サブクラス化する独自のカスタムキーボードビューを作成しますViewGroup。それをButtonsで埋めたり、サブクラス化する独自のカスタムキービューを作成したりすることもできますView。ポップアップビューを使用する場合は、このことに注意してください
  2. キーボードにカスタムイベントリスナーインターフェイスを追加します。onKeyClicked(String text)またはのようなもののためにそのメソッドを呼び出しonBackspace()ます。
  3. あなたは追加する必要はありませんkeyboard_view.xmlkey_preview.xmlまたはnumber_pad.xmlこれらは、標準のすべてであるため、上記の指示に記述しましたKeyboardView。これらすべてのUIアスペクトをカスタムビューで処理します。
  4. あなたにはMyInputMethodService、クラス、あなたはキーボードクラスで定義されたカスタムキーボードリスナーを実装します。これは、KeyboardView.OnKeyboardActionListener不要になったの代わりになります。
  5. あなたにはMyInputMethodService、クラスのonCreateInputView()メソッド、カスタムキーボードのインスタンスを作成して返します。キーボードのカスタムリスナーをに設定することを忘れないでくださいthis

35

アプリ内キーボード

この回答は、アプリ内でのみ使用するカスタムキーボードを作成する方法を示しています。どのアプリでも使用できるシステムキーボードを作成する場合は、他の回答を参照してください

例は次のようになります。キーボードレイアウトに合わせて変更できます。

ここに画像の説明を入力してください

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>

アクティビティレイアウト

デモのために、私たちの活動は1つで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

ここで注意すべき最も重要なことは、EditTextまたはへのハードリンクがないことですActivity。これにより、必要なアプリやアクティビティに簡単にプラグインできます。このカスタムキーボードビューもを使用します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にOnFocusChangeListenerand OnClickListenerを追加します。その説明については、この記事を参照してください。)適切なタイミングでキーボードを非表示または表示することもできます。

完成した

それでおしまい。これでサンプルアプリを実行し、必要に応じてテキストを入力または削除できるようになります。次のステップは、自分のニーズに合わせてすべてを変更することです。たとえば、一部のキーボードでは、ボタンをカスタマイズする方が簡単なので、ボタンではなくTextViewを使用しました。

ノート

  • xmlレイアウトファイルでは、キーをより見やすくしたい場合は、TextView代わりにaを使用することもできますButton。次に、背景をドローアブルにして、押すと外観の状態が変わるようにします。
  • 高度なカスタムキーボード:キーボードの外観とキーボードの切り替えをより柔軟にするために、サブクラス化するカスタムキービューとサブクラスView化するカスタムキーボードを作成していますViewGroup。キーボードはすべてのキーをプログラムでレイアウトします。キーはインターフェースを使用してキーボードと通信します(フラグメントがアクティビティと通信する方法と同様)。キーボードレイアウトが1つだけ必要な場合は、xmlレイアウトが適切に機能するため、これは必要ありません。ただし、私が取り組んでいることの例を確認したい場合は、すべてのKey*およびKeyboard*クラスをここで確認してください。ここでは、キーボードの入れ替えを行う機能を持つコンテナビューも使用しています。

あなたの答えは素晴らしいですが、元のキーボードとこの新しいキーボードの切り替えをどのように設定できますか。
Kishan Donga

@KishanDonga、キーボードで、キーボードを切り替えるキーを追加できます。ユーザーが押すと、が呼び出されますInputMethodManager#showInputMethodPicker()。ただし、元のキーボードにそのようなキーがない場合、ユーザーがキーボードに切り替える唯一の方法は、システム設定で手動で行うことです。Appleはすべてのキーボードにキーボード切り替えキーが必要であるため、この領域ではAndroidよりも優れています。
Suragch

@KishanDonga、私はこの答えがシステムキーボードではなく、アプリ内キーボードに関するものであることを認識しました。2つのカスタムキーボードを入れ替えたい場合は、プログラムでそれらをコンテナビューに入れたり入れたりすることができます。両方のキーボードにキーボード交換キーを追加するだけです。上記の回答にある「高度なカスタムキーボード」のメモとリンクを参照してください。
Suragch 2018年

キーボードとシステムキーボードを入れ替えたい場合は、システムキーボードを非表示にし、適切なタイミングでキーボードを表示します(逆も同様です)。
Suragch、

1
@MarekTakac、システムキーボードを無効にし、すべてのアクティビティでカスタムキーボードを追加する必要があります。アクティビティに複数EditTextのがある場合は、onFocusChangedListenerそれらにを追加して、フォーカスを受け取ったときにInputConnectionからEditTextカスタムキーボードにを割り当てることができるようにする必要があります。
Suragch

31

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


2
私はKeyboardViewクラスを使用していますが、API 29以降は非推奨になりました。
アビジット

14

ソフトキーボードのサンプルプロジェクトを次に示します。

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

あなたのは異なるレイアウトで同じ行にあるはずです。

編集:アプリケーションでのみキーボードが必要な場合は、非常に簡単です!垂直方向の線形レイアウトを作成し、その中に水平方向の3つの線形レイアウトを作成します。次に、各行のボタンをこれらの水平線形レイアウトのそれぞれに配置し、ウェイトプロパティをボタンに割り当てます。それらすべてにandroid:layout_weight = 1を使用して、等間隔になるようにします。

これで解決します。期待どおりの結果が得られなかった場合は、ここにコードを投稿してください。


キーボードが常に表示され、標準のAndroidキーボードのように動作しないため、編集は実際には不適切です。
m0skit0 2018


4

自分のカスタムキーボードを作成するために使用する方法を決定しようとしたときに、この投稿に最近出くわしました。AndroidシステムAPIが非常に限られていることがわかったので、自分でアプリ内キーボードを作成することにしました。Suragchの答えを研究の基礎として使用して、独自のキーボードコンポーネントを設計しました。MITライセンスでGitHubに投稿されています。うまくいけば、これは他の誰かが多くの時間と頭痛を救うでしょう。

アーキテクチャはかなり柔軟です。メインビュー(CustomKeyboardView)が1つあり、必要なキーボードレイアウトとコントローラーを挿入できます。

アクティビティ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カスタムキーボードgif風景

ここに画像の説明を入力してください

これがあなたが採用することに決めたアーキテクチャではない場合でも、うまくいけば、機能するアプリ内キーボードのソースコードを確認すると役立つでしょう。

ここでも、プロジェクトへのリンクです:カスタムアプリ内キーボード


2

これまでのところ、Suragchは最良の回答をしましたが、アプリのコンパイルに重要な特定のマイナーなことはスキップしました。

私は彼の答えを改善することでスラグよりも良い答えを出したいと思っています。彼が入れなかったすべての欠けている要素を追加します。

AndroidアプリAPK Builder 1.1.0を使用してAPKをコンパイルしました。それでは始めましょう。

Androidアプリを構築するには、特定の形式で整理され、それに応じて大文字になっているいくつかのファイルとフォルダーが必要です。

resレイアウト->電話でのアプリの外観を示すxmlファイル。htmlがブラウザ上でWebページがどのように見えるかを形成する方法に似ています。アプリを画面に合わせて表示できるようにします。

値->定数データ(colors.xml、strings.xml、styles.xmlなど)。これらのファイルは適切にspeltする必要があります。

ドローアブル-> pics {jpeg、png、...}; それらに任意の名前を付けます。

ミップマップ->その他の写真。アプリのアイコンに使用されますか?

xml->その他のxmlファイル。

src->は、htmlのJavaScriptのように機能します。レイアウトファイルは開始ビューを開始し、Javaファイルはタグ要素を動的に制御してイベントをトリガーします。イベントは、htmlと同じように、layout.xmlで直接アクティブ化することもできます。

AndroidManifest.xml->このファイルは、アプリの内容を登録します。アプリケーション名、プログラムの種類、必要な権限など。これにより、Androidの安全性が高まります。プログラムは文字通り、マニフェストで要求しなかったことを実行できません。

現在、Androidプログラムには、アクティビティ、サービス、コンテンツプロバイダー、放送受信機の4種類があります。私たちのキーボードは、バックグラウンドで実行できるサービスになります。起動するアプリのリストには表示されません。アンインストールすることもできます。

アプリをコンパイルするには、gradleとapk署名が必要です。あなたはそれを研究するか、Android用APKビルダーを使用することができます。とても簡単です。

Androidの開発について理解したところで、ファイルとフォルダーを作成しましょう。

  1. 上記で説明したように、ファイルとフォルダを作成します。私のディレクトリは次のようになります:

    • NumPad
      • AndroidManifest.xml
      • src
        • サラッグ
          • num_pad
            • MyInputMethodService.java
      • 解像度
        • ドローアブル
          • Suragch_NumPad_icon.png
        • レイアウト
          • key_preview.xml
          • keyboard_view.xml
        • xml
          • method.xml
          • number_pad.xml
          • colors.xml
          • strings.xml
          • styles.xml

Android StudioなどのIDEを使用している場合は、プロジェクトファイルが含まれている可能性があることに注意してください。

  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: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は、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プログラムには4つのタイプがあります。アクティビティは、ランチャーアイコンが付いた通常のアプリです。このテンキーはアクティビティではありません!さらに、彼はどんな活動も実行しませんでした。

友達にアクティビティタグが含まれていません。プログラムがコンパイルされ、起動しようとするとクラッシュします。xmlns:androidとuses-sdkについては、私はあなたを助けることができません。機能する場合は、私の設定を試してください。

ご覧のとおり、サービスとして登録するサービスタグがあります。また、service.android:nameは、Javaファイル内のパブリッククラス拡張サービスの名前である必要があります。それに応じて大文字にする必要があります。また、packageは、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、キーボードなど。これは悪い習慣です。手伝ってくれてありがとうございますが、名前が解決できない場合、コードはどのようにコンパイルされると思いましたか?

以下は正しく編集されたバージョンです。何をインポートするかを正確に知るために、適切な場所に連れて行ってくれるヒントをたまたま偶然見つけました。

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をコンパイルしてパッケージ化するためのツールの1つだと思います。apkはjarファイルまたはzipファイルのrarのようです。次に、2種類の署名があります。Playストアと秘密鍵で許可されていないデバッグキー。

さてサラグ氏に手を貸そう。そして、私のビデオを見てくれてありがとう。いいね!


1

同じ問題がありました。最初はテーブルレイアウトを使っていましたが、ボタンを押してもレイアウトが変わりました。このページはとても役に立ちました。http://mobile.tutsplus.com/tutorials/android/android-user-interface-design-creating-a-numeric-keypad-with-gridlayout/


3
スパゲッティがどこにあるかわからない。例には、onCreateを実装する5行程度のコードしかありません。
Glenn
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.