4、SoftKeyboard
[java] view plain copy
1. /**
2. * Example of writing an input method for a soft keyboard. This code is
3. * focused on simplicity over completeness, so it should in no way be considered
4. * to be a complete soft keyboard implementation. Its purpose is to provide
5. * a basic example for how you would get started writing an input method, to
6. * be fleshed out as appropriate.
7. */
8. public class SoftKeyboard extends InputMethodService
9. implements KeyboardView.OnKeyboardActionListener {
10. static final boolean DEBUG = false;
11.
12. /**
13. * This boolean indicates the optional example code for performing
14. * processing of hard keys in addition to regular text generation
15. * from on-screen interaction. It would be used for input methods that
16. * perform language translations (such as converting text entered on
17. * a QWERTY keyboard to Chinese), but may not be used for input methods
18. * that are primarily intended to be used for on-screen text entry.
19. */
20. //是否在用硬键盘,这里默认的是总可以使用,费柴变量
21. static final boolean PROCESS_HARD_KEYS = true;
22.
23. //键盘view对象,但不是自己定义的类latinkeyboardview....
24. private KeyboardView mInputView;
25. //候选栏对象
26. private CandidateView mCandidateView;
27. //候选串之串
28. private CompletionInfo[] mCompletions;
29.
30. private StringBuilder mComposing = new StringBuilder();
31. //这东西是决定能不能有候选条
32. private boolean mPredictionOn;
33. //决定auto是否需要显示在候选栏
34. private boolean mCompletionOn;
35.
36. private int mLastDisplayWidth;
37. private boolean mCapsLock;
38. private long mLastShiftTime;
39. //matakey的按下状态,猜测是每种组合对应一个此值?
40. private long mMetaState;
41.
42. private LatinKeyboard mSymbolsKeyboard;
43. private LatinKeyboard mSymbolsShiftedKeyboard;
44. private LatinKeyboard mQwertyKeyboard;
45.
46. //当前键盘
47. private LatinKeyboard mCurKeyboard;
48.
49. //默认的使得输入中断的字符
50. private String mWordSeparators;
51.
52. /**
53. * Main initialization of the input method component. Be sure to call
54. * to super class.
55. */
56. @Override public void onCreate() {
57. super.onCreate();
58. //对resource这个东西有了一些了解:getResources是contextWrapper类的函数,contextWrapper而是inputmethodservice
59. //的间接基类
60. mWordSeparators = getResources().getString(R.string.word_separators);
61. "mytest", "SoftKeyboard_onCreate");
62. }
63.
64. /**
65. * This is the point where you can do all of your UI initialization. It
66. * is called after creation and any configuration change.
67. */
68. @Override public void onInitializeInterface() {
69. "mytest", "SoftKeyboard_onInitializeInterface");
70. //这只加载键盘,类似于findViewById,离真正生成界面还早
71. if (mQwertyKeyboard != null) {
72. // Configuration changes can happen after the keyboard gets recreated,
73. // so we need to be able to re-build the keyboards if the available
74. // space has changed.
75. //可用的,最大屏幕宽度,好像也没什么用
76. int displayWidth = getMaxWidth();
77. if (displayWidth == mLastDisplayWidth) return;
78. //难道就是为了记录最大宽度于mLastDisplayWidth?
79. mLastDisplayWidth = displayWidth;
80. }
81. new LatinKeyboard(this, R.xml.qwerty);
82. new LatinKeyboard(this, R.xml.symbols);
83. new LatinKeyboard(this, R.xml.symbols_shift);
84. }
85.
86. /**
87. * Called by the framework when your view for creating input needs to
88. * be generated. This will be called the first time your input method
89. * is displayed, and every time it needs to be re-created such as due to
90. * a configuration change.
91. */
92. @Override public View onCreateInputView() {
93. "mytest", "SoftKeyboard_onCreateInputView");
94. mInputView = (KeyboardView) getLayoutInflater().inflate(
95. null);
96. //上边的函数findViewById对于keyboardView是不能用的
97. //只对TextView等可以用
98. this);
99. mInputView.setKeyboard(mQwertyKeyboard);
100. //通过这个return,自己定义的keyboardview类对象就与这个类绑定了
101. return mInputView;
102. }
103.
104. /**
105. * Called by the framework when your view for showing candidates needs to
106. * be generated, like {@link #onCreateInputView}.
107. */
108. @Override public View onCreateCandidatesView() {
109. "mytest", "SoftKeyboard_onCreateCandidatesView");
110. new CandidateView(this);
111. //为什么参数是this??因为activity,inputmethodservice,这都是context的派生类
112. this);//在CandidateView类里面对这个类的描述中,参数就是个
113. return mCandidateView; //这一步很重要,后面的setCandidatesViewShown(false);就是个返回的结果造成的?
114. }
115.
116. /**
117. * This is the main point where we do our initialization of the input method
118. * to begin operating on an application. At this point we have been
119. * bound to the client, and are now receiving all of the detailed information
120. * about the target of our edits.
121. */
122. @Override public void onStartInput(EditorInfo attribute, boolean restarting) {
123. super.onStartInput(attribute, restarting);
124. "mytest", "SoftKeyboard_onStartInput");
125. // Reset our state. We want to do this even if restarting, because
126. // the underlying state of the text editor could have changed in any way.
127. //一个StringBuilder,前面定义的
128. 0);
129. //可知此处的candidateview注定还不显示
130.
131. if (!restarting) {
132. // Clear shift states.
133. 0;
134. }
135.
136. false; //猜测:是否需要显示候选词条,证实确实如此
137. false; //允许auto的内容显示在后选栏中
138. null;
139.
140. // We are now going to initialize our state based on the type of
141. // text being edited.
142. //一个靠谱的猜测:inputtype的给定值里面有那么几个掩码,但是从参数传来的具体inputtype值里面包含了所有的信息,不同的掩码能够得出不同的信息
143. //例如TYPE_MASK_CLASS就能得出下面四种,这四种属于同一类期望信息,这个信息叫做CLASS,下面一个掩码TYPE_MASK_VARIATION按位与出来的是一类
144. //叫做VARIATION的信息
145. switch (attribute.inputType&EditorInfo.TYPE_MASK_CLASS) {
146. case EditorInfo.TYPE_CLASS_NUMBER:
147. case EditorInfo.TYPE_CLASS_DATETIME:
148. // Numbers and dates default to the symbols keyboard, with
149. // no extra features.
150. mCurKeyboard = mSymbolsKeyboard;
151. break;
152.
153. case EditorInfo.TYPE_CLASS_PHONE:
154. // Phones will also default to the symbols keyboard, though
155. // often you will want to have a dedicated phone keyboard.
156. mCurKeyboard = mSymbolsKeyboard;
157. break;
158.
159. case EditorInfo.TYPE_CLASS_TEXT:
160. // This is general text editing. We will default to the
161. // normal alphabetic keyboard, and assume that we should
162. // be doing predictive text (showing candidates as the
163. // user types).
164. mCurKeyboard = mQwertyKeyboard;
165. true;
166.
167. // We now look for a few special variations of text that will
168. // modify our behavior.
169. int variation = attribute.inputType & EditorInfo.TYPE_MASK_VARIATION;
170. if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD ||
171. variation == EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) {
172. // Do not display predictions / what the user is typing
173. // when they are entering a password.
174. false; //密码框的输入是不需要候选词条的
175. }
176.
177. if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
178. || variation == EditorInfo.TYPE_TEXT_VARIATION_URI
179. || variation == EditorInfo.TYPE_TEXT_VARIATION_FILTER) {
180. // Our predictions are not useful for e-mail addresses
181. // or URIs.
182. false; //如果是网站或者是邮箱地址,不用候选词条
183. }
184.
185. if ((attribute.inputType&EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
186. //开始界面的那个输入框,就是自动生成的
187. // If this is an auto-complete text view, then our predictions
188. // will not be shown and instead we will allow the editor
189. // to supply their own. We only show the editor's
190. // candidates when in fullscreen mode, otherwise relying
191. // own it displaying its own UI.
192. false;
193. //经过测试,当输入法处在全屏模式的时候,原本auto的候选词会显示在输入法的候选栏中
194. //这是mCompletiOn的作用,这个值初始化设为false.
195. //如果把这里的两个值都设置为true则可以发现再输入任意auto的时候都会在候选栏中显示auto的词语
196. //所以,变量mCompletionOn的后续作用需要监视
197.
198. //这两行做后续测试: 真值:false,isFullscreenMode()
199. mCompletionOn = isFullscreenMode();
200. }
201.
202. // We also want to look at the current state of the editor
203. // to decide whether our alphabetic keyboard should start out
204. // shifted.
205. updateShiftKeyState(attribute);
206. break;
207.
208. default:
209. // For all unknown input types, default to the alphabetic
210. // keyboard with no special features.
211. mCurKeyboard = mQwertyKeyboard;
212. //决定是否需要初始大写状态
213. }
214.
215. // Update the label on the enter key, depending on what the application
216. // says it will do.
217. //根据输入目标设置回车键
218. }
219.
220. /**
221. * This is called when the user is done editing a field. We can use
222. * this to reset our state.
223. */
224. @Override public void onFinishInput() {
225. super.onFinishInput();
226. "mytest", "SoftKeyboard_onFinishInput");
227. //经测试,终于发现,start与finish,在输入框切换的时候,平时这俩结束函数并不调用,或许输入框只是隐藏。
228.
229. //测试语句 mInputView=null;
230. // Clear current composing text and candidates.
231. 0);
232. updateCandidates();
233.
234. // We only hide the candidates window when finishing input on
235. // a particular editor, to avoid popping the underlying application
236. // up and down if the user is entering text into the bottom of
237. // its window.
238. false);//默认的就是不可见的
239.
240. mCurKeyboard = mQwertyKeyboard;
241. if (mInputView != null) {
242. //据分析,关闭输入界面和收起输入界面还不是一回事?
243. }
244. }
245.
246. @Override public void onStartInputView(EditorInfo attribute, boolean restarting) {
247. super.onStartInputView(attribute, restarting);
248. //如果没有这个函数的作用,在切换输入目标的时候不会发生键盘的变化
249. //而且经过测试,这个函数执行的时间是开始输入的时候
250. // Apply the selected keyboard to the input view.
251. "mytest", "SoftKeyboard_onStartInputView");
252. mInputView.setKeyboard(mCurKeyboard);
253. //这个是转换键盘的关键
254. //mInputView是自己定义的一个键盘
255. //这个语句能让整个需要输入的目标关闭?到底是干什么用的??疑问?
256. }
257.
258. /**
259. * Deal with the editor reporting movement of its cursor.
260. */
261. @Override public void onUpdateSelection(int oldSelStart, int oldSelEnd,
262. int newSelStart, int newSelEnd,
263. int candidatesStart, int candidatesEnd) {
264. //光标!
265. super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
266. candidatesStart, candidatesEnd);
267. "mytest", "SoftKeyboard_onUpdateSelection");
268. // If the current selection in the text view changes, we should
269. // clear whatever candidate text we have.
270. //当输入框向输入法报告用户移动了光标时调用。,当用户移动输入框中的光标的时候,它就默认的表示本次输入完成了,
271. //然后将候选词以及正在输入的文本复位,并且向编辑器报告输入法已经完成了一个输入。
272. //四个整形都是坐标?
273. if (mComposing.length() > 0 && (newSelStart != candidatesEnd
274. || newSelEnd != candidatesEnd)) {
275. 0);//这才是候选栏置空的精义所在
276. //候选栏置空
277. //这个语句和下面if里面那个,决定了结束输入的全过程
278. if (ic != null) {
279. //这个语句的作用是,让输入目标内的下划线去掉,完成一次编辑
280. }
281. }
282. }
283.
284. /**
285. * This tells us about completions that the editor has determined based
286. * on the current text in it. We want to use this in fullscreen mode
287. * to show the completions ourself, since the editor can not be seen
288. * in that situation.
289. */
290. @Override public void onDisplayCompletions(CompletionInfo[] completions) {
291. //当需要在候选栏里面显示auto的内容
292. //此函数作用,猜测:当全屏幕模式的时候,mCompletionOn置true,可以通过候选栏来显示auto
293. "mytest", "SoftKeyboard_onDisplayCompletions");
294. if (mCompletionOn) { //必须这个变量允许
295. //赋值给本来里面专门记录候选值的变量
296. if (completions == null) {
297. null, false, false); //如果没有候选词,就这样处置
298. return;
299. }
300.
301. new ArrayList<String>();
302. for (int i=0; i<(completions != null ? completions.length : 0); i++) {
303. CompletionInfo ci = completions[i];
304. if (ci != null) stringList.add(ci.getText().toString());
305. }
306. true, true);
307. }
308. }
309.
310. /**
311. * This translates incoming hard key events in to edit operations on an
312. * InputConnection. It is only needed when using the
313. * PROCESS_HARD_KEYS option.
314. */
315. private boolean translateKeyDown(int keyCode, KeyEvent event) {
316. //这个函数在OnKeyDown中用到了
317. //这个是当组合键时候用,shift+A或者别的Alt+A之类
318. "mytest", "SoftKeyboard_translateKeyDown");
319. mMetaState = MetaKeyKeyListener.handleKeyDown(mMetaState,
320. keyCode, event);
321. //处理matakey的按下,猜测:每一个long型的mMetaState值都代表着一个meta键组合值。8成是对的
322. int c = event.getUnicodeChar(MetaKeyKeyListener.getMetaState(mMetaState)); //如果没这套组合键,就返回0
323. //这又是在干什么?猜测:每一个mMetaState值,对应着一个unicode值,这一步就是为了得到它,此猜测正确
324. //重置这个元状态。当取得了C值之后,完全可以重置元状态了,后面的语句不会出现任何问题。
325. //上面这三行有点疑问
326. mMetaState = MetaKeyKeyListener.adjustMetaAfterKeypress(mMetaState);
327.
328. //后边这函数是inputmethodservice自己的,获得当前的链接
329. InputConnection ic = getCurrentInputConnection();
330. if (c == 0 || ic == null) {
331. return false;
332. }
333.
334. //一个dead=true意味着是一个有定义的组合键
335. boolean dead = false;
336.
337. //看看c所昭示的这个键能不能被允许组合键
338. if ((c & KeyCharacterMap.COMBINING_ACCENT) != 0) {
339. //定义下来看能否使用这个组合键
340. true;
341. //这样就得到了真正的码值
342. c = c & KeyCharacterMap.COMBINING_ACCENT_MASK;
343. }
344.
345. //这是处理“编辑中最后字符越变”的情况
346. if (mComposing.length() > 0) {
347. char accent = mComposing.charAt(mComposing.length() -1 );//返回正在编辑的字串的最后一个字符
348. //这种情况下最后是返回了新的阿斯课码。composed最终还是要还给c.作为onKey的参数。
349. int composed = KeyEvent.getDeadChar(accent, c);
350.
351. if (composed != 0) {
352. c = composed;
353. 1); // 要把最后一个字符去掉,才能够在下一步中越变成为新的字符
354. }
355. }
356.
357. null); //强制输入C,这样就实现了组合键的功效
358.
359. return true;
360. }
361.
362. /**
363. * Use this to monitor key events being delivered to the application.
364. * We get first crack at them, and can either resume them or let them
365. * continue to the app.
366. */
367. @Override public boolean onKeyDown(int keyCode, KeyEvent event) {
368. "mytest", "SoftKeyboard_onKeyDown");
369. //这是重载了基类的,经测试确定,只有在硬件盘被敲击时候才调用,除了那个键本身的功效,还有这里定义的这些
370. //是对输入法的影响
371. switch (keyCode) {
372. case KeyEvent.KEYCODE_BACK: //这就是那个破箭头,扭曲的
373. // The InputMethodService already takes care of the back
374. // key for us, to dismiss the input method if it is shown.
375. // However, our keyboard could be showing a pop-up window
376. // that back should dismiss, so we first allow it to do that.
377. //mInputView类是自己定义的keyBoardView类
378. if (event.getRepeatCount() == 0 && mInputView != null) {
379. if (mInputView.handleBack()) {//通过弯钩键来关闭键盘的元凶在这里
380. //这函数干吗呢?猜测:如果成功地荡掉了键盘,就返回真
381. return true;
382. }
383. }
384. break;
385.
386. case KeyEvent.KEYCODE_DEL:
387. // Special handling of the delete key: if we currently are
388. // composing text for the user, we want to modify that instead
389. // of let the application to the delete itself.
390. if (mComposing.length() > 0) {
391. null); //所以,onkey定义中的事情才是软键盘的事件
392. return true;
393. }
394. break;
395.
396. case KeyEvent.KEYCODE_ENTER:
397. // Let the underlying text editor always handle these.
398. return false;
399.
400. default:
401. // For all other keys, if we want to do transformations on
402. // text being entered with a hard keyboard, we need to process
403. // it and do the appropriate action.
404. if (PROCESS_HARD_KEYS) { //这个是个废柴变量,因为在前面赋值了,永远是true
405. if (keyCode == KeyEvent.KEYCODE_SPACE
406. 0) {
407. //为什么有这个按位与?因为这个META_ALT_ON就是用来按位与来判断是否按下alt
408. //条件:alt+空格
409. // A silly example: in our input method, Alt+Space
410. // is a shortcut for 'android' in lower case.
411. InputConnection ic = getCurrentInputConnection();
412. if (ic != null) {
413. // First, tell the editor that it is no longer in the
414. // shift state, since we are consuming this.
415. // 清除组合键状态,如果不清除,出来的字符就不是Android
416. //由此可知,这些函数才是控制显示字符的,但貌似没那么简单
417. keyDownUp(KeyEvent.KEYCODE_A);
418. keyDownUp(KeyEvent.KEYCODE_N);
419. keyDownUp(KeyEvent.KEYCODE_D);
420. keyDownUp(KeyEvent.KEYCODE_R);
421. keyDownUp(KeyEvent.KEYCODE_O);
422. keyDownUp(KeyEvent.KEYCODE_I);
423. keyDownUp(KeyEvent.KEYCODE_D);
424. // And we consume this event.
425. return true;
426. }
427. }
428. if (mPredictionOn && translateKeyDown(keyCode, event)) {
429. return true;
430. }
431. }
432. }
433.
434. return super.onKeyDown(keyCode, event);
435. }
436.
437. /**
438. * Use this to monitor key events being delivered to the application.
439. * We get first crack at them, and can either resume them or let them
440. * continue to the app.
441. */
442. @Override public boolean onKeyUp(int keyCode, KeyEvent event) {
443. // If we want to do transformations on text being entered with a hard
444. // keyboard, we need to process the up events to update the meta key
445. // state we are tracking.
446. "mytest", "SoftKeyboard_onKeyUp");
447. if (PROCESS_HARD_KEYS) {
448. //哈哈,判断是不在使用硬件输入
449. //要懂得,mete keys意味着shift和alt这类的键
450. if (mPredictionOn) {
451. //处理matakey的释放
452. mMetaState = MetaKeyKeyListener.handleKeyUp(mMetaState,
453. keyCode, event);
454. }
455. }
456. //只有在一个键被放起时候执行,但经过测试,他不是执行输入的,仅仅是再输入之前做些事务,
457. return super.onKeyUp(keyCode, event);
458. }
459.
460. /**
461. * Helper function to commit any text being composed in to the editor.
462. */
463. private void commitTyped(InputConnection inputConnection) {
464. "mytest", "SoftKeyboard_commitTyped");
465. if (mComposing.length() > 0) {
466. //后边的参数决定了光标的应有位置
467. 0);
468. //这两行联手,一般能造成候选栏置空与候选词条串置空的效果
469. }
470. }
471.
472. /**
473. * Helper to update the shift state of our keyboard based on the initial
474. * editor state.
475. */
476. private void updateShiftKeyState(EditorInfo attr) {
477. //但是,这个函数每次输入一个字母都要执行
478. //用于在开始输入前切换大写
479. //它首先是判断是否输入视图存在,并且输入框要求有输入法,然后根据输入框的输入类型来获得是否需要大小写,最后定义在输入视图上。
480. //经测试,每当键盘刚出来的时候会有,每输入一个字符都会有这个函数的作用
481. "mytest", "SoftKeyboard_updateShiftKeyState");
482. //getKeyboard又是个可得私有变量的公有函数
483. //条件的含义是:当有字母键盘存在的时候
484. if (attr != null
485. null && mQwertyKeyboard == mInputView.getKeyboard()) {
486. int caps = 0;
487. //获得当前输入框的信息?本.java中,大多数的attr参数于这个东西等同
488. //这个破inputtype类型是全0,一般不会有这种破类型
489. if (ei != null && ei.inputType != EditorInfo.TYPE_NULL) {
490. //返回的东西不是光标位置,得到的是
491. //是否需要大写的判断,但是返回值是怎么弄的??
492. }
493. 0);
494. }
495. }
496.
497. /**
498. * Helper to determine if a given character code is alphabetic.
499. */
500. private boolean isAlphabet(int code) {
501. //看看是不是字母
502. "mytest", "SoftKeyboard_isAlphabet");
503. if (Character.isLetter(code)) {
504. return true;
505. else {
506. return false;
507. }
508. }
509.
510. /**
511. * Helper to send a key down / key up pair to the current editor.
512. */
513. private void keyDownUp(int keyEventCode) {
514. "mytest", "SoftKeyboard_keyDownUp");
515. getCurrentInputConnection().sendKeyEvent(
516. new KeyEvent(KeyEvent.ACTION_DOWN, keyEventCode)); //参见文档中KeyEvent
517. getCurrentInputConnection().sendKeyEvent(
518. new KeyEvent(KeyEvent.ACTION_UP, keyEventCode));
519. //明白了,这个函数是用来特殊输出的,就好像前面定义的“android”输出,但如果简单地从键盘输入字符,是不会经过这一步的
520. //一点都没错,强制输出,特殊输出,就这里
521. // keyDownUp(KeyEvent.KEYCODE_N);
522. // keyDownUp(KeyEvent.KEYCODE_B);
523. }
524.
525. /**
526. * Helper to send a character to the editor as raw key events.
527. */
528. private void sendKey(int keyCode) {
529. //传入的参数是阿斯课码
530. //处理中断符的时候使用到了
531. "mytest", "SoftKeyboard_sendKey");
532. switch (keyCode) {
533. case '\n':
534. keyDownUp(KeyEvent.KEYCODE_ENTER);
535. break;
536. default:
537. if (keyCode >= '0' && keyCode <= '9') {
538. '0' + KeyEvent.KEYCODE_0);
539. else {
540. char) keyCode), 1);
541. }
542. break;
543. }
544. }
545.
546. // Implementation of KeyboardViewListener
547. // Implementation of KeyboardViewListener
548. //你难道没看见这个类定义时候的接口吗?那个接口定义的监听函数就是为了监听这种On事件的,这就是软键盘按压事件
549. public void onKey(int primaryCode, int[] keyCodes) {
550. "mytest", "SoftKeyboard_onKey");
551. //后面定义的函数
552. //当输入被中断符号中断
553. if (isWordSeparator(primaryCode)) {
554. // Handle separator
555. if (mComposing.length() > 0) {
556. commitTyped(getCurrentInputConnection());
557. }
558. //提交完了输出之后,还必须要把这个特殊字符写上
559. //看看是否到了特殊的位置,需要改变大小写状态
560. else if (primaryCode == Keyboard.KEYCODE_DELETE) {
561. handleBackspace();
562. else if (primaryCode == Keyboard.KEYCODE_SHIFT) {
563. handleShift();
564. else if (primaryCode == Keyboard.KEYCODE_CANCEL) { //左下角那个键,关闭
565. handleClose();
566. return;
567. else if (primaryCode == LatinKeyboardView.KEYCODE_OPTIONS) {
568. //这个键,是这样的,前面的LatinKeyboardView这个类里面定义了KEYCODE_OPTIONS
569. //用来描述长按左下角关闭键的代替。经测试,千真万确
570. // Show a menu or somethin'
571. else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE
572. null) { //就是显示着“abc”或者"123"的那个键
573. Keyboard current = mInputView.getKeyboard();
574. if (current == mSymbolsKeyboard || current == mSymbolsShiftedKeyboard) {
575. current = mQwertyKeyboard;
576. else {
577. current = mSymbolsKeyboard;
578. }
579. //改变键盘的根本操作,但是对于具体输入的是大写字母这件事情,还要等按下了之后在做定论
580. mInputView.setKeyboard(current);
581. if (current == mSymbolsKeyboard) {
582. false); //测试,这里要是设置为true,打开之后只是shift键的绿点变亮,但是并没有变成另一个符号键盘
583. }
584. else {
585. //这就是处理真正的字符处理函数,不是那些其他的控制键
586. }
587. }
588.
589. public void onText(CharSequence text) { //这也是接口类的触发的函数。什么时候响应,有待考证
590. "mytest", "SoftKeyboard_onText");
591. InputConnection ic = getCurrentInputConnection();
592. if (ic == null) return;
593. ic.beginBatchEdit();
594. if (mComposing.length() > 0) {
595. commitTyped(ic);
596. }
597. 0);
598. ic.endBatchEdit();
599. //看是否需要切换大小写
600. }
601.
602. /**
603. * Update the list of available candidates from the current composing
604. * text. This will need to be filled in by however you are determining
605. * candidates.
606. */
607. private void updateCandidates() {//此函数处理的是不允许从auto获取的情况,应该是大多数情况
608. "mytest", "SoftKeyboard_updateCandidates");
609. if (!mCompletionOn) {
610. if (mComposing.length() > 0) { //mComposing记录着候选字符串之串,待考证
611. new ArrayList<String>();
612. list.add(mComposing.toString());
613. true, true);
614. else {
615. null, false, false);
616. }
617. }
618. }
619.
620. public void setSuggestions(List<String> suggestions, boolean completions,
621. boolean typedWordValid) {
622. //这第三个参数是前面函数调用的时候人为给的,没什么玄妙
623. "mytest", "SoftKeyboard_setSuggestions");
624. if (suggestions != null && suggestions.size() > 0) {
625. true);
626. else if (isExtractViewShown()) {
627. true);
628. }
629. if (mCandidateView != null) {
630. mCandidateView.setSuggestions(suggestions, completions, typedWordValid);
631. //就是改变了一下suggestion,在candidateView里面真正靠的是onDraw
632. }
633. }
634. //删除一个字,用的就是他
635. private void handleBackspace() {
636. "mytest", "SoftKeyboard_handleBackspace");
637. final int length = mComposing.length();
638. if (length > 1) {//就是在说等于1的时候
639. 1, length);
640. 1);
641. updateCandidates();
642. else if (length > 0) {
643. 0);
644. "", 0);
645. updateCandidates();
646. else {
647. keyDownUp(KeyEvent.KEYCODE_DEL);
648. }
649. updateShiftKeyState(getCurrentInputEditorInfo());
650. }
651.
652. private void handleShift() {//这才是大小写的切换,是正常切换(通过转换键)
653. "mytest", "SoftKeyboard_handleShift");
654. if (mInputView == null) {
655. return;
656. }
657.
658. Keyboard currentKeyboard = mInputView.getKeyboard();
659. if (mQwertyKeyboard == currentKeyboard) {
660. // Alphabet keyboard
661. //只有当键盘是字母键盘的时候,需要检验锁(控制变幻频率,不能过快)
662. mInputView.setShifted(mCapsLock || !mInputView.isShifted());
663. else if (currentKeyboard == mSymbolsKeyboard) {
664. true);
665. //所谓的setShift,仅仅指的是那个键盘的大小写键变化,经测试,只要android:code=-1就有这种绿点效果
666. mInputView.setKeyboard(mSymbolsShiftedKeyboard);
667. true);
668. else if (currentKeyboard == mSymbolsShiftedKeyboard) {
669. false);
670. mInputView.setKeyboard(mSymbolsKeyboard);
671. false);
672. }
673. }
674.
675. private void handleCharacter(int primaryCode, int[] keyCodes) { //primayCode是键的阿斯课码值
676. "mytest", "SoftKeyboard_handleCharacter");
677. if (isInputViewShown()) {
678. if (mInputView.isShifted()) {
679. primaryCode = Character.toUpperCase(primaryCode);
680. //这才真正把这个字符变成了大写的效果,经测试,没有就不行
681. //把键盘换成大写的了还不够,那只是从View上解决了问题,一定要这样一句才行
682. }
683. }
684. if (isAlphabet(primaryCode) && mPredictionOn) { //输入的是个字母,而且允许候选栏显示
685. char) primaryCode); //append(添加)就是把当前的输入的一个字符放到mComposing里面来
686. 1);//在输入目标中也显示最新得到的mComposing.
687. //每当输入完结,都要检验是否需要变到大写
688. updateCandidates();
689. else {
690. //比如说当输入的是“‘”这个符号的时候,就会掉用这个
691. //结果就是remove掉所有编辑中的字符,第二个参数的正负,决定着
692. //光标位置的不同
693. getCurrentInputConnection().commitText(
694. char) primaryCode), 1);
695. }
696. }
697.
698. private void handleClose() {
699. "mytest", "SoftKeyboard_handleClose");
700. //关闭键盘件的作用就在这里,左下角那个.,记住!!!!!左下角那个,不是弯钩键!!!!
701. commitTyped(getCurrentInputConnection());
702. 0); //关掉输入法的区域,这才是关闭的王道.似乎这句包含了上面那句的作用(测试结果)
703. //这个函数不懂什么意思待问?? 哪里都测试,哪里都没有用处??
704. }
705.
706. private void checkToggleCapsLock() {
707. "mytest", "SoftKeyboard_checkToggleCapsLock");
708. long now = System.currentTimeMillis();//记录上次变幻的时间
709. if (mLastShiftTime + 800 > now) {//不允许频繁地换大小写?
710. mCapsLock = !mCapsLock;
711. 0;
712. else {
713. mLastShiftTime = now;
714. }
715. }
716.
717. private String getWordSeparators() {
718. "mytest", "SoftKeyboard_getWordSeparators");
719. return mWordSeparators;
720. }
721.
722. public boolean isWordSeparator(int code) {
723. "mytest", "SoftKeyboard_isWordSeparator");
724. //检查所属入的字符有没有在这些字符里面
725. return separators.contains(String.valueOf((char)code));
726. }
727.
728. public void pickDefaultCandidate() {
729. "mytest", "SoftKeyboard_pickDefaultCandidate");
730. 0);
731. }
732.
733. public void pickSuggestionManually(int index) {
734. "mytest", "SoftKeyboard_pickSuggestionManually");
735. if (mCompletionOn && mCompletions != null && index >= 0
736. && index < mCompletions.length) {
737. CompletionInfo ci = mCompletions[index];
738. getCurrentInputConnection().commitCompletion(ci);
739. if (mCandidateView != null) {
740. mCandidateView.clear();
741. }
742. updateShiftKeyState(getCurrentInputEditorInfo());
743. else if (mComposing.length() > 0) {
744. // If we were generating candidate suggestions for the current
745. // text, we would commit one of them here. But for this sample,
746. // we will just commit the current text.
747. commitTyped(getCurrentInputConnection());
748. }
749. }
750.
751. //着下面6个函数,完全是因为声明了那个接口类,所以必须要包含这几个函数,还有上面的几个函数,但是实际上这些函数可以没有意义
752. public void swipeRight() {
753. "mytest", "SoftKeyboard_swipeRight");
754. if (mCompletionOn) {
755. pickDefaultCandidate();
756. }
757. }
758.
759. public void swipeLeft() {
760. "mytest", "SoftKeyboard_swipeLeft");
761. handleBackspace();
762. }
763.
764. public void swipeDown() {
765. "mytest", "SoftKeyboard_swipeDown");
766. handleClose();
767. }
768.
769. public void swipeUp() {
770. "mytest", "SoftKeyboard_swipeUp");
771. }
772.
773. public void onPress(int primaryCode) {
774. "mytest", "SoftKeyboard_onPress");
775. }
776.
777. public void onRelease(int primaryCode) {
778. "mytest", "SoftKeyboard_onRelease");
779. }
780. }
参考文献:
android sdk中 softkeyboard的自己解析(1)android sdk中 softkeyboard的自己解析(2)android sdk中 softkeyboard的自己解析(3)android sdk中 softkeyboard的自己解析(4)