Izradite Prilagođenu Tipkovnicu na Androidu
() translation by (you can also view the original English article)



Većina Android uređaja nema fizičku tipkovnicu. Umjesto toga, oslanjaju se na virtualnu ili softversku tipkovnicu za prihvaćanje korisničkog unosa. Ako Vas zanima personalizacija Androida, želite znati kako izraditi prilagođenu tipkovnicu, softverska tipkovnica može vaš hobi odvesti na novu razinu.
Koristeći Android SDK možete brzo napraviti softversku tipkovnicu s iznenađujuće malim brojem koda, jer SDK brine o nizu zadataka na nižoj razini, kao što je prepoznavanje dodira tipki, crtanje tipkovnice i uspostavljanje veza između tipkovnice i polja za unos.
U ovom tutorialu ćete saznati kako izraditi potpuno funkcionalnu softversku tipkovnicu koja može poslužiti kao zadana tipkovnica vašeg Android uređaja.
1. Prerekviziti
Morati ćete instalirati Eclipse ADT Bundle. Možete ga preuzeti na Android Deveoper web stranci.
2. Izradite Novi Projekt
Pokrenite Eclipse i izradite novu Android aplikaciju. Nazovite ovu aplikaciju SimpleKeyboard. Svakako odaberite jedinstveno ime paketa. Podesite minimalni SDK na Android 2.2 i podesite ciljani SDK na Android 4.4.



Ova aplikacija neće imati nikakvih aktivnosti, stoga uklonite oznaku Create Activity i kliknite Finish.



3. Uredite Manifest
Softverska tipkovnica smatra se kao Input Method Editor (IME) u operacijskom sustavu Android. IME je deklariran kao Service
u AndroidManifest.xml koja koristi BIND_INPUT_METHOD
dopuštenje i odgovara na radnju android.view.InputMethod
.
Dodajte sljedeće linije na application
tag manifesta:
1 |
<service android:name=".SimpleIME" |
2 |
android:label="@string/simple_ime" |
3 |
android:permission="android.permission.BIND_INPUT_METHOD" |
4 |
>
|
5 |
<meta-data android:name="android.view.im" android:resource="@xml/method"/> |
6 |
<intent-filter>
|
7 |
<action android:name="android.view.InputMethod" /> |
8 |
</intent-filter>
|
9 |
</service>
|
4. Izradite method.xml
service
tag u datoteci manifesta sadrži meta-data
tag koji se odnosi na XML datoteku nazvanu method.xml. Bez te datoteke, Android operativni sustav neće prepoznati naš Service
kao valjanu IME uslugu. Datoteka sadrži pojedinosti o načinu unosa i podtipovima. Za našu tipkovnicu, definiramo jedan podtip za en_US lokalno okruženje. Izradite direktorij res/xml ako ne postoji, i dodajte mu method.xml datoteku. Sadržaj datoteke trebao bi biti:
1 |
<?xml version="1.0" encoding="utf-8"?>
|
2 |
<input-method xmlns:android="https://schemas.android.com/apk/res/android"> |
3 |
<subtype
|
4 |
android:label="@string/subtype_en_US" |
5 |
android:imeSubtypeLocale="en_US" |
6 |
android:imeSubtypeMode="keyboard" /> |
7 |
</input-method>
|
5. Uredite strings.xml
Nizovi koje koristi ova aplikacija definirani su u res/values/strings.xml datoteci. Trebati će nam tri niza: Trebati ćemo tri niza:
- Naziv aplikacije
- oznake IME
- oznake podvrste IME-a
Ažurirajte strings.xml tako da ima sljedeće sadržaje:
1 |
<resources>
|
2 |
<string name="app_name">SimpleKeyboard</string> |
3 |
<string name="simple_ime">Simple IME</string> |
4 |
<string name="subtype_en_US">English (US)</string> |
5 |
</resources>
|
6. Odredite Izgled Tipkovnice
Izgled naše tipkovnice sadrži samo KeyboardView
. Atribut layout_alignParentBottom
je postavljen na true
, tako da se tipkovnica pojavi na dnu zaslona.
Izradite datoteku pod nazivom res/layout/keyboard.xml i zamijenite njezin sadržaj sljedećim:
1 |
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
<android.inputmethodservice.KeyboardView
|
3 |
xmlns:android="http://schemas.android.com/apk/res/android" |
4 |
android:id="@+id/keyboard" |
5 |
android:layout_width="match_parent" |
6 |
android:layout_height="wrap_content" |
7 |
android:layout_alignParentBottom="true" |
8 |
android:keyPreviewLayout ="@layout/preview" |
9 |
/>
|
KeyPreviewLayout
je izgled kratkoročnog skočnog prozora koji se pojavljuje kad god pritisnete tipku na tipkovnici. Sadrži jedan TextView
. Izradite datoteku pod nazivom res/layout/preview.xml i dodajte joj sljedeće:
1 |
<?xml version="1.0" encoding="utf-8"?>
|
2 |
<TextView xmlns:android="http://schemas.android.com/apk/res/android" |
3 |
android:layout_width="match_parent" |
4 |
android:layout_height="match_parent" |
5 |
android:gravity="center" |
6 |
android:background="#ffff00" |
7 |
android:textStyle="bold" |
8 |
android:textSize="30sp" |
9 |
>
|
10 |
</TextView>
|
6. Odredite Tipke Tipkovnice
Pojedinosti tipki za tipkovnicu i njihove pozicije su određene u XML datoteci. Svaka tipka ima sljedeće atribute:
-
keyLabel
: ovaj atribut sadrži tekst koji je prikazan na tipci. -
codes
: ovaj atribut sadrži unicode vrijednosti znakova koje tipka predstavlja.
Na primjer, kako biste definirali tipku za slovo A, codes
atribut bi trebao imati vrijednost 97, a keyLabe
l atribut bi trebao biti postavljen na A.
Ako je više od jednog koda povezano s više tipki, onda će znak koji tipka predstavlja ovisiti o broju "udaraca" koje tipka prima. Na primjer, ako tipka ima kodove 63, 33 i 58:
- jedan klik na tipku rezultira znakom ?
- dva dodira gumba u brzom slijedu rezultiraju znakom !
- tri dodira gumba u brzom slijedu rezultiraju znakom :
Tipka može imati nekoliko dodatnih atributa:
-
keyEdgeFlags
: Ovaj atribut može uzeti vrijednostleft
iliright
. Ovaj se atribut obično dodaje lijevim i desnim tipkama u nizu. Ovaj se atribut obično dodaje lijevim i desnim tipkama u nizu. -
keyWidth
: Ovaj atribut definira širinu tipke. Obično se definira kao postotna vrijednost. -
isRepeatable
: Ako je ovaj atribut postavljen natrue
, dugotrajnim pritiskom na tipku ponoviti ćete akciju tipke više puta. Obično se postavlja natrue
za brisanje i tipke za razmak.
Tipke tipkovnice grupirane su u retke. Dobra je praksa ograničiti broj tipki u retku na najviše deset, pri čemu svaka tipka ima širinu od 10% tipkovnice. U ovom tutorialu, visina tipki je postavljena na 60dp. Ta se vrijednost može podesiti, ali vrijednosti manje od 48dp se ne preporučuju. Naša tipkovnica imati će pet redova tipki.
Sada možemo nastaviti dalje i dizajnirati tipkovnicu. Izradite novu datoteku pod nazivom res/xml/qwerty.xml i zamijenite njezin sadržaj sljedećim:
1 |
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android" |
2 |
android:keyWidth="10%p" |
3 |
android:horizontalGap="0px" |
4 |
android:verticalGap="0px" |
5 |
android:keyHeight="60dp" |
6 |
>
|
7 |
<Row>
|
8 |
<Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left"/> |
9 |
<Key android:codes="50" android:keyLabel="2"/> |
10 |
<Key android:codes="51" android:keyLabel="3"/> |
11 |
<Key android:codes="52" android:keyLabel="4"/> |
12 |
<Key android:codes="53" android:keyLabel="5"/> |
13 |
<Key android:codes="54" android:keyLabel="6"/> |
14 |
<Key android:codes="55" android:keyLabel="7"/> |
15 |
<Key android:codes="56" android:keyLabel="8"/> |
16 |
<Key android:codes="57" android:keyLabel="9"/> |
17 |
<Key android:codes="48" android:keyLabel="0" android:keyEdgeFlags="right"/> |
18 |
</Row>
|
19 |
<Row>
|
20 |
<Key android:codes="113" android:keyLabel="q" android:keyEdgeFlags="left"/> |
21 |
<Key android:codes="119" android:keyLabel="w"/> |
22 |
<Key android:codes="101" android:keyLabel="e"/> |
23 |
<Key android:codes="114" android:keyLabel="r"/> |
24 |
<Key android:codes="116" android:keyLabel="t"/> |
25 |
<Key android:codes="121" android:keyLabel="y"/> |
26 |
<Key android:codes="117" android:keyLabel="u"/> |
27 |
<Key android:codes="105" android:keyLabel="i"/> |
28 |
<Key android:codes="111" android:keyLabel="o"/> |
29 |
<Key android:codes="112" android:keyLabel="p" android:keyEdgeFlags="right"/> |
30 |
</Row>
|
31 |
<Row>
|
32 |
<Key android:codes="97" android:keyLabel="a" android:keyEdgeFlags="left"/> |
33 |
<Key android:codes="115" android:keyLabel="s"/> |
34 |
<Key android:codes="100" android:keyLabel="d"/> |
35 |
<Key android:codes="102" android:keyLabel="f"/> |
36 |
<Key android:codes="103" android:keyLabel="g"/> |
37 |
<Key android:codes="104" android:keyLabel="h"/> |
38 |
<Key android:codes="106" android:keyLabel="j"/> |
39 |
<Key android:codes="107" android:keyLabel="k"/> |
40 |
<Key android:codes="108" android:keyLabel="l"/> |
41 |
<Key android:codes="35,64" android:keyLabel="\# \@" android:keyEdgeFlags="right"/> |
42 |
</Row>
|
43 |
<Row>
|
44 |
<Key android:codes="-1" android:keyLabel="CAPS" android:keyEdgeFlags="left"/> |
45 |
<Key android:codes="122" android:keyLabel="z"/> |
46 |
<Key android:codes="120" android:keyLabel="x"/> |
47 |
<Key android:codes="99" android:keyLabel="c"/> |
48 |
<Key android:codes="118" android:keyLabel="v"/> |
49 |
<Key android:codes="98" android:keyLabel="b"/> |
50 |
<Key android:codes="110" android:keyLabel="n"/> |
51 |
<Key android:codes="109" android:keyLabel="m"/> |
52 |
<Key android:codes="46" android:keyLabel="."/> |
53 |
<Key android:codes="63,33,58" android:keyLabel="\? ! :" android:keyEdgeFlags="right"/> |
54 |
</Row>
|
55 |
<Row android:rowEdgeFlags="bottom"> |
56 |
<Key android:codes="44" android:keyLabel="," android:keyWidth="10%p" android:keyEdgeFlags="left"/> |
57 |
<Key android:codes="47" android:keyLabel="/" android:keyWidth="10%p" /> |
58 |
<Key android:codes="32" android:keyLabel="SPACE" android:keyWidth="40%p" android:isRepeatable="true"/> |
59 |
<Key android:codes="-5" android:keyLabel="DEL" android:keyWidth="20%p" android:isRepeatable="true"/> |
60 |
<Key android:codes="-4" android:keyLabel="DONE" android:keyWidth="20%p" android:keyEdgeFlags="right"/> |
61 |
</Row>
|
62 |
</Keyboard>
|
Možda ste primijetili da neke tipke imaju negativne vrijednosti za codes
atribut. Negativne vrijednosti su jednake predodređenim konstantama u Keyboar
d klasi. Na primjer, vrijednost -5
je jednaka vrijednosti od Keyboard.KEYCODE_DELETE
.
7. Izradite Service
Klasu
Izradite novu Java klasu i nazovite je SimpleIME.java. Klasa bi trebala produžiti InputMethodService
klasu i implementirati OnKeyboardActionListener
sučelje. OnKeyboardActionListener
sučelje sadrži metode koje su pozvane kada se pritisnu ili dodirnu tipke na softverskoj tipkovnici.
SimpleIME
klasa trebala bi imati tri varijable člana:
-
KeyboardView
koji se odnosi na prikaz definiran u izgledu -
Keyboard
instancu koja je dodijeljenaKeyboardView
-
boolean
koji nam govori da li je uključena tipka za velika slova
Nakon deklariranja tih varijabli i dodavanja metodi OnKeyboardActionListener
sučelja, SimpleIME
klasa bi treba izgledati ovako:
1 |
public class SimpleIME extends InputMethodService |
2 |
implements OnKeyboardActionListener{ |
3 |
|
4 |
private KeyboardView kv; |
5 |
private Keyboard keyboard; |
6 |
|
7 |
private boolean caps = false; |
8 |
|
9 |
@Override
|
10 |
public void onKey(int primaryCode, int[] keyCodes) { |
11 |
|
12 |
}
|
13 |
|
14 |
@Override
|
15 |
public void onPress(int primaryCode) { |
16 |
}
|
17 |
|
18 |
@Override
|
19 |
public void onRelease(int primaryCode) { |
20 |
}
|
21 |
|
22 |
@Override
|
23 |
public void onText(CharSequence text) { |
24 |
}
|
25 |
|
26 |
@Override
|
27 |
public void swipeDown() { |
28 |
}
|
29 |
|
30 |
@Override
|
31 |
public void swipeLeft() { |
32 |
}
|
33 |
|
34 |
@Override
|
35 |
public void swipeRight() { |
36 |
}
|
37 |
|
38 |
@Override
|
39 |
public void swipeUp() { |
40 |
}
|
41 |
}
|
Kada se kreira tipkovnica, poziva se metoda onCreateInputView
. Ovdje se mogu inicijalizirati svi članovi varijable Service
. Ažurirajte implementaciju onCreateInputView
metode kao što je prikazano u nastavku:
1 |
@Override
|
2 |
public View onCreateInputView() { |
3 |
kv = (KeyboardView)getLayoutInflater().inflate(R.layout.keyboard, null); |
4 |
keyboard = new Keyboard(this, R.xml.qwerty); |
5 |
kv.setKeyboard(keyboard); |
6 |
kv.setOnKeyboardActionListener(this); |
7 |
return kv; |
8 |
}
|
Zatim, kreiramo metodu koja proizvodi zvuk kada je tipka pritisnuta. Mi koristimo AudioManger
klasu da reproduciramo zvukove. Android SDK uključuje nekoliko zadanih zvučnih efekata za pritiske tipki i oni se koriste u playClick
metodi.
1 |
private void playClick(int keyCode){ |
2 |
AudioManager am = (AudioManager)getSystemService(AUDIO_SERVICE); |
3 |
switch(keyCode){ |
4 |
case 32: |
5 |
am.playSoundEffect(AudioManager.FX_KEYPRESS_SPACEBAR); |
6 |
break; |
7 |
case Keyboard.KEYCODE_DONE: |
8 |
case 10: |
9 |
am.playSoundEffect(AudioManager.FX_KEYPRESS_RETURN); |
10 |
break; |
11 |
case Keyboard.KEYCODE_DELETE: |
12 |
am.playSoundEffect(AudioManager.FX_KEYPRESS_DELETE); |
13 |
break; |
14 |
default: am.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD); |
15 |
}
|
16 |
}
|
Konačno, ažurirajte metodu onKey
tako da aplikacija tipkovnice može komunicirati s poljima za unos (obično EditText
pregledi) drugih aplikacija.
Metoda getCurrentInputConnection
koristi se za uspostavljanje veze s poljem za unos druge aplikacije. Kada imamo vezu, možemo koristiti sljedeće metode:
-
commitText
za dodavanje jednog ili više znakova u polje za unos -
deleteSurroundingText
da biste izbrisali jedan ili više znakova polja za unos -
sendKeyEvent
da biste poslali događaje, kao što jeKEYCODE_ENTER
, vanjskoj aplikaciji
Kad god korisnik pritisne tipku na softverskoj tipkovnici, onKey
metoda se zove s unicode vrijednošću tipke kao jedan od njegovih parametara. Na temelju ove vrijednosti, tipkovnica izvršava jednu od sljedećih radnji:
- Ako je kod
KEYCODE_DELETE
, jedan znak lijevo od kursora se briše pomoću obrascadeleteSurroundingText
. - Ako je kod
KEYCODE_DONE
, aktiviran jeKEYCODE_ENTER
. - Ako je kod
KEYCODE_SHIFT
, vrijednostcaps
varijable je promijenjena i stanje mirovanja tipkovnice se ažurira pomoćusetShifted
metode. Trebate redizajnirati tipkovnicu kad se stanje mijenja tako da se ažuriraju oznake tipki. MetodainvalidateAllKeys
koristi se za preusmjeravanje svih tipki. - Kod svih ostalih kodova, kod se jednostavno pretvara u znak i šalje ga na polje za unos. Ako kôd predstavlja slovo abecede i
caps
varijabla je postavljena natrue
, znak se pretvara u velika slova.
Ažurirajte onKey
metodu tako da izgleda ovako:
1 |
@Override
|
2 |
public void onKey(int primaryCode, int[] keyCodes) { |
3 |
InputConnection ic = getCurrentInputConnection(); |
4 |
playClick(primaryCode); |
5 |
switch(primaryCode){ |
6 |
case Keyboard.KEYCODE_DELETE : |
7 |
ic.deleteSurroundingText(1, 0); |
8 |
break; |
9 |
case Keyboard.KEYCODE_SHIFT: |
10 |
caps = !caps; |
11 |
keyboard.setShifted(caps); |
12 |
kv.invalidateAllKeys(); |
13 |
break; |
14 |
case Keyboard.KEYCODE_DONE: |
15 |
ic.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)); |
16 |
break; |
17 |
default: |
18 |
char code = (char)primaryCode; |
19 |
if(Character.isLetter(code) && caps){ |
20 |
code = Character.toUpperCase(code); |
21 |
}
|
22 |
ic.commitText(String.valueOf(code),1); |
23 |
}
|
24 |
}
|
8. Testiranje Tipkovnice
Softverska tipkovnica je sada spremna za testiranje. Kompajlirajte i pokrenite tipkovnicu na Android uređaju. Ova aplikacija nema Activity
, što znači da se neće prikazati u pokretaču. Kako biste je koristili, prvo je trebate aktivirati u Postavkama uređaja (Settings).



Nakon što aktivirate Simple IME, otvorite bilo koju aplikaciju koja omogućuje unos teksta (na primjer, bilo koja aplikacija za slanje poruka) i kliknite na jedno od njezinih polja za unos. Trebali biste vidjeti da se pojavila ikona tipkovnice u području za obavijesti. Ovisno o vašem uređaju, možete kliknuti na tu ikonu ili povući traku obavijesti dolje i odabrati Simple IME kao metodu unosa. Sada bite trebali moći tipkati koristeći svoju novu tipkovnicu.



Zaključak
U ovom tutorialu ste naučili kako u potpunosti izraditi aplikaciju za prilagođenu tipkovnicu. Za promjenu izgleda tipkovnice, morate samo dodati malo stila res/layout/keyboard.xml i res/layout/preview.xml datotekama. Za promjenu pozicije tipki, ažurirajte res/xml/qwerty.xml datoteku. Za dodavanje značajki vašoj tipkovnici, pogledajte dokumentaciju za razvojne programere.