输入法原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangzihan91/article/details/85162425

Question1:客户端如何与输入法产生联系

首先我们要明确的是输入法就是一个Service,无论是百度输入法还是搜狗输入法,都继承自系统提供的InputMethodService类

再说一下我们如何在App中主动调起输入法,其中,InputMethodManager就是用来操作输入法的类:

InputMethodManager inputManager = InputMethodManager.peekInstance();

inputManager.showSoftInput(editText, 0);

这个是输入法的经典流程图,上面我们说过,应用进程使用的是IMM,输入法进程使用的是IMS,在IMM和IMS中间是一个系统服务,缩写是IMMS

但是日常使用中,我们并没有主动调用IMM,但是输入法却能正常使用,比如当我们进入一个有 EditText控件的界面时,会自动弹出软键盘,原因是系统默默的帮我们做了很多工作。在新增或者删除窗口时,WindowManagerService会上自下判断由哪个窗口获取焦点,WMS拿到焦点Window后会跳到的ViewRootImpl,然后通过DecorView分发到各个view,最后调的是view的onWindowFocusChanged, 布尔值参数表示当前View所在窗口得到还是失去焦点, 我们直接看得到焦点这个分支,这个判断条件表示当前view能不能拿到焦点,如果view也能拿到焦点的话,最终会走到startInputInner,在该方法中会初始化View的进程通信接口,并调用IMM的startInput方法把该接口传递给输入法,在IMMS中会完成输入法创建和进程通讯接口双向绑定的工作,当输入法生成数据后,会通过这个binder把数据传递给应用进程

Question2:从源码上看,输入法是无法获取焦点的(由于输入法Window设置了FLAG_NOT_FOCUSABLE属性,所以无法获取焦点),因此,我们第一反应是输入法拿不到硬键盘输入KeyEvent,但事实上,输入法可以完美支持硬键盘

上面仔细分析了输入法的整体流程,其中,硬键盘事件是在ViewRootImpl中处理的,当系统把焦点事件传递给获取焦点的Window时,ViewRootImpl会通过dispatchInputEvent方法把硬键盘事件传递给输入法

Question3:如何实现一个输入法应用,直接上图

我们直接继承IMS,其中setCandidatesView(View)用来设置候选词视图,setInputView(View)用来设置输入视图,getCurrentInputConnection用来获取应用进程的通讯接口(InputConnection),这里面主要有两个方法比较常用,sendKeyEvent和commitText,其中sendKeyEvent用来发送硬键盘事件(删除等),commitText用来发送文本

猜你喜欢

转载自blog.csdn.net/wangzihan91/article/details/85162425
今日推荐