Since SDK 1.5, Android has enabled its IMFInput Method Framework. This allows us to develop our own input methods. The best reference for the development input method is the Sample-SoftKeyboard provided by Android. Although this example only contains English and numbers, it is still complete and clear, it is of great help for us to start Android development.
I,IMF Introduction
An IMF structure contains three main parts:
Input method manager: Manages interactions between different parts. It is a client API that exists in the context of each application and is used to communicate and manage global system services for interaction between all processes.
Input method (IME): implements an independent Interaction module that allows users to generate texts. The system binds the current input method. Create and generate the input method, and decide when to hide or display its UI. Only one IME can run at a time.
Client application: controls the input focus and IME status through the Input Method Manager. Only one client can use IME at a time.
1. InputManager
Is called by UI controls such as View, TextView, and EditText. For example, enable, disable, and switch the input method.
It is the core API of the entire Input Method Framework (IMF) structure to process interactions between applications and the current input method. You can use Context. getSystemService () to obtain an InputMethodManager instance.
In the development process, the most basic and important thing is to develop the habit of reading APIs. A good programmer needs to develop a way to keep himself in a dark room, cut off the Internet and contact with the outside world, rely only on the development environment and API documentation on his computer, and three meals a day from beautiful maids, write Excellent programs. In martial arts novels, this is called "closed customs" and "Clean Room" in software development. Haha.
The Android API documentation is at: % SDK_ROOM %/docs/reference/index.html,
InputManager class location: % SDK_ROOM %/docs/reference/android/view/inputmethod/InputMethodManager.html
This class has little to do with the Sample to be discussed here. Please read the API doc on your own.
2. InputMethodService
Including the internal logic of the input method, keyboard layout, and word selection. Finally, the selected characters are submitted through commitText. The basis for implementing the input method is the class named InputMethodService. For example, if you want to implement a Google input method, it is the extends class. The SoftKeyboard Sample we will learn next is also the extends class. The InputMethodService class is located at: % SDK_ROOM %/docs/reference/android/inputmethodservice/InputMethodService.html
InputMethodService is a complete implementation of InputMethod. You can expand and customize it based on it. The main method is as follows:
◆ OnInitializeInterface (), as its name implies, is called during interface initialization. Generally, this function is executed due to configuration file changes.
◆ OnBinndInput () is called when another client connects to the input method.
◆ OnStartInput () is a very important callback, which is called when the user has started to input in the editing box. For example, when you click an input box, you need to set some features of the input method based on the information in the input box. This is very useful in the Sample.
◆ OnCreateInputView () returns a hierarchical input view, which is called only when the view is displayed for the first time.
◆ OnCreateCandidatesView () is the same as onCreateInputView (), but the view of the candidate box is created.
◆ OnCreateExtractTextView () is a special view in full screen mode.
◆ OnStartInputView () is called when the input view is displayed and a start is input in a new input box.
Basically, the custom input method is implemented around this class. It mainly provides a basic user interface framework, including the input view, candidate word view, and full screen mode ), but these are all customized by the implementers themselves. The implementation here is to place all elements in a Single Window managed by InputMethodService. It provides many callback APIs that need to be implemented by ourselves. Some default settings include:
◆ Soft keyboard input view, which is usually placed below the screen.
◆ Candidate word view, which is usually placed on the input view.
◆ When we enter this information, we need to change the application interface to adapt to the placement rules of these views. For example, if you enter it on Android, the editing box will automatically change to a position on the keyboard.
Two very important views:
1. Soft input view. Is the main place of interaction with users: buttons, drawing, or other methods. The general implementation is to simply use a view to process all the work, and return a new instance when onCreateInputView () is called. The system calls onEvaluateInputViewShow () to test whether the input view needs to be displayed. It is implemented by the system based on the current context. When the input method status changes, you need to call updateInputViewShown () to re-estimate it.
2. Candidate word view. After a user inputs some characters, the input method may be provided to the user with a list of available candidate words. The management of this view is not the same as that of the input view, because it is very short-lived and will only be displayed when there are candidate words. You can use setCandidatesViewShow () to set whether to display this view. It is precisely because of the frequency of display that it will not be destroyed and will not change the view of the current application.
Finally, the generation of text is the ultimate goal of IME. It uses InputConnection to link IME and applications: it can directly generate desired key information, and even directly edit it in candidate and submitted text. When you switch between different input targets, IME will continuously call onFinishInput () and onStartInput (). In these two functions, the reset status should be repeated and the information of the new input box should be responded.
The above is the most basic introduction of an input method. The following describes these problems based on the SoftKeyboard in the Sample.
II,Create an Eclipse project
Here, the SoftKeyboard Sample in Android SDK 2.3.3 of the latest version is used to create a project. In fact, this Sample already exists in Android SDK 1.5. At the same time, because SoftKeyboard can be misunderstood as a subclass of KeyBoard, it is particularly renamed as InputMethodServiceSample, which is more in line with its functions and features.
Click Finish to create the project. The project structure is as follows:
Run this Sample on Android SDK 2.3.3 simulator. You must select this Sample in Setting and select the name of this Sample in Language & keyboard.
When you try to select the Sample Soft Keyboard, a security prompt is displayed for Android. IME does have to choose what you trust, because it can collect and record all your input. It will be terrible if it is used by people who are interested.
After selecting the Sample Soft Keyboard as our input method, enter the place where the input method is required. Here, we use the text message interface as an example. In the input box, press the button and the "edit text" menu appears, click "Input Method" to enter the input method selection box on the current input interface. You can use the input method to switch to this input method to view its keyboard.
Then we can see the Soft keyboard as follows:
III,Configuration and resource File Parsing
In addition to the source code, which will be analyzed in the later section, we will introduce the configuration and resource files.
1. AndroidMainifest. xml
Each Android Application has a configuration description file. Here, Sample declares itself as a service and binds it to the input method. Its intent-filter is a direct InputMethod interface, which is also an interface for all input methods.
2. res directory
Place the resource, that is, the resource file, which contains many things, as shown below.
(1) The drawable directory contains the icon file.
(2) The values directory contains strings. xml and some xml files of custom types and values.
Strings. xml
-Ime_name defines the name of the input method.
-Word_separators is a Separator Used to indicate the characters completed by a word input, such as spaces and punctuations)
-Label_xx_key is the tag that defines the validation key for the soft keyboard. In the code parsing, you can see that the Program sets the EnterKey icon or tag based on the information in the input box. For example, if you enter a URL, a search icon is displayed. When you edit a text message, if you write it to the recipient, EnterKey is the Next tag, which is used to directly jump to the text message body.
Dimens. xml defines the size information of the soft keyboard, including the key_height, candidate_font_height, and candidate_vertical_padding ).
Color. xml defines the background color of candidate words, such as normal (candidate_normal), recommended (candidate_recommended), background (candidate_background), and other (candidate_other) colors.
(3) layout directory to save the layout configuration file. There is only one configuration file: input. xml, which defines the information of the input view, including id (android: id = "@ + id/keyboard"), placed at the bottom of the screen (android: layout_alignParentBottom = "true"), horizontal maximum filling (android: layout_width = "match_parent"), vertical containing sub-content (android: layout_height = "wrap_content ").
(4) xml directory. The file is as follows:
Method. xml, which provides configuration information for search management.
Qwerty. xml: a keyboard layout file with English characters. The definition is intuitive and easy to understand.
Symbols_shift.xml and symbols. xml are all keyboard layout files for punctuation characters.
IV,Source code parsing
1)Overview
From the InputMethodServiceSample project, we can see that the implementation of an input method requires at least four files: CandidateView, LatinKeyboard, LatinKeyboardView, and SoftKeyboard:
◆ CandidateView is responsible for displaying the candidate area on the keyboard.
◆ LatinKeyboard parses and saves the keyboard layout, and provides word selection algorithms for running programs. The keyboard layout is stored in the resource as an XML file. For example, in the Chinese Character Input Method, press B and. LatinKeyboard is responsible for converting the two letters into "dad", "ba" and "ba" and displaying them on CandidateView.
◆ LatinKeyboardView displays the buttons we see. It is combined with CandidateView to form an InputView, which is the soft keyboard we see.
◆ SoftKeyboard inherits InputMethodService. to start an input method, it actually starts an InputMethodService. When the SoftKeyboard input method is used, the SoftKeyboard Service is started.
2)LatinKeyboard. java
The soft Keyboard class directly inherits the Keyboard class and defines the layout of a Keyboard in xml format to implement a Keyboard that inputs the Latin. Here we only create a keyboard object and do not provide a method for the specific layout.
To better understand the LatinKeyboard class, we will briefly introduce the Keyboard class. The Keyboard can load an xml file used to display the Keyboard layout to initialize itself and save the key attributes of these keyboards. He has three constructors:
◆ Keyboard (Context context, int xmlLayoutResId), which is created by indexing xml files with Context and xml resource id.
◆ Keyboard (Context context, int xmlLayoutResId, int modeId), which is similar to the above, but only has a modeld.
◆ Keyboard (Context context, int layoutTemplateResId, CharSequence characters, int columns, int horizontalPadding). This is complicated. Use an empty xml layout template to create a Keyboard, then fill the template with the specified characters from left to right and from top to bottom.
The source code of this file fully inherits the keyboard and uses the parent class constructor for initialization.
Here, because createKeyFromXml (Resources res, Row parent, int x, int y, XmlResourceParser parser) of the Keyboard class is overwritten, to return a Key object, simply create a LatinKey object. Here we can see the requirements of object-oriented and framework.
Next, this file reloads A createKeyFromXml function, which is a callback function called when the keyboard depicts the key and loads a key from an xml resource file, and placed at the coordinates of (x, y. It also determines whether the key is a return key and saves it. Here, to return a Key object, you can directly create the LatinKey object of the internal class. Here we can see the requirements of object-oriented and framework.
In addition, setImeOptions is used to set appropriate labels for the keyboard's return key based on the current information in the editing box. If the input box is different, a label or icon with different enter keys will be generated. In this function, some imeOption bit information is used, such as IME_MASK_ACTION. It is mainly used to view the EditorInfo Action information, which includes:
◆ IME_ACTION_GO: The action that brings the user to the target of the input box. The validation key will not have icons, only the label: GO
◆ IME_ACTION_NEXT: next operation, which brings the user into the text box to write an input box. For example, when editing a short message, the content is the next text field in the recipient's mobile phone number box. It is just a NEXT label.
◆ IME_ACTION_SEARCH: search operation. The default action is search. For example, when you enter an image in the URL box, the search operation is performed by default. It provides an icon like a magnifier.
◆ IME-ACTION_SEND: send operation, the default action is to send the current content. For example, when a short message is entered in the content box, a sending operation is usually followed. It also provides only one Label: SEND
◆ DEFAULT: by DEFAULT, the text box does not have any special requirements, so you only need to set the return icon.
Finally, it defines an internal class-LatinKey, which directly inherits the Key to define a separate Key. Its unique function to be overloaded is isInside (int x, int y ), used to determine whether a coordinate is within the key. It reloads to determine whether the key is a CANCEL key. If yes, it reduces the Y coordinate by 10 PX. According to his explanation, it is used to restore the target area of the key that can turn off the keyboard.
3)LatinKeyboardView. java
Here is a View, which naturally inherits from the View. Because the keyboard created earlier is just a concept and cannot be used to create a UI, you need to use a VIEW class for rendering. This class simply inherits the KeyboardView class and then reloads an action method called onLongPress.
It is called when a key event occurs for a long time. First, it determines whether the key is a CANCEL key. If yes, it calls the OnKeyboardActionListener object that has been placed in KeyboardView, send an event to the keyboard for which the OPTIONS key is pressed. It is the key used to block the CANCEL key and then send an unknown code.
4)CandidateView. java
CandidateView is a candidate word display view. It provides a candidate word selection View that can be directly inherited from the view class. When we enter a character, it should be able to display certain prompts according to the character, such as pinyin homophone, Lenovo word, and so on.
1. First, it defines the important variables:
◆ MService: the host class of candidateView, that is, why the view is input service.
◆ MSuggestions: recommended. For example, when we enter some letters, the input method is recommended based on input.
◆ MSelectedIndex: Index of the selected words.
◆ MSelectionHighlight: depicts the class highlighted in the selected area.
◆ MTypedWordValid: indicates whether the entered word is valid or not.
◆ MBgPadding: Fill the background area.
◆ MWordWidth: the width of each candidate word.
◆ MWordX: X coordinate of each candidate word. With these two variables, the candidate key can be accurately drawn on the screen.
◆ MColor *: various colors are defined.
◆ MPaint: A drawing class, which will be used later
◆ MVerticalPadding: vertical filling area.
◆ MTargetScrollX: the horizontal coordinate of the target rolling, that is, the target to be rolled.
◆ MTotalWidth: Total Width
◆ MGestureDetector: declares a gesture monitor.
The GestureDetector object is rare. Let's take a look at android. view. GestureDetector. This is a class related to action events and can be used to detect various action events. It is called a gesture monitor. Its callback function is GestureDetector. OnGestureListener, which is executed when an action occurs and can only be triggered when it is touched. It is invalid to use a scroll ball. To use this feature, you must first create an object, as shown in the code, and then set GestureDetector. OnGestureListener to write the code to be executed when an action occurs in onTouchEvent (MotionEvent.
2. constructor mainly initializes some variables.
First, mSelectionHighlight is initialized. This is a drawable object, and the initial state of this drawable is set using the setState method of drawable. Add a color under the res directory. the xml file defines all the color resources used, and then uses the R index. These resources can be added to their own R. java content can be directly referenced. The remaining content is the initialization background. The background color of the selected or unselected view is defined in color. xml. In this way:
Resources r = context. getResources ();
Method to obtain the current resource object.
SetBackgroundColor (r. getColor (R. color. candidate_background ));
Then a gesturedetector is initialized, and its Listener reloads a method called onScroll, which is triggered when the gesture detector finds a scroll action. In this function, we mainly judge sliding.
The following methods are used in the view: getScrollX (); getWidth (); scrollTo (sx, getScrollY (); invalidate:
◆ GetScrollX (): obtains the abscissa of the view after scrolling.
◆ ScrollTo (): scroll to the target coordinate
◆ GetScrollY (): obtains the ordinate of the view after scrolling.
◆ Invalidate (): redraw a view
Here, distanceX is the X-axis distance for rolling after onscroll is called last time. If the view has not been rolled before, and the coordinates are in the display area for the first time, sx = getScrollX () + distanceX, the view is scrollTo. If sx exceeds the maximum display width, scrollTo will roll back to the original sx, that is, not moving. That is to say: the system rolling produces a feeling of inertia. When you place the view into X coordinate points, the system adds distanceX to you. This distanceX is not the distance between two actions, it should be the distance between the stop point of the previous rolling action and the stop point of the current rolling action. This distance is calculated by the system. We don't have to worry about it. As long as it reaches the maximum boundary, the view will not scroll, or in-situ scrolling.
Next:
◆ SetHorizontalFadingEdgeEnabled (true); // sets whether the horizontal side fades out when the view is horizontally scrolling.
◆ SetWillNotDraw (false); // The view does not draw itself
◆ SetHorizontalScrollBarEnabled (false); // The horizontal scroll bar is not set.
◆ SetVerticalScrollBarEnabled (false); // do not set the vertical scroll bar
3. setService is used to set the host input method.
4. computeHorizontalScrollRange indicates the horizontal rolling area of the view, and the overall width of the candidate view is returned.
5. onMeasure: overload the self-view class, which is called by the parent view in the layout stage. For example, if the parent view needs to be laid out based on the size of its child views, you need to call back this function to view the size of the view. When calling this function, you must call setMeasureDimension internally to save the width and height. Otherwise, an exception will occur. Here, we reload it to check the size of the character area to be drawn. Because the font may have a size, it should be based on the font. It calculates its expected width, calls resolveSize to see if it can get a 50px width, and then calculates the desired height based on the font and the padding of the display prompt area.
6. onDraw, the main function of view. Each view must be rewritten to draw its own. It provides a canvas. If it is empty, it calls the parent class to draw the canvas directly.
The internal logic here is roughly as follows:
Determine whether a candidate word exists. If no candidate word exists, you do not need to draw it.
Initialize the filling Area of the background. You can directly view the background.
For each candidate word, obtain its text, calculate its width, and then add gaps on both sides.
Determine whether the current word is selected: The touch Position + the scroll position. If it is between the left and right of the current word, the highlighted area is drawn on the canvas. The size of the highlighted area is the size of the current word, and the selected word index is saved.
Draw the text on the canvas of the candidate word, and make a judgment to determine which word is the recommendation word. By default, it is the first word of a candidate word, but it determines whether the first word is valid. If yes, the first word is a candidate word, otherwise, the second word is the rough candidate, and then draw.
Draw a line to separate candidate words. The total width mentioned above can be obtained after all words are drawn.
To determine whether the target rolling is current, You Need To scroll over if not.
7. scrollToTarget: Roll to the target area. Get the current value, and add a rolling distance to check whether the value exceeds and adjust it accordingly. Then, scroll to the corresponding coordinates.
8. setSuggestions: Set candidate words and draw them later.
9. onTouchEvent, called when a touch event is generated. First, determine whether it is a gesturedetector listening action. If not, perform the following processing. Initialize the action, record the action, and record the coordinate of the vertex. Then, the response is classified based on the action type:
◆ Downward: no action;
◆ Move: to move left, you must manually select candidate words;
◆ Up: You need to manually select candidate words.
10. Select the word at the coordinate x in takeSuggestionAt. The processing is that the user clicks the keyboard gently, that is, the candidate word is selected.
11. removeHighlight to remove the highlighted display.
5)SoftKeyboard. java
The overall framework of the input method, including when to create, when to display the input method, and how to communicate with the text box. The above files are for this class of service. In general, an input method requires an input view, a candidate word view, and a link to the application.
The basic sequence diagram is as follows:
The input method is essentially a Service in Android. If you have just started Android, Android notifies the Service to start initialization when the user's mobile focus enters the text editing box for the first time. So we have a series of actions.
The onCreate method inherits from the Service class, which is the same as that of other services. Here, some non-UI Initialization is made, that is, the initialization of the string variable vocabulary separator.
Next, run onInitializeInterface, where the UI is initialized. This method will be called after creation and after Configuration modification. The Keyboard is initialized here. The Keyboard information is read from the XML file and encapsulated into the Keyboard object.
The third execution is the onStartInput method. Here, we are bound to the client to receive all the details about the edited object.
The fourth method is onCreateInputView. When the area you enter is to be displayed, this method is called by the Framework. When the input method is displayed for the first time or the configuration information is changed, this method will be executed. In this method, inputview is initialized: Read layout file information, set onKeyboardActionListener, and set keyboard initially.
The fifth method is onCreateCandidatesView, which is called by the Framework to display the view of candidate words. Similar to onCreateInputView. In this method, candidateview is initialized.
The sixth and last method, onStartInputView, re-associates inputview with the current keyboard.
In the preceding six methods, the onCreateInputView and onCreateCandidatesView methods are executed only once during initialization, unless the configuration information is changed. So what exactly is the configuration information changed? When you read the InputMethodService API documentation, you can see that there is a method onConfigurationChanged. According to the documentation, this method is mainly responsible for configuration changes. In the example, there is no override method, but this method is used in PinyinIME In the android source code package. If you are interested, you can check the source code of PinyinIME after reading the SoftKeyboard Sample.
Some other methods in this class are not explained because they are intuitive. If you are interested, refer to "parsing softkeyboard in android sdk (4)".
V,Input Method debugging
By adding breakpoints in the debugging mode, we can better understand the time sequence of the input method and the function and call duration of each class and its methods.
The DDMS perspective of Eclipse is used for debugging. For details, see develop and debug Android applications with Eclipse.
Switch to the DDMS mode. In this mode, DDMS is linked to a running mobile phone or simulator, and can extract various information on the mobile phone, such as threads, there are also various services running in the background. Click "Debug selected Process" on the toolbar to implant the debugger into this service.
After switching to the debug mode, you will find that the debugger has been linked to this simulator, and then you can debug this input method just like debugging a common program.
In the debug mode, we can find that the onCreateInputView> onCreateCandidatesView executed by the input method is not displayed yet. When we click the mouse in an input box, the system generates an event, which is first captured by the input method, and then the control is handed over to the input method. In addition, when switching an object, the input method is always regarded as an end of an input and then performs a series of reset operations. All keyboard and other events are first transmitted to the input method. Therefore, if a key event is not a problem that we can solve, we need to continue to pass the event, rather than discard it, this may be a task of other controls.
On the message sending interface, after entering a message TO someone, click the content input box. The onFinishInput is called first, that is, the last input is completed. OnStartInputView is called to display the interface. Call onStartInput to start the formal input. In this process, you need to select different keyboards based on different input boxes. when you enter a key, the onKey callback is triggered first. Here, you need to determine that it is a common character, or control characters, such as deletion and return. For example, enter a 'G' here and then call the handleCharacter function that processes common characters. The policy here is to enter a common character, add Composing, and update the list of candidate words. There is a very subtle switch, namely, mPrediction, which is to determine whether the Composing needs to be saved. For example, when you enter the URL box, this switch is set to off and the input is directly entered in the text box.
To test all functions, you must come up with an input method that allows you to execute each function. Then you can see the original face of the input method.
Please try it on your own. It is helpful to read and understand the source code process, timing, and lifecycle. You can also easily find bugs in your own code.
VI,Call of Input Method
You can call the EditText widget to call the input method and receive the string passed by the input method from a View. However, if you want to make a very elegant and personalized input method, you must connect the input method like EditText. The introduction is as follows:
First, define a class inherited from BaseInputConnection. As mentioned above, the input method uses commitText to submit selected characters.
- Public class MyBaseInputConnection extends BaseInputConnection {
-
- Public MyBaseInputConnection (View targetView, boolean fullEditor ){
-
- Super (targetView, fullEditor );
-
- }
-
- Public static String tx = "";
-
- // The input method program outputs the final result by calling this method.
-
- @ Override
-
- Public boolean commitText (CharSequence text, int newCursorPosition ){
-
- Tx = text. toString ();
-
- Return true;
-
- }
-
- }
BaseInputConnection is equivalent to a channel between InputMethodService and View. Whenever InputMethodService generates a result, it will call the commitText method of BaseInputConnection to pass the result.
Then, use the following method to input the outbound call method and pass the custom BaseInputConnection channel to InputMethodService.
- Public class MyView extends XXView ...{
-
- // Obtain InputMethodManager
-
- InputMethodManager input = (InputMethodManager) context. getSystemService (Context. INPUT_METHOD_SERVICE );
-
- // Define the event Processor
-
- ResultReceiver receiver ER = new ResultReceiver (new Handler (){
-
- Public void handleMessage (Message msg ){
-
- }
-
- });
-
- ...
-
- // Call this sentence when you want to call out the Input Method
-
- Input. showSoftInput (this, 0, mRR );
-
- ...
-
- @ Override
-
- // This method is inherited from View. Pass the custom BaseInputConnection channel to InputMethodService
-
- Public InputConnection onCreateInputConnection (EditorInfo outAttrs ){
-
- Return new MyBaseInputConnection (this, false );
-
- }
-
- }
On the low-level interface, you can call the input method and receive the output result of the input method.