android输入法02:openwnn源码解析05—用户自定义词库
2012-05-15 22:08
295 查看
本文是openwnn源码解析的第5篇,主要是介绍openwnn日文输入法的自定义词库功能。
最近看到网上有转载我的文章,但没有注明出处。由于这是系列文章单单转载一两篇读者也不一定看得懂。因此在这里做一个标记,如果看到转载的同学,可以访问我的博客http://blog.csdn.net/xianming01。
用户自定义词库包含UserDictionaryToolsEdit.java,UserDictionaryToolsList.java,UserDictionaryToolsListFocus.java,UserDictionaryToolsListJAJP.java,UserDictionaryToolsEditJAJP.java,ClearLearnDictionaryDialogPreferenceJAJP.java,ClearUserDictionaryDialogPreferenceJAJP.java这些类。
用户可以进入输入法设置界面,其中关于自定义词库部分:
![](http://my.csdn.net/uploads/201205/08/1336409061_7738.JPG)
其中日语用户词典与英语用户词典实现起来是一样的。而“学习词典初始化”只是将用户的学习词典清空,也是比较简单的。
1、涉及的类
这里涉及5个类UserDictionaryToolsEdit.java,UserDictionaryToolsList.java,UserDictionaryToolsListFocus.java,UserDictionaryToolsListJAJP.java,UserDictionaryToolsEditJAJP.java.其中最关键的是UserDictionaryToolsEdit.java,UserDictionaryToolsList.java;而UserDictionaryToolsEditJAJP.java,UserDictionaryToolsListJAJP.java则分别继承前面两个类,其重载了几个方法,主要是为了做不同输入法的配置工作。
比如UserDictionaryToolsListJAJP类代码:
[java] view
plaincopy
/**
* 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
其界面类似如下:
![](http://my.csdn.net/uploads/201205/08/1336409442_9131.JPG)
点击其中的“add”按钮,则弹出如下添加对话框(实际上是个activity):
![](http://my.csdn.net/uploads/201205/08/1336409545_4092.JPG)
从上面的这两个界面我们可以看出,这个类有很大一部分代码是用来生成并处理menu的,这一部分代码就不介绍了。
我们以删除对话框中的删除词条功能来介绍一下这里面比较特别的地方:
[java] view
plaincopy
/**
* 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,反之亦然。
当然,又个问题差点漏了。大家看这一段事件处理程序:
[java] view
plaincopy
/** @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;
}
这里,你如果在用输入法时,按模拟器的那个中间键(他的旁边是前后左右四个键),则会弹出菜单,跟按“menu”键效果是一样的。
3、UserDictionaryToolsEdit.java
这里实际上就是一个编辑框,技术实现上是比较简单的。
不管是添加词条还是修改词条,用的都是这个界面,因此它需要判断当前是添加还是编辑,如果是编辑,需要初始化数据。在onCreate函数中,有如下代码:
[java] view
plaincopy
/* 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;
}
这个是根据action的类型来判断是添加还是编辑。
其他的代码都比较简单,应该看得懂。
4、清空词典
这里涉及到清空用户学习词典和用户自定义词典。
以清空用户学习词典为例子,这里是重定义了一个DialogPreference,用户选择确认了以后给OpenWnnJAJP发送一个事件。代码如下:
[java] view
plaincopy
/** @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部分没有介绍,等着后续吧。
最近看到网上有转载我的文章,但没有注明出处。由于这是系列文章单单转载一两篇读者也不一定看得懂。因此在这里做一个标记,如果看到转载的同学,可以访问我的博客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类代码:
[java] view
plaincopy
/**
* 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的,这一部分代码就不介绍了。
我们以删除对话框中的删除词条功能来介绍一下这里面比较特别的地方:
[java] view
plaincopy
/**
* 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,反之亦然。
当然,又个问题差点漏了。大家看这一段事件处理程序:
[java] view
plaincopy
/** @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;
}
这里,你如果在用输入法时,按模拟器的那个中间键(他的旁边是前后左右四个键),则会弹出菜单,跟按“menu”键效果是一样的。
3、UserDictionaryToolsEdit.java
这里实际上就是一个编辑框,技术实现上是比较简单的。
不管是添加词条还是修改词条,用的都是这个界面,因此它需要判断当前是添加还是编辑,如果是编辑,需要初始化数据。在onCreate函数中,有如下代码:
[java] view
plaincopy
/* 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;
}
这个是根据action的类型来判断是添加还是编辑。
其他的代码都比较简单,应该看得懂。
4、清空词典
这里涉及到清空用户学习词典和用户自定义词典。
以清空用户学习词典为例子,这里是重定义了一个DialogPreference,用户选择确认了以后给OpenWnnJAJP发送一个事件。代码如下:
[java] view
plaincopy
/** @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部分没有介绍,等着后续吧。
相关文章推荐
- android输入法02:openwnn源码解析02—Keyboard和KeyboardView
- android输入法02:openwnn源码解析01—输入流程
- 【Android 源码解析】bus 实现原理(附demo)
- Android中Ringtone播放详解【安卓源码解析五】
- Android源码解析Handler系列第(二)篇--- ThreadLocal详解
- Android中Ringtone播放详解【安卓源码解析五】
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- 插件化系列开发之九--Android 全面插件化 RePlugin 流程与源码解析
- Android依赖注入Dagger的使用和源码解析
- Android消息机制Handler解析(源码+Demo)
- Android 带你从源码的角度解析Scroller的滚动实现原理
- android smack源码分析——接收消息以及如何解析消息
- Android setContentView()源码解析
- Android 带你从源码的角度解析Scroller的滚动实现原理
- Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
- android handler机制源码解析(三)
- java微信开发API解析(六)-综合运用(消息处理、自定义菜单响应处理、用户自动分组处理;包含源码)
- android 用户登陆注册UI设计之 edittext (就是输入用户名和密码的文本框)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)