編輯:Android開發實例
我們知道當一個編輯框獲得焦點的時候,將會create一個新的IME客戶端,那麼IMF框架是怎樣處理這個事件的呢?
首先調用EditText的構造函數EditTex->TextView->setText()
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) imm.restartInput(this);
->startInputInner
- void startInputInner() {
- final View view;
- synchronized (mH) {
- view = mServedView;
- // Make sure we have a window token for the served view.
- if (DEBUG) Log.v(TAG, "Starting input: view=" + view);
- if (view == null) {
- if (DEBUG) Log.v(TAG, "ABORT input: no served view!");
- return;
- }
- }
- // Now we need to get an input connection from the served view.
- // This is complicated in a couple ways: we can't be holding our lock
- // when calling out to the view, and we need to make sure we call into
- // the view on the same thread that is driving its view hierarchy.
- Handler vh = view.getHandler();
- if (vh == null) {
- // If the view doesn't have a handler, something has changed out
- // from under us, so just bail.
- if (DEBUG) Log.v(TAG, "ABORT input: no handler for view!");
- return;
- }
- if (vh.getLooper() != Looper.myLooper()) {
- // The view is running on a different thread than our own, so
- // we need to reschedule our work for over there.
- if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread");
- vh.post(new Runnable() {
- public void run() {
- startInputInner();
- }
- });
- return;
- }
- // 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); //create 新的InputConnection
- if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);
- synchronized (mH) {
- // Now that we are locked again, validate that our state hasn't
- // changed.
- if (mServedView != view || !mServedConnecting) {
- // Something else happened, so abort.
- if (DEBUG) Log.v(TAG,
- "Starting input: finished by someone else (view="
- + mServedView + " conn=" + mServedConnecting + ")");
- return;
- }
- // If we already have a text box, then this view is already
- // connected so we want to restart it.
- final boolean initial = mCurrentTextBoxAttribute == null;
- // Hook 'em up and let 'er rip.
- mCurrentTextBoxAttribute = tba;
- mServedConnecting = false;
- mServedInputConnection = ic;
- IInputContext servedContext;
- if (ic != null) {
- mCursorSelStart = tba.initialSelStart;
- mCursorSelEnd = tba.initialSelEnd;
- mCursorCandStart = -1;
- mCursorCandEnd = -1;
- mCursorRect.setEmpty();
- servedContext = new ControlledInputConnectionWrapper(vh.getLooper(), ic);
- } else {
- servedContext = null;
- }
- try {
- if (DEBUG) Log.v(TAG, "START INPUT: " + view + " ic="
- + ic + " tba=" + tba + " initial=" + initial);
- InputBindResult res = mService.startInput(mClient,
- servedContext, tba, initial, mCurMethod == null); //啟動IMEservice
- if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
- if (res != null) {
- if (res.id != null) {
- mBindSequence = res.sequence;
- mCurMethod = res.method;
- } else {
- // This means there is no input method available.
- if (DEBUG) Log.v(TAG, "ABORT input: no input method!");
- return;
- }
- }
- if (mCurMethod != null && mCompletions != null) {
- try {
- mCurMethod.displayCompletions(mCompletions);
- } catch (RemoteException e) {
- }
- }
- } catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- }
- }
那麼到了IME部分的流程又是如何的呢?
首先收到configure change的event調用onConfigurationChanged->inputmethodservice.onConfigurationChanged(conf)
- @Override public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- boolean visible = mWindowVisible;
- int showFlags = mShowInputFlags;
- boolean showingInput = mShowInputRequested;
- CompletionInfo[] completions = mCurCompletions;
- initViews();
- mInputViewStarted = false;
- mCandidatesViewStarted = false;
- if (mInputStarted) {
- doStartInput(getCurrentInputConnection(),
- getCurrentInputEditorInfo(), true); //調用startinput,創建IME的input
- }
- if (visible) {
- if (showingInput) {
- // If we were last showing the soft keyboard, try to do so again.
- if (onShowInputRequested(showFlags, true)) {
- showWindow(true);
- if (completions != null) {
- mCurCompletions = completions;
- onDisplayCompletions(completions);
- }
- } else {
- hideWindow();
- }
- } else if (mCandidatesVisibility == View.VISIBLE) {
- // If the candidates are currently visible, make sure the
- // window is shown for them.
- showWindow(false);
- } else {
- // Otherwise hide the window.
- hideWindow();
- }
- }
- }
doStartInput->initialize->onInitializeInterface->onStartInput->onStartInputView.
onStartInputView中會handle各種IME的event並進一步調用IME自身的onCreate函數,做進一步的初始化以及receiver的rigister。
本文實例講述了Android編程實現讀取手機聯系人、撥號、發送短信及長按菜單操作方法。分享給大家供大家參考,具體如下: 1.Andrid項目結構圖↓主要操作圖中紅
首先先建布局文件,界面很簡單,就是一個搜索框和下面的聯系人列表: 代碼如下: <?xml version=1.0 encoding=utf-8?
JSON代表JavaScript對象符號。它是一個獨立的數據交換格式,是XML的最佳替代品。本章介紹了如何解析JSON文件,並從中提取所需的信息。Android提供了四個
由於最近項目忙,博客一直沒有時間更新,今天有點時間就連續更新兩篇吧,過過瘾。 這篇圖片拖拽縮放也是我在項目中用到的,今天整理一下,將源碼奉獻給大家,希望對大家以後