Android Keyboard 解析过程

可参考XmlResourceParser类对xml标签的解析:

public SoftKeyboard loadKeyboard(int resourceId, int skbWidth, int skbHeight) {
        if (null == mContext) return null;
        Resources r = mResources;
        SkbPool skbPool = SkbPool.getInstance();
        XmlResourceParser xrp = mContext.getResources().getXml(resourceId);
        mSkbTemplate = null;
        SoftKeyboard softKeyboard = null;
        Drawable skbBg;
        Drawable popupBg;
        Drawable balloonBg;
        SoftKey softKey = null;

        KeyCommonAttributes attrDef = new KeyCommonAttributes(xrp);
        KeyCommonAttributes attrSkb = new KeyCommonAttributes(xrp);
        KeyCommonAttributes attrRow = new KeyCommonAttributes(xrp);
        KeyCommonAttributes attrKeys = new KeyCommonAttributes(xrp);
        KeyCommonAttributes attrKey = new KeyCommonAttributes(xrp);

        mKeyXPos = 0;
        mKeyYPos = 0;
        mSkbWidth = skbWidth;
        mSkbHeight = skbHeight;

        try {
            mKeyXMargin = 0;
            mKeyYMargin = 0;
            mXmlEventType = xrp.next();
            while (mXmlEventType != XmlResourceParser.END_DOCUMENT) {
                mNextEventFetched = false;
                if (mXmlEventType == XmlResourceParser.START_TAG) {
                    String attr = xrp.getName();
                    // 1. Is it the root element, "keyboard"?
                    if (XMLTAG_KEYBOARD.compareTo(attr) == 0) {
                        // 1.1 Get the keyboard template id.
                        int skbTemplateId = xrp.getAttributeResourceValue(null,
                                XMLATTR_SKB_TEMPLATE, 0);

                        // 1.2 Try to get the template from pool. If it is not
                        // in, the pool will try to load it.
                        mSkbTemplate = skbPool.getSkbTemplate(skbTemplateId,
                                mContext);

                        if (null == mSkbTemplate
                                || !attrSkb.getAttributes(attrDef)) {
                            return null;
                        }

                        boolean cacheFlag = getBoolean(xrp,
                                XMLATTR_SKB_CACHE_FLAG, DEFAULT_SKB_CACHE_FLAG);
                        boolean stickyFlag = getBoolean(xrp,
                                XMLATTR_SKB_STICKY_FLAG,
                                DEFAULT_SKB_STICKY_FLAG);
                        boolean isQwerty = getBoolean(xrp, XMLATTR_QWERTY,
                                false);
                        boolean isQwertyUpperCase = getBoolean(xrp,
                                XMLATTR_QWERTY_UPPERCASE, false);

                        softKeyboard = new SoftKeyboard(resourceId,
                                mSkbTemplate, mSkbWidth, mSkbHeight);
                        softKeyboard.setFlags(cacheFlag, stickyFlag, isQwerty,
                                isQwertyUpperCase);

                        mKeyXMargin = getFloat(xrp, XMLATTR_KEY_XMARGIN,
                                mSkbTemplate.getXMargin());
                        mKeyYMargin = getFloat(xrp, XMLATTR_KEY_YMARGIN,
                                mSkbTemplate.getYMargin());
                        skbBg = getDrawable(xrp, XMLATTR_SKB_BG, null);
                        popupBg = getDrawable(xrp, XMLATTR_POPUP_BG, null);
                        balloonBg = getDrawable(xrp, XMLATTR_BALLOON_BG, null);
                        if (null != skbBg) {
                            softKeyboard.setSkbBackground(skbBg);
                        }
                        if (null != popupBg) {
                            softKeyboard.setPopupBackground(popupBg);
                        }
                        if (null != balloonBg) {
                            softKeyboard.setKeyBalloonBackground(balloonBg);
                        }
                        softKeyboard.setKeyMargins(mKeyXMargin, mKeyYMargin);
                    } else if (XMLTAG_ROW.compareTo(attr) == 0) {
                        if (!attrRow.getAttributes(attrSkb)) {
                            return null;
                        }
                        // Get the starting positions for the row.
                        mKeyXPos = getFloat(xrp, XMLATTR_START_POS_X, 0);
                        mKeyYPos = getFloat(xrp, XMLATTR_START_POS_Y, mKeyYPos);
                        int rowId = getInteger(xrp, XMLATTR_ROW_ID,
                                KeyRow.ALWAYS_SHOW_ROW_ID);
                        softKeyboard.beginNewRow(rowId, mKeyYPos);
                    } else if (XMLTAG_KEYS.compareTo(attr) == 0) {
                        if (null == softKeyboard) return null;
                        if (!attrKeys.getAttributes(attrRow)) {
                            return null;
                        }

                        String splitter = xrp.getAttributeValue(null,
                                XMLATTR_KEY_SPLITTER);
                        splitter = Pattern.quote(splitter);
                        String labels = xrp.getAttributeValue(null,
                                XMLATTR_KEY_LABELS);
                        String codes = xrp.getAttributeValue(null,
                                XMLATTR_KEY_CODES);
                        if (null == splitter || null == labels) {
                            return null;
                        }
                        String labelArr[] = labels.split(splitter);
                        String codeArr[] = null;
                        if (null != codes) {
                            codeArr = codes.split(splitter);
                            if (labelArr.length != codeArr.length) {
                                return null;
                            }
                        }

                        for (int i = 0; i < labelArr.length; i++) {
                            softKey = new SoftKey();
                            int keyCode = 0;
                            if (null != codeArr) {
                                keyCode = Integer.valueOf(codeArr[i]);
                            }
                            softKey.setKeyAttribute(keyCode, labelArr[i],
                                    attrKeys.repeat, attrKeys.balloon);

                            softKey.setKeyType(mSkbTemplate
                                    .getKeyType(attrKeys.keyType), null, null);

                            float left, right, top, bottom;
                            left = mKeyXPos;

                            right = left + attrKeys.keyWidth;
                            top = mKeyYPos;
                            bottom = top + attrKeys.keyHeight;

                            if (right - left < 2 * mKeyXMargin) return null;
                            if (bottom - top < 2 * mKeyYMargin) return null;

                            softKey.setKeyDimensions(left, top, right, bottom);
                            softKeyboard.addSoftKey(softKey);
                            mKeyXPos = right;
                            if ((int) mKeyXPos * mSkbWidth > mSkbWidth) {
                                return null;
                            }
                        }
                    } else if (XMLTAG_KEY.compareTo(attr) == 0) {
                        if (null == softKeyboard) {
                            return null;
                        }
                        if (!attrKey.getAttributes(attrRow)) {
                            return null;
                        }

                        int keyId = this.getInteger(xrp, XMLATTR_ID, -1);
                        if (keyId >= 0) {
                            softKey = mSkbTemplate.getDefaultKey(keyId);
                        } else {
                            softKey = getSoftKey(xrp, attrKey);
                        }
                        if (null == softKey) return null;

                        // Update the position for next key.
                        mKeyXPos = softKey.mRightF;
                        if ((int) mKeyXPos * mSkbWidth > mSkbWidth) {
                            return null;
                        }
                        // If the current xml event type becomes a starting tag,
                        // it indicates that we have parsed too much to get
                        // toggling states, and we started a new row. In this
                        // case, the row starting position information should
                        // be updated.
                        if (mXmlEventType == XmlResourceParser.START_TAG) {
                            attr = xrp.getName();
                            if (XMLTAG_ROW.compareTo(attr) == 0) {
                                mKeyYPos += attrRow.keyHeight;
                                if ((int) mKeyYPos * mSkbHeight > mSkbHeight) {
                                    return null;
                                }
                            }
                        }
                        softKeyboard.addSoftKey(softKey);
                    }
                } else if (mXmlEventType == XmlResourceParser.END_TAG) {
                    String attr = xrp.getName();
                    if (XMLTAG_ROW.compareTo(attr) == 0) {
                        mKeyYPos += attrRow.keyHeight;
                        if ((int) mKeyYPos * mSkbHeight > mSkbHeight) {
                            return null;
                        }
                    }
                }

                // Get the next tag.
                if (!mNextEventFetched) mXmlEventType = xrp.next();
            }
            xrp.close();
            softKeyboard.setSkbCoreSize(mSkbWidth, mSkbHeight);
            return softKeyboard;
        } catch (XmlPullParserException e) {
            // Log.e(TAG, "Ill-formatted keybaord resource file");
        } catch (IOException e) {
            // Log.e(TAG, "Unable to read keyboard resource file");
        }
        return null;
    }

你可能感兴趣的:(Android)