现在的位置: 首页 > 综合 > 正文

在Android中创建一种新的输入法(Creating an Input Method))

2013年08月27日 ⁄ 综合 ⁄ 共 7326字 ⁄ 字号 评论关闭

译自[url]http://android-developers.blogspot.com/2009/04/creating-input-method.html[/url]
by Fly Fire  如需转载,请注明来源 [url]www.yddev.com[/url]

一.
1.创建一个新的输入法需要继承android.inputmethodservice.InputMethodService,这个类提供了一个输入法
的基本实现,例子可以参考sdk中的SoftKeyboard的代码。

2.输入法跟其他application或service一样会被打包成一个apk,在 AndroidManifest.xml,把它声明成一个
service.[code]<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.fastinput">

    <application android:label="@string/app_label">

        <!-- Declares the input method service -->
        <service android:name="FastInputIME"
            android:label="@string/fast_input_label"
            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>

        <!-- Optional activities. A good idea to have some user settings. -->
        <activity android:name="FastInputIMESettings" android:label="@string/fast_input_settings">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
            </intent-filter>
        </activity>
    </application>
</manifest>[/code]3.输入法的service生命周期如下
[img]https://docs.google.com/a/google.com/File?id=ad9xdxhtb4_043qn7phd_b[/img]

二.输入法界面元素

输入法有2个主要的界面元素,InputView与Candidates View。
InputView:是用户输入文字的地方,当输入法被显示的时候会调用InputMethodService.onCreateInputView()
,在这个函数里创建和返回你想在输入法窗口中显示的Input View.
Candidates View:是用来提供输入选择,在函数InputMethodService.onCreateCandidatesView()中创建,默认
为空。

三.设计不同的输入类型
  一个程序的文本框可能有不同的输入类型,比如字符,数字,url,email地址等,当你实现一种输入法的时候你
就需要知道不同输入方式的区别,输入法不会自动根据不同的输入类型来切换,所以你的输入法需要支持所有的
输入类型。至于输入数据的验证就交由应用程序去负责。

例如,Android中一个Latin输入法提供的字符与数字输入的界面:
[img]https://docs.google.com/a/google.com/File?id=ddvqp2ns_18g2nm5jhb_b[/img]

[img]https://docs.google.com/a/google.com/File?id=ddvqp2ns_17crk39fd9_b[/img]

调用InputMethodService.onStartInputView()的时候会传递一个 EditorInfo对象来判断输入类型。
例如使用(EditorInfo.inputType & EditorInfo.TYPE_CLASS_MASK)来判断是属于下面的哪种类型:
TYPE_CLASS_NUMBER
TYPE_CLASS_DATETIME
TYPE_CLASS_PHONE
TYPE_CLASS_TEXT

  密码输入:注意不要在你的界面中显示密码,除了提醒用户外也不要把密码保存起来。

四.把输入文本传送给应用程序
   1.可以发送一个key event来实现[code]InputConnection ic = getCurrentInputConnection();
long eventTime = SystemClock.uptimeMillis();
ic.sendKeyEvent(new KeyEvent(eventTime, eventTime,
    KeyEvent.ACTION_DOWN, keyEventCode, 0, 0, 0, 0,
    KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));
ic.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
    KeyEvent.ACTION_UP, keyEventCode, 0, 0, 0, 0,
   
KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));[/code]或者
[code]InputMethodService.sendDownUpKeyEvents(keyEventCode);[/code]建议对于一些
输入模式使用第一种方法,因为有些按键可能被过滤。

   2.通过编辑输入文本,主要使用以下方法。[code]getTextBeforeCursor()
getTextAfterCursor()
deleteSurroundingText()
commitText()[/code]比如,一个以Fell开头的文本,你想把它替换成Hello![code]InputConnection ic = getCurrentInputConnection();
ic.deleteSurroundingText(4, 0);
ic.commitText("Hello", 1);
ic.commitText("!", 1);[/code]五.联想输入
  如果你需要联想输入或者输入过程中动态预测输入的文本,你可以参考如下代码:[code]InputConnection ic = getCurrentInputConnection();
ic.setComposingText("Composi", 1);
...
ic.setComposingText("Composin", 1);
...
ic.commitText("Composing ", 1);[/code][img]https://docs.google.com/a/google.com/File?id=ddvqp2ns_0g2z84dg2_b[/img]

[img]https://docs.google.com/a/google.com/File?id=ddvqp2ns_1jnw696d3_b[/img]

[img]https://docs.google.com/a/google.com/File?id=ddvqp2ns_2crrwtbf7_b[/img]

六.拦截硬件按键消息
尽管输入法窗口没有foucs,但是它最先收到硬件的按键消息,如果需要处理这些硬件按键消息,你只需要
重写InputMethodService.onKeyDown() 与InputMethodService.onKeyUp(),如果你不想处理某个按键,记得调
用super.onKey* 。

七.其他注意点
   1.提供一个用户可以直接从当前输入法进行相关输入法设置的方式。
   2.提供一个用户可以切换不同输入法的方式。
   3.让输入法界面尽快的弹出,资源或者耗时长的操作可以稍后加载。
   4.当输入法窗口被隐藏的时候,大块的内存分配最好尽快释放
   5.确保输入法能包含最常用的字符。

八.例子:
可以参考LatinIME的例子:
[url=http://android.git.kernel.org/?p=platform/packages/inputmethods/LatinIME.git;a=tree]http://android.git.kernel.org/?p=platform/packages/inputmethods/LatinIME.git;a=tree[/url]
或者1.5 SDK也提供了一个SoftKeyboard的例子。

Terry
发表于 2009-4-25 03:21

这是1.5版核心的输入吗?挺不错的

fly_fire
发表于 2009-4-25 09:37

[quote]这是1.5版核心的输入吗?挺不错的
[size=2][color=#999999]Terry 发表于 2009-4-25 03:21[/color]
[url=http://yddev.com/bbs/redirect.php?goto=findpost&pid=96&ptid=63][img]http://yddev.com/bbs/images/common/back.gif[/img][/url][/size][/quote]

对,这是基于1.5的输入法框架创建新的输入法。。

yantao821015
发表于 2009-7-22 16:54

如何通过API去设置当前输入法呢?
我看了下setting的代码,他是用
Settings.Secure.putString(getContentResolver(),
            Settings.Secure.ENABLED_INPUT_METHODS, builder.toString());
但是,在SDK文档中明确指出,该设置只能读,不能写。郁闷了。。。
高人给指点一下

http://www.yddev.com/bbs/viewthread.php?tid=63

 

 

 

 

softkeyboard

总结:

SoftKeyboard.java

主要变量:

StringBuilder mComposing 用于存放向链接应用提交的字符串

主要接口函数:

public void onKey(int primaryCode, int[] keyCodes) {
        if (isWordSeparator(primaryCode)) { //判断是否为指定符号(空格,分号,冒号等)。指定符号在string.xml中
            // Handle separator
            if (mComposing.length() > 0) { //输入该符号之前是否有输入
                commitTyped(getCurrentInputConnection());//将之前打的文本提交给连接的应用,并清除输入状态
            }
            sendKey(primaryCode);//执行该按键的自身操作(输入空格、冒号等)
            updateShiftKeyState(getCurrentInputEditorInfo());
        } else if (primaryCode == Keyboard.KEYCODE_DELETE) {
            handleBackspace();
        } else if (primaryCode == Keyboard.KEYCODE_SHIFT) {
            handleShift();
        } else if (primaryCode == Keyboard.KEYCODE_CANCEL) {
            handleClose();//关闭软键盘
            return;
        } else if (primaryCode == LatinKeyboardView.KEYCODE_OPTIONS) {
            // Show a menu or somethin'
        } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE
                && mInputView != null) {//切换输入发状态
            Keyboard current = mInputView.getKeyboard();
            if (current == mSymbolsKeyboard || current == mSymbolsShiftedKeyboard) {
                current = mPinyinKeyboard;//mQwertyKeyboard;
            } else if(current == mPinyinKeyboard){
    current = mQwertyKeyboard;//
   } else {
                current = mSymbolsKeyboard;
            }
            mInputView.setKeyboard(current);
            if (current == mSymbolsKeyboard) {
                current.setShifted(false);
            }
        } else {
            handleCharacter(primaryCode, keyCodes);//输入普通字符或符号
        }
    }

    private void handleCharacter(int primaryCode, int[] keyCodes) {
        if (isInputViewShown()) {//软键盘是否打开
            if (mInputView.isShifted()) {//检查键盘状态
                primaryCode = Character.toUpperCase(primaryCode);//转换大小写
            }
        }
        if (isAlphabet(primaryCode) && mPredictionOn) {//用charactor.isletter()判断是否为字符,并且之前有输入
            mComposing.append((char) primaryCode);//向结尾处追加字符
            getCurrentInputConnection().setComposingText(mComposing, mComposing.length());//设置当前输入文本显示
            updateShiftKeyState(getCurrentInputEditorInfo());
            updateCandidates();
        } else {
            getCurrentInputConnection().commitText(
                    String.valueOf((char) primaryCode), 1);//直接将当前输入的字符提交给链接的应用
        }
    }

http://vivien0515.blog.163.com/blog/static/11096733200921753459780/

 

 

 

http://blog.csdn.net/Fendy_Dai/archive/2010/06/08/5656081.aspx

http://blog.163.com/quickpy@yeah/

http://www.javaeye.com/topic/574406

 

http://www.gsmcdma.com/a/ruanjiankaifa/yingyongkaifa/2010/0515/3.html英文版

http://www.yddev.com/bbs/thread-63-1-1.html中文版http://www.heiher.info/855.html      http://news.wangmeng.cn/detailNews/2616-android-development-of-a-simple-description-of-the-input

 

http://www.devdiv.net/viewthread-26807

http://www.docin.com/p-47951191.html#

http://a.77mi.com/Thread/view/cps-3/id-4646

 

 

http://www.coolapk.com/docs/reference/android/inputmethodservice/InputMethodService.html

 

 

抱歉!评论已关闭.