private void parseIncludeInternal( final XmlPullParser parser, final KeyboardRow row, final boolean skip) throws XmlPullParserException, IOException { if (skip) { XmlParseUtils.checkEndTag(TAG_INCLUDE, parser); if (DEBUG) startEndTag("</%s> skipped", TAG_INCLUDE); return; } final AttributeSet attr = Xml.asAttributeSet(parser); final TypedArray keyboardAttr = mResources.obtainAttributes(attr, R.styleable.Keyboard_Include); final TypedArray keyAttr = mResources.obtainAttributes(attr, R.styleable.Keyboard_Key); int keyboardLayout = 0; try { XmlParseUtils.checkAttributeExists( keyboardAttr, R.styleable.Keyboard_Include_keyboardLayout, "keyboardLayout", TAG_INCLUDE, parser); keyboardLayout = keyboardAttr.getResourceId(R.styleable.Keyboard_Include_keyboardLayout, 0); if (row != null) { // Override current x coordinate. row.setXPos(row.getKeyX(keyAttr)); // Push current Row attributes and update with new attributes. row.pushRowAttributes(keyAttr); } } finally { keyboardAttr.recycle(); keyAttr.recycle(); } XmlParseUtils.checkEndTag(TAG_INCLUDE, parser); if (DEBUG) { startEndTag( "<%s keyboardLayout=%s />", TAG_INCLUDE, mResources.getResourceEntryName(keyboardLayout)); } final XmlResourceParser parserForInclude = mResources.getXml(keyboardLayout); try { parseMerge(parserForInclude, row, skip); } finally { if (row != null) { // Restore Row attributes. row.popRowAttributes(); } parserForInclude.close(); } }
private void parseGridRows(final XmlPullParser parser, final boolean skip) throws XmlPullParserException, IOException { if (skip) { XmlParseUtils.checkEndTag(TAG_GRID_ROWS, parser); if (DEBUG) { startEndTag("<%s /> skipped", TAG_GRID_ROWS); } return; } final KeyboardRow gridRows = new KeyboardRow(mResources, mParams, parser, mCurrentY); final TypedArray gridRowAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.Keyboard_GridRows); final int codesArrayId = gridRowAttr.getResourceId(R.styleable.Keyboard_GridRows_codesArray, 0); final int textsArrayId = gridRowAttr.getResourceId(R.styleable.Keyboard_GridRows_textsArray, 0); gridRowAttr.recycle(); if (codesArrayId == 0 && textsArrayId == 0) { throw new XmlParseUtils.ParseException("Missing codesArray or textsArray attributes", parser); } if (codesArrayId != 0 && textsArrayId != 0) { throw new XmlParseUtils.ParseException( "Both codesArray and textsArray attributes specifed", parser); } final String[] array = mResources.getStringArray(codesArrayId != 0 ? codesArrayId : textsArrayId); final int counts = array.length; final float keyWidth = gridRows.getKeyWidth(null, 0.0f); final int numColumns = (int) (mParams.mOccupiedWidth / keyWidth); for (int index = 0; index < counts; index += numColumns) { final KeyboardRow row = new KeyboardRow(mResources, mParams, parser, mCurrentY); startRow(row); for (int c = 0; c < numColumns; c++) { final int i = index + c; if (i >= counts) { break; } final String label; final int code; final String outputText; final int supportedMinSdkVersion; if (codesArrayId != 0) { final String codeArraySpec = array[i]; label = CodesArrayParser.parseLabel(codeArraySpec); code = CodesArrayParser.parseCode(codeArraySpec); outputText = CodesArrayParser.parseOutputText(codeArraySpec); supportedMinSdkVersion = CodesArrayParser.getMinSupportSdkVersion(codeArraySpec); } else { final String textArraySpec = array[i]; // TODO: Utilize KeySpecParser or write more generic TextsArrayParser. label = textArraySpec; code = Constants.CODE_OUTPUT_TEXT; outputText = textArraySpec + (char) Constants.CODE_SPACE; supportedMinSdkVersion = 0; } if (Build.VERSION.SDK_INT < supportedMinSdkVersion) { continue; } final int x = (int) row.getKeyX(null); final int y = row.getKeyY(); final Key key = new Key( mParams, label, null /* hintLabel */, 0 /* iconId */, code, outputText, x, y, (int) keyWidth, (int) row.getRowHeight(), row.getDefaultKeyLabelFlags(), row.getDefaultBackgroundType()); endKey(key); row.advanceXPos(keyWidth); } endRow(row); } XmlParseUtils.checkEndTag(TAG_GRID_ROWS, parser); }