天天看点

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;

    }