web-dev-qa-db-ja.com

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

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

enter image description here

86
XX_brother

まず最初に、keyboard.xmlフォルダーに配置されるres/xmlファイルが必要になります(フォルダーが存在しない場合は作成します)。

<?xml version="1.0" encoding="utf-8"?> 
<Keyboard xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:keyWidth="15%p"
    Android:keyHeight="15%p" >

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

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

** backspaceドロアブルを作成し、非常に小さなサイズ(18x18ピクセルなど)でres/drawable-ldpiフォルダーに配置する必要があることに注意してください。

次に、使用するxmlファイル(TextViewがある場所)に次のコードを追加する必要があります。

<RelativeLayout
 ...
>

        .....


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

        ......


</RelativeLayout>

** Android.inputmethodservice.KeyboardViewを設定できるようにするには、alignParentBottom="true"を配置するxmlファイルがRelativeLayoutである必要があります(通常、キーボードはスクリーン)

次に、キーボードを接続するonCreateを処理するActivityTextView関数に次のコードを追加する必要があります

    // 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は、作成する必要があるプライベートクラス変数であることに注意してください。

次に、キーボードを開くために次の関数が必要です(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() {
    }
};

それが役立つことを願っています!!!

ほとんどのコードが見つかりました here

74
Pontios

システムキーボード

この回答は、ユーザーが自分の携帯電話にインストールした任意のアプリで使用できるカスタムシステムキーボードの作成方法を示しています。独自のアプリ内でのみ使用されるキーボードを作成する場合は、 他の回答 を参照してください。

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

enter image description here

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

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

キープレビューは、キーボードのキーを押すとポップアップ表示されるレイアウトです。それはあなたがどのキーを押しているのかを示すだけです(太い太い指がそれを覆っている場合)。これは複数選択のポップアップではありません。そのためには、 Candidatesビュー をチェックアウトする必要があります。

<?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を右クリックして、New> Directoryを選択します。)

次に、次の2つのxmlファイルを追加します。 (xmlフォルダーを右クリックして、New> 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は、各キーがparentの幅の20%を占めることを意味します。ただし、3行目のDeleteキーとEnterキーで発生したことがわかるように、個々のキーでオーバーライドできます。
  • keyHeight :ここではハードコーディングされていますが、@dimen/key_heightのようなものを使用して、さまざまな画面サイズに動的に設定できます。
  • Gap :水平方向と垂直方向のギャップは、キー間に残すスペースの量を示します。 0pxに設定しても、まだ小さなギャップがあります。
  • codes :これは、キーが押されたときに何が起こるか、何が入力されるかを決定するUnicodeまたはカスタムコード値です。より長いUnicode文字列を入力する場合は、 keyOutputText を参照してください。
  • keyLabel :これは、キーに表示されるテキストです。
  • keyEdgeFlags :これは、キーをどのEdgeに合わせるかを示します。
  • 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ストアのカスタムキーボードはどうですか?上記のaboveいキーボードのようには見えません。

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

  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に設定することを忘れないでください。
53
Suragch

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 を参照してください。

31
bigstones

アプリ内キーボード

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

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

enter image description here

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

プロジェクトにInAppKeyboardという名前を付けました。好きなように電話してください。

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

キーボードレイアウト

res/layoutフォルダーにレイアウトファイルを追加します。私はkeyboardと呼びました。キーボードはカスタム 複合ビュー になり、このxmlレイアウトファイルからインフレートします。好きなレイアウトを使用してキーを配置できますが、私はLinearLayoutを使用しています。 merge タグに注意してください。

res/layout/keyboard.xml

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

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

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

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

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

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

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

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

        </LinearLayout>

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

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

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

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

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

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

        </LinearLayout>

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

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

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

        </LinearLayout>
    </LinearLayout>

</merge>

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

デモンストレーションのために、アクティビティには単一のEditTextがあり、キーボードは一番下にあります。カスタムキーボードビューMyKeyboardを呼び出しました。 (このコードはすぐに追加するので、今はエラーを無視します。)キーボードコードをすべて単一のビューに入れることの利点は、別のアクティビティやアプリで簡単に再利用できることです。

res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    tools:context="com.example.inappkeyboard.MainActivity">

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

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

</RelativeLayout>

3.キーボードJavaファイルを追加します

新しいJavaファイルを追加します。私はMyKeyboardと呼びました。

ここで注意すべき最も重要なことは、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をキーボードに渡すためのコードを記述する必要があります。 (これを行うには、OnFocusChangeListenerOnClickListenerをEditTextsに追加します。その説明については この記事 を参照してください。)適切なタイミングでキーボードを非表示または表示することもできます。

完成した

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

ノート

  • Xmlレイアウトファイルでは、キーの外観を良くしたい場合は、TextViewではなくButtonを使用することもできます。次に、背景をドローアブルにして、押すと外観状態を変更します。
  • 高度なカスタムキーボード:キーボードの外観とキーボードの切り替えの柔軟性を高めるために、Viewをサブクラス化するカスタムキービューと、ViewGroupをサブクラス化するカスタムキーボードビューを作成しています。キーボードはすべてのキーをプログラムで配置します。キーはインターフェースを使用してキーボードと通信します(フラグメントがアクティビティと通信する方法に似ています)。単一のキーボードレイアウトのみが必要な場合は、xmlレイアウトが適切に機能するため、これは必要ありません。しかし、私が取り組んでいる例を見たい場合は、すべてのKey*およびKeyboard*クラスをチェックしてください here 。また、ここではキーボードビューを交換する機能を持つコンテナビューも使用していることに注意してください。
26
Suragch

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

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

レイアウトが異なる同じ行にある必要があります。

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

これで解決します。期待したものが得られなかった場合は、ここにコードを投稿してください。私たちはあなたを助けるためにここにいます!

14
nithinreddy

私が見つけた最もよく文書化された例の1つ。

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

KeyboardView関連のXMLファイルとソースコードが提供されます。

7
Youngjae

同じ問題があった。最初はテーブルレイアウトを使用しましたが、ボタンを押した後もレイアウトは変化し続けました。ただし、このページは非常に便利です。 http://mobile.tutsplus.com/tutorials/Android/android-user-interface-design-creating-a-numeric-keypad-with-gridlayout/

1
jeydee

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

アーキテクチャは非常に柔軟です。 1つのメインビュー(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

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

ここでも、プロジェクトへのリンクは次のとおりです。 カスタムアプリ内キーボード

1
Don Brody

スラグチはこれまでのところ最良の答えを出しましたが、彼はアプリをコンパイルするために重要な特定のマイナーなものをスキップしました。

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

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

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

resレイアウト->アプリが電話でどのように見えるかを示すxmlファイル。 htmlがブラウザでWebページをどのように表示するかと同様です。それに応じてアプリを画面に合わせることができます。

値-> colors.xml、strings.xml、styles.xmlなどの定数データ。これらのファイルは適切にスペルが必要です。

drawable-> pics {jpeg、png、...};それらに何でも名前を付けてください。

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

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

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

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

現在、4つのタイプのAndroidプログラム、アクティビティ、サービス、コンテンツプロバイダー、およびブロードキャストレシーバーがあります。キーボードは、バックグラウンドで実行できるサービスになります。起動するアプリのリストには表示されません。ただし、アンインストールできます。

アプリをコンパイルするには、gradleとapk署名が必要です。その1つを調査するか、Android用APK Builderを使用できます。とても簡単です。

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

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

    • NumPad
      • 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 St​​udioなどの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 St​​udioへのアクセス権があると想定しました。自動的に作成されます。 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ストアで許可されていないデバッグキーと秘密キー。

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

0