android

Tạo bàn phím mang phong cách của riêng bạn trong Android

Hôm bữa thấy người yêu mình xài điện thoại có cái bàn phím mà style nó hơi bị đẹp ;) Mình cũng thấy hay hay , thế là lân la gạ hỏi hóa ra cô ấy xài Swift Key , thế là cũng cài vào , thế rồi thắc mắc là tại sao họ có thể làm được cái bàn phím đẹp như thế ?

Thế là sau vài chục phút mày mò , mình cũng làm ra được 1 cái bàn phím của riêng mình , tuy không cute phô mai que như Swift nhưng kệ , trước mắt cứ như thế đã :D Rồi từ từ cải tiến sau , cái gì mà chả có phiên bản 1.0 ?

Okay ! Bắt đầu nào , trước tiên là Demo , tính mình là làm cái gì thì làm trước tiên là phải show kết quả đã rồi nói chuyện sau ?

Vào Settings -> Virtual Keyboard -> Enable cái custom keyboard của mình

Sau đó chỉ việc change bàn phím

Kết quả nè :?

Hehehe , bắt đầu thôi , đầu tiên các bạn hãy tạo 1 dự án mới , nhớ là không cần tạo Launcher activity nhé , vì trong ví dụ này chúng ta chạy Service , ko chạy launcher activity (Service là gì thì cứ document của Android mà đọc cho nó chính phái)

Sau khi có dự án rồi , trong thư mục layout tạo ra 2 file XML lần lượt là

  • key_preview.xml (file này sẽ là giao diện để cho các bạn preview character khi select phím)
<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:gravity="center"
    android:background="#5d5d5d"
    android:textColor="@android:color/white"
    android:textStyle="italic"
    android:textSize="30sp"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

</TextView>
  • keyboard.xml (file này là file UI layout của bàn phím)
<?xml version="1.0" encoding="utf-8"?>
<android.inputmethodservice.KeyboardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/keyboard"
    android:layout_alignParentBottom="true"

    android:keyTextColor="@android:color/white"
    android:keyBackground="@drawable/key_background"
    android:keyPreviewLayout="@layout/key_preview"
    android:background="@color/colorPrimaryDark"

    android:layout_width="match_parent"
    android:layout_height="wrap_content">

</android.inputmethodservice.KeyboardView>

Tiếp theo , click chuột phải vào thư mục res->Add resources directory -> xml

![](https://viblo.asia/uploads/5e927348-7b8e-466d-9819-7550d714c51f.png)

Trong thư mục mới tạo này (xml) , các bạn tạo tiếp 2 file

  • method.xml (Đây là file cấu hình kiểu , ngôn ngữ của bàn phím)
<?xml version="1.0" encoding="utf-8"?>
<input-method xmlns:android="http://schemas.android.com/apk/res/android">
    <subtype
        android:label="English (US)"
        android:imeSubtypeLocale="en_US"
        android:imeSubtypeMode="keyboard"
        />

</input-method>
  • qwerty.xml (Đây là file cấu hình các phím)
<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="10%p"
    android:horizontalGap="0px"
    android:verticalGap="0px"
    android:keyHeight="60dp">

    <Row>
        <Key android:keyLabel="1"
            android:keyEdgeFlags="left"
            android:codes="49"/>
        <Key android:keyLabel="2"
            android:codes="50"/>
        <Key android:keyLabel="3"
            android:codes="51"/>
        <Key android:keyLabel="4"
            android:codes="52"/>
        <Key android:keyLabel="5"
            android:codes="53"/>
        <Key android:keyLabel="6"
            android:codes="54"/>
        <Key android:keyLabel="7"
            android:codes="55"/>
        <Key android:keyLabel="8"
            android:codes="56"/>
        <Key android:keyLabel="9"
            android:codes="57"/>
        <Key android:keyLabel="0"
            android:keyEdgeFlags="right"
            android:codes="48"/>
    </Row>

    <Row>
        <Key android:keyLabel="q" android:keyEdgeFlags="left" android:codes="113"/>
        <Key android:keyLabel="w" android:codes="119"/>
        <Key android:keyLabel="e" android:codes="101"/>
        <Key android:keyLabel="r" android:codes="114"/>
        <Key android:keyLabel="t" android:codes="116"/>
        <Key android:keyLabel="y" android:codes="121"/>
        <Key android:keyLabel="u" android:codes="117"/>
        <Key android:keyLabel="i" android:codes="105"/>
        <Key android:keyLabel="o" android:codes="111"/>
        <Key android:keyLabel="p" android:keyEdgeFlags="right" android:codes="112"/>
    </Row>

    <Row>
        <Key android:keyLabel="a" android:keyEdgeFlags="left" android:codes="97"/>
        <Key android:keyLabel="s" android:codes="115"/>
        <Key android:keyLabel="d" android:codes="100"/>
        <Key android:keyLabel="f" android:codes="102"/>
        <Key android:keyLabel="g" android:codes="103"/>
        <Key android:keyLabel="h" android:codes="104"/>
        <Key android:keyLabel="j" android:codes="106"/>
        <Key android:keyLabel="k" android:codes="107"/>
        <Key android:keyLabel="l" android:codes="108"/>
        <Key android:keyLabel="\# \@" android:keyEdgeFlags="right" android:codes="35,64"/>
    </Row>

    <Row>
        <Key android:keyLabel="CAPS" android:keyEdgeFlags="left" android:codes="-1"/>
        <Key android:keyLabel="z" android:codes="122"/>
        <Key android:keyLabel="x" android:codes="120"/>
        <Key android:keyLabel="c" android:codes="99"/>
        <Key android:keyLabel="v" android:codes="118"/>
        <Key android:keyLabel="b" android:codes="98"/>
        <Key android:keyLabel="n" android:codes="110"/>
        <Key android:keyLabel="m" android:codes="109"/>
        <Key android:keyLabel="." android:codes="46"/>
        <Key android:keyLabel="\? ! :" android:keyEdgeFlags="right" android:codes="63,33,58"/>
    </Row>

    <Row android:rowEdgeFlags="bottom">
        <Key android:keyLabel="," android:keyWidth="10%p" android:keyEdgeFlags="left" android:codes="44"/>
        <Key android:keyLabel="/" android:keyWidth="10%p"  android:codes="47"/>
        <Key android:keyLabel="SPACE" android:keyWidth="40%p" android:isRepeatable="true" android:codes="32"/>
        <Key android:keyLabel="DEL" android:keyWidth="20%p" android:isRepeatable="true" android:codes="-5"/>
        <Key android:keyLabel="DONE" android:keyWidth="20%p" android:keyEdgeFlags="right" android:codes="-4"/>

    </Row>

</Keyboard>

Trong này thì các bạn chỉ cần chú ý các tham số sau
android:keyEdgeFlags="left" => Đây là vị trí của phím
android:keyLabel="b" => Label hiển thị trên màn hình
android:codes="98" => Mã code của ký tự (ASCII code)


Okay , bây giờ , chúng ta cần tạo 1 Service để xử lý đống trên , click phải vào package name và chọn NEw -> Servc

Code của Service

public class EDMTKeyboard extends InputMethodService implements KeyboardView.OnKeyboardActionListener {

    private KeyboardView kv;
    private Keyboard keyboard;

    private  boolean isCaps = false;


    //Press Ctrl+O


    @Override
    public View onCreateInputView() {
        kv = (KeyboardView)getLayoutInflater().inflate(R.layout.keyboard,null);
        keyboard = new Keyboard(this,R.xml.qwerty);
        kv.setKeyboard(keyboard);
        kv.setOnKeyboardActionListener(this);
        return kv;
    }

    @Override
    public void onPress(int i) {

    }

    @Override
    public void onRelease(int i) {

    }

    @Override
    public void onKey(int i, int[] ints) {

        InputConnection ic = getCurrentInputConnection();
        playClick(i);
        switch (i)
        {
            case Keyboard.KEYCODE_DELETE:
                ic.deleteSurroundingText(1,0);
            break;
            case Keyboard.KEYCODE_SHIFT:
                isCaps = !isCaps;
                keyboard.setShifted(isCaps);
                kv.invalidateAllKeys();
                break;
            case Keyboard.KEYCODE_DONE:
                ic.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_ENTER));
                break;
                default:
                    char code = (char)i;
                    if(Character.isLetter(code) && isCaps)
                        code = Character.toUpperCase(code);
                    ic.commitText(String.valueOf(code),1);
        }

    }

    private void playClick(int i) {

        AudioManager am = (AudioManager)getSystemService(AUDIO_SERVICE);
        switch(i)
        {
            case 32:
                am.playSoundEffect(AudioManager.FX_KEYPRESS_SPACEBAR);
                break;
            case Keyboard.KEYCODE_DONE:
            case 10:
                am.playSoundEffect(AudioManager.FX_KEYPRESS_RETURN);
                break;
            case Keyboard.KEYCODE_DELETE:
                am.playSoundEffect(AudioManager.FX_KEYPRESS_DELETE);
                break;
            default: am.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD);
        }
    }

    @Override
    public void onText(CharSequence charSequence) {

    }

    @Override
    public void swipeLeft() {

    }

    @Override
    public void swipeRight() {

    }

    @Override
    public void swipeDown() {

    }

    @Override
    public void swipeUp() {

    }
}

@Override
public View onCreateInputView() {
kv = (KeyboardView)getLayoutInflater().inflate(R.layout.keyboard,null);
keyboard = new Keyboard(this,R.xml.qwerty);
kv.setKeyboard(keyboard);
kv.setOnKeyboardActionListener(this);
return kv;
}
Trong hàm này , chúng ta đã xử lý việc khởi tạo 1 virtual keyboard từ giao diện riêng của chúng ta , sau đó set các sự kiện cho nó

@Override
public void onKey(int i, int[] ints) {

    InputConnection ic = getCurrentInputConnection();
    playClick(i);
    switch (i)
    {
        case Keyboard.KEYCODE_DELETE:
            ic.deleteSurroundingText(1,0);
        break;
        case Keyboard.KEYCODE_SHIFT:
            isCaps = !isCaps;
            keyboard.setShifted(isCaps);
            kv.invalidateAllKeys();
            break;
        case Keyboard.KEYCODE_DONE:
            ic.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_ENTER));
            break;
            default:
                char code = (char)i;
                if(Character.isLetter(code) && isCaps)
                    code = Character.toUpperCase(code);
                ic.commitText(String.valueOf(code),1);
    }

}

Trong hàm này , chúng ta sẽ xử lý những nút đặc biệt như : Click vào nút DELETE thì xóa ký tự hiện tại , click vào nút SHIFT thì cho phép viết hoa , click vào nút Enter thì xuống dòng , còn lại các nút kia thì in character của nó ra

private void playClick(int i) {
    AudioManager am = (AudioManager)getSystemService(AUDIO_SERVICE);
    switch(i)
    {
        case 32:
            am.playSoundEffect(AudioManager.FX_KEYPRESS_SPACEBAR);
            break;
        case Keyboard.KEYCODE_DONE:
        case 10:
            am.playSoundEffect(AudioManager.FX_KEYPRESS_RETURN);
            break;
        case Keyboard.KEYCODE_DELETE:
            am.playSoundEffect(AudioManager.FX_KEYPRESS_DELETE);
            break;
        default: am.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD);
    }
}

Hàm này sẽ play âm thanh khi chúng ta nhấn phím

Okay , và đừng quên khai báo Service trong Manifest nhé

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="edmt.dev.androidcustomkeyboard">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <service
            android:name=".EDMTKeyboard"
            android:label="EDMTKeyboard"
           android:permission="android.permission.BIND_INPUT_METHOD"
            >
            <meta-data android:name="android.view.im" android:resource="@xml/method"/>
            <intent-filter>
                <action android:name="android.view.InputMethod"/>
            </intent-filter>

        </service>
    </application>

</manifest>

Đây là file colors.xml của mình , màu đúng y như demo nhé (vì mình set màu bàn phím theo colorPrimary và colorPrimaryDark)

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

    <color name="keyboard_background_color">#34495e</color>
    <color name="keyboard_divider">#2c3e50</color>
    <color name="keyboard_pressed">#95a5a6</color>
</resources>

Và hãy thưởng thức nào ;)

Registration Login
Sign in with social account
or
Lost your Password?
Registration Login
Sign in with social account
or
A password will be send on your post
Registration Login
Registration