本文是openwnn源码解析的第5篇,主要是介绍openwnn日文输入法的自定义词库功能。
最近看到网上有转载我的文章,但没有注明出处。由于这是系列文章单单转载一两篇读者也不一定看得懂。因此在这里做一个标记,如果看到转载的同学,可以访问我的博客http://blog.csdn.net/xianming01。
用户自定义词库包含UserDictionaryToolsEdit.java,UserDictionaryToolsList.java,UserDictionaryToolsListFocus.java,UserDictionaryToolsListJAJP.java,UserDictionaryToolsEditJAJP.java,ClearLearnDictionaryDialogPreferenceJAJP.java,ClearUserDictionaryDialogPreferenceJAJP.java这些类。
用户可以进入输入法设置界面,其中关于自定义词库部分:
其中日语用户词典与英语用户词典实现起来是一样的。而“学习词典初始化”只是将用户的学习词典清空,也是比较简单的。
1、涉及的类
这里涉及5个类UserDictionaryToolsEdit.java,UserDictionaryToolsList.java,UserDictionaryToolsListFocus.java,UserDictionaryToolsListJAJP.java,UserDictionaryToolsEditJAJP.java.其中最关键的是UserDictionaryToolsEdit.java,UserDictionaryToolsList.java;而UserDictionaryToolsEditJAJP.java,UserDictionaryToolsListJAJP.java则分别继承前面两个类,其重载了几个方法,主要是为了做不同输入法的配置工作。
比如UserDictionaryToolsListJAJP类代码:
- /**
- * The user dictionary tool class for Japanese IME.
- *
- * @author Copyright (C) 2009 OMRON SOFTWARE CO., LTD. All Rights Reserved.
- */
- public class UserDictionaryToolsListJAJP extends UserDictionaryToolsList {
- /**
- * Constructor
- */
- public UserDictionaryToolsListJAJP() {
- mListViewName = "jp.co.omronsoft.openwnn.JAJP.UserDictionaryToolsListJAJP";
- mEditViewName = "jp.co.omronsoft.openwnn.JAJP.UserDictionaryToolsEditJAJP";
- mPackageName = "jp.co.omronsoft.openwnn";
- }
- /** @see jp.co.omronsoft.openwnn.UserDictionaryToolsList#headerCreate */
- @Override protected void headerCreate() {
- getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,
- R.layout.user_dictionary_tools_list_header_ja);
- }
- /** @see jp.co.omronsoft.openwnn.UserDictionaryToolsList#createUserDictionaryToolsEdit */
- @Override protected UserDictionaryToolsEdit createUserDictionaryToolsEdit(View view1, View view2) {
- return new UserDictionaryToolsEditJAJP(view1, view2);
- }
- /** @see jp.co.omronsoft.openwnn.UserDictionaryToolsList#sendEventToIME */
- @Override protected boolean sendEventToIME(OpenWnnEvent ev) {
- try {
- return OpenWnnJAJP.getInstance().onEvent(ev);
- } catch (Exception ex) {
- /* do nothing if an error occurs */
- }
- return false;
- }
- }
2、UserDictionaryToolsList.java
其界面类似如下:
点击其中的“add”按钮,则弹出如下添加对话框(实际上是个activity):
从上面的这两个界面我们可以看出,这个类有很大一部分代码是用来生成并处理menu的,这一部分代码就不介绍了。
我们以删除对话框中的删除词条功能来介绍一下这里面比较特别的地方:
- /**
- * Process the event when the button on the "Delete word" dialog is pushed
- *
- * @param dialog The information of the dialog
- * @param button The button that is pushed
- */
- private DialogInterface.OnClickListener mDialogDeleteWords =
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int button) {
- CharSequence focusString = ((TextView)sFocusingView).getText();
- CharSequence focusPairString = ((TextView)sFocusingPairView).getText();
- WnnWord wnnWordSearch = new WnnWord();
- if (mSelectedViewID > MAX_WORD_COUNT) {
- wnnWordSearch.stroke = focusPairString.toString();
- wnnWordSearch.candidate = focusString.toString();
- } else {
- wnnWordSearch.stroke = focusString.toString();
- wnnWordSearch.candidate = focusPairString.toString();
- }
- boolean deleted = deleteWord(wnnWordSearch);
- if (deleted) {
- Toast.makeText(getApplicationContext(),
- R.string.user_dictionary_delete_complete,
- Toast.LENGTH_LONG).show();
- } else {
- Toast.makeText(getApplicationContext(),
- R.string.user_dictionary_delete_fail,
- Toast.LENGTH_LONG).show();
- return;
- }
- int id = mSelectedViewID;
- id = (MAX_WORD_COUNT < id) ? id - MAX_WORD_COUNT : id;
- View v = null;
- mTableLayout.removeView((View)sFocusingView.getParent());
- //sFocusingView的ViewParent是一个row
- //拥有焦点的词条被删除以后,先从被删词条下面开始找,若有,则下面的按个词条获得焦点,否则被删词条上面的词条获得焦点
- for (int i = id; i < MAX_WORD_COUNT; i++) {
- v = mTableLayout.findViewById(i);
- if (v != null) {
- break;
- }
- }
- if (v == null) {
- for (int i = id; 0 <= i; i--) {
- v = mTableLayout.findViewById(i);
- if (v != null) {
- break;
- }
- }
- }
- if (v != null) {
- ((View)v.getParent()).requestFocus();
- }
- mWordCount--;
- TextView leftText = (TextView) findViewById(R.id.user_dictionary_tools_list_title_words_count);
- leftText.setText(mWordCount + "/" + MAX_WORD_COUNT);
- if (mInitializedMenu) {
- onCreateOptionsMenu(mMenu);
- }
- }
- };
另外,程序中用到了一个小技巧,就是在一个row里面本来有两个TextView的,一个是Read(读音),一个是Candidate(候选词)。正常情况下,我们找到Read还需要去找Candidate。程序使用了UserDictionaryToolsListFocus这个类重定义了TextView。其目的是使得你找到了Read,就可以通过UserDictionaryToolsListFocus类的mPairView找到Candidate,反之亦然。
当然,又个问题差点漏了。大家看这一段事件处理程序:
- /** @see android.app.Activity#onKeyUp
- * 这里表示按下了手机硬键盘中的中间键
- **/
- @Override public boolean onKeyUp(int keyCode, KeyEvent event) {
- /* open the menu if KEYCODE_DPAD_CENTER is pressed */
- if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
- openOptionsMenu();
- return true;
- }
- return false;
- }
3、UserDictionaryToolsEdit.java
这里实际上就是一个编辑框,技术实现上是比较简单的。
不管是添加词条还是修改词条,用的都是这个界面,因此它需要判断当前是添加还是编辑,如果是编辑,需要初始化数据。在onCreate函数中,有如下代码:
- /* get the request and do it */
- Intent intent = getIntent();
- String action = intent.getAction();
- if (action.equals(Intent.ACTION_INSERT)) {
- /* add a word */
- mEntryButton.setEnabled(false);
- mRequestState = STATE_INSERT;
- } else if (action.equals(Intent.ACTION_EDIT)) {
- /* edit a word */
- mEntryButton.setEnabled(true);
- mReadEditText.setText(((TextView)sFocusingView).getText());
- mCandidateEditText.setText(((TextView)sFocusingPairView).getText());
- mRequestState = STATE_EDIT;
- /* save the word's information before this edit */
- mBeforeEditWnnWord = new WnnWord();
- mBeforeEditWnnWord.stroke = ((TextView)sFocusingView).getText().toString();
- mBeforeEditWnnWord.candidate = ((TextView)sFocusingPairView).getText().toString();
- } else {
- /* finish if it is unknown request */
- Log.e("OpenWnn", "onCreate() : Invaled Get Intent. ID=" + intent);
- finish();
- return;
- }
其他的代码都比较简单,应该看得懂。
4、清空词典
这里涉及到清空用户学习词典和用户自定义词典。
以清空用户学习词典为例子,这里是重定义了一个DialogPreference,用户选择确认了以后给OpenWnnJAJP发送一个事件。代码如下:
- /** @see android.preference.DialogPreference#onDialogClosed */
- @Override protected void onDialogClosed(boolean positiveResult) {
- if (positiveResult) {
- /* clear the learning dictionary */
- OpenWnnEvent ev = new OpenWnnEvent(OpenWnnEvent.INITIALIZE_LEARNING_DICTIONARY, new WnnWord());
- OpenWnnJAJP.getInstance().onEvent(ev);
- /* show the message */
- Toast.makeText(mContext.getApplicationContext(), R.string.dialog_clear_learning_dictionary_done,
- Toast.LENGTH_LONG).show();
- }
- }
5、其他
这一部分代码比较简单,所以就做了个简单介绍。
另外,对于事件处理部分,特别是OpenWnnEvent部分没有介绍,等着后续吧。