Android 从输入法 到 EditText 研究
2016-01-15 18:41
531 查看
首先看一个 View 的一个方法:
View 没有实现,直接返回 null,
再看 TextView 的实现,
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
if (onCheckIsTextEditor() && isEnabled()) {
...
if (mText instanceof Editable) {
InputConnection ic = new EditableInputConnection(this);
outAttrs.initialSelStart = getSelectionStart();
outAttrs.initialSelEnd = getSelectionEnd();
outAttrs.initialCapsMode = ic.getCursorCapsMode(getInputType());
return ic;
}
...
使用了 EditableInputConnection
现在要知道,这个方法何时被调用?
首先我们是点击了 EditText 系统随机呼出输入法,那么好,我们看 TextView 的 onTouchEvent 方法
@Override
public boolean onTouchEvent(MotionEvent event) {
...
if (touchIsFinished && (isTextEditable() || textIsSelectable)) {
// Show the IME, except when selecting in read-only text.
final InputMethodManager imm = InputMethodManager.peekInstance();
viewClicked(imm);
if (!textIsSelectable && mEditor.mShowSoftInputOnFocus) {
handled |= imm != null && imm.showSoftInput(this, 0);
}<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
这里调用了 imm.showSoftInput 弹出输入法,
但是我们还得找到 TextView 与输入法建立链接的地方,我们查找 InputMethodManager 找到了一处调用,view.onCreateInputConnection 方法:
public void restartInput(View view) {
...
boolean startInputInner(IBinder windowGainingFocus, int controlFlags, int softInputMode,
int windowFlags) {
...
// Okay we are now ready to call into the served view and have it
// do its stuff.
// Life is good: let's hook everything up!
EditorInfo tba = new EditorInfo();
tba.packageName = view.getContext().getPackageName();
tba.fieldId = view.getId();
InputConnection ic = view.onCreateInputConnection(tba);
if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);
...到这一步似乎 TextView 就与输入法建立起了连接,不过还有很重要的一点是,要弹出输入法首先 EditText 必须获取焦点,正是获取焦点的时候,与输入法进行了关键一步的交流,这个实现在 View:
protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
...
InputMethodManager imm = InputMethodManager.peekInstance();
if (!gainFocus) {
if (isPressed()) {
setPressed(false);
}
if (imm != null && mAttachInfo != null
&& mAttachInfo.mHasWindowFocus) {
imm.focusOut(this);
}
onFocusLost();
} else if (imm != null && mAttachInfo != null
&& mAttachInfo.mHasWindowFocus) {
imm.focusIn(this);
}
...
调用了 InputMethodManager 的 focusIn 告知输入法当前接受输入的 View,你如果只通过前面几个方法去看,根本不知道 InputMethodManager 何时确定了 View 对象,
然后,输入法与接收客户端进行交互是通过 InputConnection 进行的
public interface InputConnection {
public boolean deleteSurroundingText(int beforeLength, int afterLength); //删除输入的字符
public boolean commitText(CharSequence text, int newCursorPosition); //输入字符
public boolean sendKeyEvent(KeyEvent event); //注入按键
}当你在输入的时候,输入法会调用以上3个方法(夸进程)
具体如何调用不解释,本篇的重点在理清联系,
除了 EditText ,WebView 也能弹出输入法,WebView 我是比较好奇的,因为他只是一个 ViewGroup
欲知详情请移步至此:点击打开链接
View 没有实现,直接返回 null,
再看 TextView 的实现,
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
if (onCheckIsTextEditor() && isEnabled()) {
...
if (mText instanceof Editable) {
InputConnection ic = new EditableInputConnection(this);
outAttrs.initialSelStart = getSelectionStart();
outAttrs.initialSelEnd = getSelectionEnd();
outAttrs.initialCapsMode = ic.getCursorCapsMode(getInputType());
return ic;
}
...
使用了 EditableInputConnection
现在要知道,这个方法何时被调用?
首先我们是点击了 EditText 系统随机呼出输入法,那么好,我们看 TextView 的 onTouchEvent 方法
@Override
public boolean onTouchEvent(MotionEvent event) {
...
if (touchIsFinished && (isTextEditable() || textIsSelectable)) {
// Show the IME, except when selecting in read-only text.
final InputMethodManager imm = InputMethodManager.peekInstance();
viewClicked(imm);
if (!textIsSelectable && mEditor.mShowSoftInputOnFocus) {
handled |= imm != null && imm.showSoftInput(this, 0);
}<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
这里调用了 imm.showSoftInput 弹出输入法,
但是我们还得找到 TextView 与输入法建立链接的地方,我们查找 InputMethodManager 找到了一处调用,view.onCreateInputConnection 方法:
public void restartInput(View view) {
...
boolean startInputInner(IBinder windowGainingFocus, int controlFlags, int softInputMode,
int windowFlags) {
...
// Okay we are now ready to call into the served view and have it
// do its stuff.
// Life is good: let's hook everything up!
EditorInfo tba = new EditorInfo();
tba.packageName = view.getContext().getPackageName();
tba.fieldId = view.getId();
InputConnection ic = view.onCreateInputConnection(tba);
if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);
...到这一步似乎 TextView 就与输入法建立起了连接,不过还有很重要的一点是,要弹出输入法首先 EditText 必须获取焦点,正是获取焦点的时候,与输入法进行了关键一步的交流,这个实现在 View:
protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
...
InputMethodManager imm = InputMethodManager.peekInstance();
if (!gainFocus) {
if (isPressed()) {
setPressed(false);
}
if (imm != null && mAttachInfo != null
&& mAttachInfo.mHasWindowFocus) {
imm.focusOut(this);
}
onFocusLost();
} else if (imm != null && mAttachInfo != null
&& mAttachInfo.mHasWindowFocus) {
imm.focusIn(this);
}
...
调用了 InputMethodManager 的 focusIn 告知输入法当前接受输入的 View,你如果只通过前面几个方法去看,根本不知道 InputMethodManager 何时确定了 View 对象,
然后,输入法与接收客户端进行交互是通过 InputConnection 进行的
public interface InputConnection {
public boolean deleteSurroundingText(int beforeLength, int afterLength); //删除输入的字符
public boolean commitText(CharSequence text, int newCursorPosition); //输入字符
public boolean sendKeyEvent(KeyEvent event); //注入按键
}当你在输入的时候,输入法会调用以上3个方法(夸进程)
具体如何调用不解释,本篇的重点在理清联系,
除了 EditText ,WebView 也能弹出输入法,WebView 我是比较好奇的,因为他只是一个 ViewGroup
欲知详情请移步至此:点击打开链接
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories