下面列出了android.util.Xml#asAttributeSet ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private KeyboardRow parseRowAttributes(final XmlPullParser parser)
throws XmlPullParserException {
final AttributeSet attr = Xml.asAttributeSet(parser);
final TypedArray keyboardAttr = mResources.obtainAttributes(attr, R.styleable.Keyboard);
try {
if (keyboardAttr.hasValue(R.styleable.Keyboard_horizontalGap)) {
throw new XmlParseUtils.IllegalAttribute(parser, TAG_ROW, "horizontalGap");
}
if (keyboardAttr.hasValue(R.styleable.Keyboard_verticalGap)) {
throw new XmlParseUtils.IllegalAttribute(parser, TAG_ROW, "verticalGap");
}
return new KeyboardRow(mResources, mParams, parser, mCurrentY);
} finally {
keyboardAttr.recycle();
}
}
/** @hide */
static VectorDrawable create(Resources resources, int rid) {
android.util.Log.i("SupportVectorDrawable", resources.getResourceEntryName(rid));
try {
final XmlPullParser parser = resources.getXml(rid);
final AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
while ((type=parser.next()) != XmlPullParser.START_TAG &&
type != XmlPullParser.END_DOCUMENT) {
// Empty loop
}
if (type != XmlPullParser.START_TAG) {
throw new XmlPullParserException("No start tag found");
}
final VectorDrawable drawable = new VectorDrawable();
drawable.mResourceName = resources.getResourceEntryName(rid);
drawable.inflate(resources, parser, attrs);
return drawable;
} catch (XmlPullParserException | IOException e) {
Log.e(LOGTAG, "parser error", e);
}
return null;
}
private KeyboardRow parseRowAttributes(final XmlPullParser parser)
throws XmlPullParserException {
final AttributeSet attr = Xml.asAttributeSet(parser);
final TypedArray keyboardAttr = mResources.obtainAttributes(attr, R.styleable.Keyboard);
try {
if (keyboardAttr.hasValue(R.styleable.Keyboard_horizontalGap)) {
throw new XmlParseUtils.IllegalAttribute(parser, TAG_ROW, "horizontalGap");
}
if (keyboardAttr.hasValue(R.styleable.Keyboard_verticalGap)) {
throw new XmlParseUtils.IllegalAttribute(parser, TAG_ROW, "verticalGap");
}
return new KeyboardRow(mResources, mParams, parser, mCurrentY);
} finally {
keyboardAttr.recycle();
}
}
private void parseKeyStyle(final XmlPullParser parser, final boolean skip)
throws XmlPullParserException, IOException {
final AttributeSet attr = Xml.asAttributeSet(parser);
final TypedArray keyStyleAttr = mResources.obtainAttributes(
attr, R.styleable.Keyboard_KeyStyle);
final TypedArray keyAttrs = mResources.obtainAttributes(attr, R.styleable.Keyboard_Key);
try {
if (!keyStyleAttr.hasValue(R.styleable.Keyboard_KeyStyle_styleName)) {
throw new XmlParseUtils.ParseException("<" + TAG_KEY_STYLE
+ "/> needs styleName attribute", parser);
}
if (DEBUG) {
startEndTag("<%s styleName=%s />%s", TAG_KEY_STYLE,
keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_styleName),
skip ? " skipped" : "");
}
if (!skip) {
mParams.mKeyStyles.parseKeyStyleAttributes(keyStyleAttr, keyAttrs, parser);
}
} finally {
keyStyleAttr.recycle();
keyAttrs.recycle();
}
XmlParseUtils.checkEndTag(TAG_KEY_STYLE, parser);
}
/**
* A public method to create GradientColor from a XML resource.
*/
public static GradientColor createFromXml(Resources r, XmlResourceParser parser, Theme theme)
throws XmlPullParserException, IOException {
final AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
// Seek parser to start tag.
}
if (type != XmlPullParser.START_TAG) {
throw new XmlPullParserException("No start tag found");
}
return createFromXmlInner(r, parser, attrs, theme);
}
private KeyboardRow parseRowAttributes(final XmlPullParser parser)
throws XmlPullParserException {
final AttributeSet attr = Xml.asAttributeSet(parser);
final TypedArray keyboardAttr = mResources.obtainAttributes(attr, R.styleable.Keyboard);
try {
if (keyboardAttr.hasValue(R.styleable.Keyboard_horizontalGap)) {
throw new XmlParseUtils.IllegalAttribute(parser, TAG_ROW, "horizontalGap");
}
if (keyboardAttr.hasValue(R.styleable.Keyboard_verticalGap)) {
throw new XmlParseUtils.IllegalAttribute(parser, TAG_ROW, "verticalGap");
}
return new KeyboardRow(mResources, mParams, parser, mCurrentY);
} finally {
keyboardAttr.recycle();
}
}
public void inflateMenu(@MenuRes int menuRes) {
if(menuRes == 0) return;
if (isInEditMode()) return;
getActivity().getMenuInflater().inflate(menuRes, mActionMenu.getMenu());
XmlResourceParser parser = null;
try {
//noinspection ResourceType
parser = getResources().getLayout(menuRes);
AttributeSet attrs = Xml.asAttributeSet(parser);
parseMenu(parser, attrs);
} catch (XmlPullParserException | IOException e) {
// should not happens
throw new InflateException("Error parsing menu XML", e);
} finally {
if (parser != null) parser.close();
}
}
/**
* Create a drawable from an XML document using an optional {@link Resources.Theme}.
* For more information on how to create resources in XML, see
* <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
*/
public static Drawable createFromXml(Resources r, XmlPullParser parser, Resources.Theme theme) throws XmlPullParserException, IOException {
AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) {
// Empty loop
}
if (type != XmlPullParser.START_TAG) {
throw new XmlPullParserException("No start tag found");
}
Drawable drawable = createFromXmlInner(r, parser, attrs, theme);
if (drawable == null) {
throw new RuntimeException("Unknown initial tag: " + parser.getName());
}
return drawable;
}
private RestrictionEntry loadRestrictionElement(Context appContext, XmlResourceParser xml)
throws IOException, XmlPullParserException {
if (xml.getName().equals(TAG_RESTRICTION)) {
AttributeSet attrSet = Xml.asAttributeSet(xml);
if (attrSet != null) {
TypedArray a = appContext.obtainStyledAttributes(attrSet,
com.android.internal.R.styleable.RestrictionEntry);
return loadRestriction(appContext, a, xml);
}
}
return null;
}
/**
* Inflate a NavGraph from the given XML resource id.
*
* @param graphResId
* @return
*/
@SuppressLint("ResourceType")
@NonNull
public NavGraph inflate(@NavigationRes int graphResId) {
Resources res = mContext.getResources();
XmlResourceParser parser = res.getXml(graphResId);
final AttributeSet attrs = Xml.asAttributeSet(parser);
try {
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
// Empty loop
}
if (type != XmlPullParser.START_TAG) {
throw new XmlPullParserException("No start tag found");
}
String rootElement = parser.getName();
NavDestination destination = inflate(res, parser, attrs);
if (!(destination instanceof NavGraph)) {
throw new IllegalArgumentException("Root element <" + rootElement + ">"
+ " did not inflate into a NavGraph");
}
return (NavGraph) destination;
} catch (Exception e) {
throw new RuntimeException("Exception inflating "
+ res.getResourceName(graphResId) + " line "
+ parser.getLineNumber(), e);
} finally {
parser.close();
}
}
private static Interpolator createInterpolatorFromXml(Resources res, Theme theme, XmlPullParser parser)
throws XmlPullParserException, IOException {
BaseInterpolator interpolator = null;
// Make sure we are on a start tag.
int type;
int depth = parser.getDepth();
while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
&& type != XmlPullParser.END_DOCUMENT) {
if (type != XmlPullParser.START_TAG) {
continue;
}
AttributeSet attrs = Xml.asAttributeSet(parser);
String name = parser.getName();
if (name.equals("linearInterpolator")) {
interpolator = new LinearInterpolator();
} else if (name.equals("accelerateInterpolator")) {
interpolator = new AccelerateInterpolator(res, theme, attrs);
} else if (name.equals("decelerateInterpolator")) {
interpolator = new DecelerateInterpolator(res, theme, attrs);
} else if (name.equals("accelerateDecelerateInterpolator")) {
interpolator = new AccelerateDecelerateInterpolator();
} else if (name.equals("cycleInterpolator")) {
interpolator = new CycleInterpolator(res, theme, attrs);
} else if (name.equals("anticipateInterpolator")) {
interpolator = new AnticipateInterpolator(res, theme, attrs);
} else if (name.equals("overshootInterpolator")) {
interpolator = new OvershootInterpolator(res, theme, attrs);
} else if (name.equals("anticipateOvershootInterpolator")) {
interpolator = new AnticipateOvershootInterpolator(res, theme, attrs);
} else if (name.equals("bounceInterpolator")) {
interpolator = new BounceInterpolator();
} else if (name.equals("pathInterpolator")) {
interpolator = new PathInterpolator(res, theme, attrs);
} else {
throw new RuntimeException("Unknown interpolator name: " + parser.getName());
}
}
return interpolator;
}
/**
* Constructor.
*
* @param context The Context in which we are parsing the device admin.
* @param activityInfo The ActivityInfo returned from the package manager about
* this device admin's component.
*
* @hide
*/
public DeviceAdminInfo(Context context, ActivityInfo activityInfo)
throws XmlPullParserException, IOException {
mActivityInfo = activityInfo;
PackageManager pm = context.getPackageManager();
XmlResourceParser parser = null;
try {
parser = mActivityInfo.loadXmlMetaData(pm, DeviceAdminReceiver.DEVICE_ADMIN_META_DATA);
if (parser == null) {
throw new XmlPullParserException("No "
+ DeviceAdminReceiver.DEVICE_ADMIN_META_DATA + " meta-data");
}
Resources res = pm.getResourcesForApplication(mActivityInfo.applicationInfo);
AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& type != XmlPullParser.START_TAG) {
}
String nodeName = parser.getName();
if (!"device-admin".equals(nodeName)) {
throw new XmlPullParserException(
"Meta-data does not start with device-admin tag");
}
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.DeviceAdmin);
mVisible = sa.getBoolean(
com.android.internal.R.styleable.DeviceAdmin_visible, true);
sa.recycle();
int outerDepth = parser.getDepth();
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tagName = parser.getName();
if (tagName.equals("uses-policies")) {
int innerDepth = parser.getDepth();
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String policyName = parser.getName();
Integer val = sKnownPolicies.get(policyName);
if (val != null) {
mUsesPolicies |= 1 << val.intValue();
} else {
Log.w(TAG, "Unknown tag under uses-policies of "
+ getComponent() + ": " + policyName);
}
}
} else if (tagName.equals("support-transfer-ownership")) {
if (parser.next() != XmlPullParser.END_TAG) {
throw new XmlPullParserException(
"support-transfer-ownership tag must be empty.");
}
mSupportsTransferOwnership = true;
}
}
} catch (NameNotFoundException e) {
throw new XmlPullParserException(
"Unable to create context for: " + mActivityInfo.packageName);
} finally {
if (parser != null) parser.close();
}
}
/**
* Constructor.
*
* @param context The Context in which we are parsing the wallpaper.
* @param service The ResolveInfo returned from the package manager about
* this wallpaper's component.
*/
public WallpaperInfo(Context context, ResolveInfo service)
throws XmlPullParserException, IOException {
mService = service;
ServiceInfo si = service.serviceInfo;
final PackageManager pm = context.getPackageManager();
XmlResourceParser parser = null;
try {
parser = si.loadXmlMetaData(pm, WallpaperService.SERVICE_META_DATA);
if (parser == null) {
throw new XmlPullParserException("No "
+ WallpaperService.SERVICE_META_DATA + " meta-data");
}
Resources res = pm.getResourcesForApplication(si.applicationInfo);
AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& type != XmlPullParser.START_TAG) {
}
String nodeName = parser.getName();
if (!"wallpaper".equals(nodeName)) {
throw new XmlPullParserException(
"Meta-data does not start with wallpaper tag");
}
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.Wallpaper);
mSettingsActivityName = sa.getString(
com.android.internal.R.styleable.Wallpaper_settingsActivity);
mThumbnailResource = sa.getResourceId(
com.android.internal.R.styleable.Wallpaper_thumbnail,
-1);
mAuthorResource = sa.getResourceId(
com.android.internal.R.styleable.Wallpaper_author,
-1);
mDescriptionResource = sa.getResourceId(
com.android.internal.R.styleable.Wallpaper_description,
-1);
mContextUriResource = sa.getResourceId(
com.android.internal.R.styleable.Wallpaper_contextUri,
-1);
mContextDescriptionResource = sa.getResourceId(
com.android.internal.R.styleable.Wallpaper_contextDescription,
-1);
mShowMetadataInPreview = sa.getBoolean(
com.android.internal.R.styleable.Wallpaper_showMetadataInPreview,
false);
mSupportsAmbientMode = sa.getBoolean(
com.android.internal.R.styleable.Wallpaper_supportsAmbientMode,
false);
sa.recycle();
} catch (NameNotFoundException e) {
throw new XmlPullParserException(
"Unable to create context for: " + si.packageName);
} finally {
if (parser != null) parser.close();
}
}
private void parseKeyboardAttributes(final XmlPullParser parser) {
final AttributeSet attr = Xml.asAttributeSet(parser);
final TypedArray keyboardAttr = mContext.obtainStyledAttributes(
attr, R.styleable.Keyboard, R.attr.keyboardStyle, R.style.Keyboard);
final TypedArray keyAttr = mResources.obtainAttributes(attr, R.styleable.Keyboard_Key);
try {
final KeyboardParams params = mParams;
final int height = params.mId.mHeight;
final int width = params.mId.mWidth;
params.mOccupiedHeight = height;
params.mOccupiedWidth = width;
params.mTopPadding = (int)keyboardAttr.getFraction(
R.styleable.Keyboard_keyboardTopPadding, height, height, 0);
params.mBottomPadding = (int)keyboardAttr.getFraction(
R.styleable.Keyboard_keyboardBottomPadding, height, height, 0);
params.mLeftPadding = (int)keyboardAttr.getFraction(
R.styleable.Keyboard_keyboardLeftPadding, width, width, 0);
params.mRightPadding = (int)keyboardAttr.getFraction(
R.styleable.Keyboard_keyboardRightPadding, width, width, 0);
final int baseWidth =
params.mOccupiedWidth - params.mLeftPadding - params.mRightPadding;
params.mBaseWidth = baseWidth;
params.mDefaultKeyWidth = (int)keyAttr.getFraction(R.styleable.Keyboard_Key_keyWidth,
baseWidth, baseWidth, baseWidth / DEFAULT_KEYBOARD_COLUMNS);
params.mHorizontalGap = (int)keyboardAttr.getFraction(
R.styleable.Keyboard_horizontalGap, baseWidth, baseWidth, 0);
// TODO: Fix keyboard geometry calculation clearer. Historically vertical gap between
// rows are determined based on the entire keyboard height including top and bottom
// paddings.
params.mVerticalGap = (int)keyboardAttr.getFraction(
R.styleable.Keyboard_verticalGap, height, height, 0);
final int baseHeight = params.mOccupiedHeight - params.mTopPadding
- params.mBottomPadding + params.mVerticalGap;
params.mBaseHeight = baseHeight;
params.mDefaultRowHeight = (int)ResourceUtils.getDimensionOrFraction(keyboardAttr,
R.styleable.Keyboard_rowHeight, baseHeight, baseHeight / DEFAULT_KEYBOARD_ROWS);
params.mKeyVisualAttributes = KeyVisualAttributes.newInstance(keyAttr);
params.mMoreKeysTemplate = keyboardAttr.getResourceId(
R.styleable.Keyboard_moreKeysTemplate, 0);
params.mMaxMoreKeysKeyboardColumn = keyAttr.getInt(
R.styleable.Keyboard_Key_maxMoreKeysColumn, 5);
params.mThemeId = keyboardAttr.getInt(R.styleable.Keyboard_themeId, 0);
params.mIconsSet.loadIcons(keyboardAttr);
params.mTextsSet.setLocale(params.mId.getLocale(), mContext);
final int resourceId = keyboardAttr.getResourceId(
R.styleable.Keyboard_touchPositionCorrectionData, 0);
if (resourceId != 0) {
final String[] data = mResources.getStringArray(resourceId);
params.mTouchPositionCorrection.load(data);
}
} finally {
keyAttr.recycle();
keyboardAttr.recycle();
}
}
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 boolean parseCaseCondition(final XmlPullParser parser) {
final KeyboardId id = mParams.mId;
if (id == null) {
return true;
}
final AttributeSet attr = Xml.asAttributeSet(parser);
final TypedArray caseAttr = mResources.obtainAttributes(attr, R.styleable.Keyboard_Case);
try {
final boolean keyboardLayoutSetMatched = matchString(caseAttr,
R.styleable.Keyboard_Case_keyboardLayoutSet,
id.mSubtype.getKeyboardLayoutSetName());
final boolean keyboardLayoutSetElementMatched = matchTypedValue(caseAttr,
R.styleable.Keyboard_Case_keyboardLayoutSetElement, id.mElementId,
KeyboardId.elementIdToName(id.mElementId));
final boolean keyboardThemeMacthed = matchTypedValue(caseAttr,
R.styleable.Keyboard_Case_keyboardTheme, mParams.mThemeId,
KeyboardTheme.getKeyboardThemeName(mParams.mThemeId));
final boolean modeMatched = matchTypedValue(caseAttr,
R.styleable.Keyboard_Case_mode, id.mMode, KeyboardId.modeName(id.mMode));
final boolean navigateNextMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_navigateNext, id.navigateNext());
final boolean navigatePreviousMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_navigatePrevious, id.navigatePrevious());
final boolean passwordInputMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_passwordInput, id.passwordInput());
final boolean clobberSettingsKeyMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_clobberSettingsKey, id.mClobberSettingsKey);
final boolean hasShortcutKeyMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_hasShortcutKey, id.mHasShortcutKey);
final boolean languageSwitchKeyEnabledMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_languageSwitchKeyEnabled,
id.mLanguageSwitchKeyEnabled);
final boolean isMultiLineMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_isMultiLine, id.isMultiLine());
final boolean imeActionMatched = matchInteger(caseAttr,
R.styleable.Keyboard_Case_imeAction, id.imeAction());
final boolean isIconDefinedMatched = isIconDefined(caseAttr,
R.styleable.Keyboard_Case_isIconDefined, mParams.mIconsSet);
final Locale locale = id.getLocale();
final boolean localeCodeMatched = matchLocaleCodes(caseAttr, locale);
final boolean languageCodeMatched = matchLanguageCodes(caseAttr, locale);
final boolean countryCodeMatched = matchCountryCodes(caseAttr, locale);
final boolean splitLayoutMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_isSplitLayout, id.mIsSplitLayout);
final boolean selected = keyboardLayoutSetMatched && keyboardLayoutSetElementMatched
&& keyboardThemeMacthed && modeMatched && navigateNextMatched
&& navigatePreviousMatched && passwordInputMatched && clobberSettingsKeyMatched
&& hasShortcutKeyMatched && languageSwitchKeyEnabledMatched
&& isMultiLineMatched && imeActionMatched && isIconDefinedMatched
&& localeCodeMatched && languageCodeMatched && countryCodeMatched
&& splitLayoutMatched;
if (DEBUG) {
startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE,
textAttr(caseAttr.getString(
R.styleable.Keyboard_Case_keyboardLayoutSet), "keyboardLayoutSet"),
textAttr(caseAttr.getString(
R.styleable.Keyboard_Case_keyboardLayoutSetElement),
"keyboardLayoutSetElement"),
textAttr(caseAttr.getString(
R.styleable.Keyboard_Case_keyboardTheme), "keyboardTheme"),
textAttr(caseAttr.getString(R.styleable.Keyboard_Case_mode), "mode"),
textAttr(caseAttr.getString(R.styleable.Keyboard_Case_imeAction),
"imeAction"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_navigateNext,
"navigateNext"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_navigatePrevious,
"navigatePrevious"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_clobberSettingsKey,
"clobberSettingsKey"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_passwordInput,
"passwordInput"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_hasShortcutKey,
"hasShortcutKey"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_languageSwitchKeyEnabled,
"languageSwitchKeyEnabled"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_isMultiLine,
"isMultiLine"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_isSplitLayout,
"splitLayout"),
textAttr(caseAttr.getString(R.styleable.Keyboard_Case_isIconDefined),
"isIconDefined"),
textAttr(caseAttr.getString(R.styleable.Keyboard_Case_localeCode),
"localeCode"),
textAttr(caseAttr.getString(R.styleable.Keyboard_Case_languageCode),
"languageCode"),
textAttr(caseAttr.getString(R.styleable.Keyboard_Case_countryCode),
"countryCode"),
selected ? "" : " skipped");
}
return selected;
} finally {
caseAttr.recycle();
}
}
/**
* Parse the given XML file as a header description, adding each
* parsed Header into the target list.
*
* @param resId The XML resource to load and parse.
* @param target The list in which the parsed headers should be placed.
*/
@SuppressWarnings("ResourceType")
private void loadHeadersFromResource(@MenuRes int resId, List<PanelMenuItem> target) {
Resources resources = getResources();
try (XmlResourceParser parser = resources.getXml(resId)) {
AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
//noinspection StatementWithEmptyBody
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) {
// Parse next until start tag is found
}
String nodeName = parser.getName();
if (!"menu".equals(nodeName)) {
throw new RuntimeException("XML document must start with <menu> tag; found" + nodeName + " at " + parser.getPositionDescription());
}
final int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
nodeName = parser.getName();
if ("item".equals(nodeName)) {
PanelMenuItem item = new PanelMenuItem(getContext());
int[] set = {
android.R.attr.id,
android.R.attr.title,
android.R.attr.icon,
android.R.attr.checkable,
android.R.attr.actionLayout
};
TypedArray sa = getContext().obtainStyledAttributes(attrs, set);
item.setItemId(sa.getResourceId(0, PanelMenuItem.HEADER_ID_UNDEFINED));
TypedValue tv = sa.peekValue(1);
if (tv != null && tv.type == TypedValue.TYPE_STRING) {
if (tv.resourceId != 0) {
item.setTitle(tv.resourceId);
} else {
item.setTitle(tv.string);
}
}
int iconRes = sa.getResourceId(2, 0);
if (iconRes != 0)
item.setIcon(iconRes);
item.setCheckable(sa.getBoolean(3, false));
int actionRes = sa.getResourceId(4, 0);
if (actionRes != 0)
item.setActionView(actionRes);
sa.recycle();
target.add(item);
} else {
XmlUtils.skipCurrentTag(parser);
}
}
} catch (XmlPullParserException | IOException e) {
throw new RuntimeException("Error parsing headers", e);
}
}
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 includeAttr = mResources.obtainAttributes(
attr, R.styleable.Keyboard);
mParams.mDefaultRowHeight = (int)ResourceUtils.getDimensionOrFraction(includeAttr,
R.styleable.Keyboard_rowHeight, mParams.mBaseHeight, mParams.mDefaultRowHeight);
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();
includeAttr.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 boolean parseCaseCondition(final XmlPullParser parser) {
final KeyboardId id = mParams.mId;
if (id == null) {
return true;
}
final AttributeSet attr = Xml.asAttributeSet(parser);
final TypedArray caseAttr = mResources.obtainAttributes(attr, R.styleable.Keyboard_Case);
try {
final boolean keyboardLayoutSetMatched = matchString(caseAttr,
R.styleable.Keyboard_Case_keyboardLayoutSet,
id.mSubtype.getKeyboardLayoutSetName());
final boolean keyboardLayoutSetElementMatched = matchTypedValue(caseAttr,
R.styleable.Keyboard_Case_keyboardLayoutSetElement, id.mElementId,
KeyboardId.elementIdToName(id.mElementId));
final boolean keyboardThemeMatched = matchTypedValue(caseAttr,
R.styleable.Keyboard_Case_keyboardTheme, mParams.mThemeId,
KeyboardTheme.getKeyboardThemeName(mParams.mThemeId));
final boolean modeMatched = matchTypedValue(caseAttr,
R.styleable.Keyboard_Case_mode, id.mMode, KeyboardId.modeName(id.mMode));
final boolean navigateNextMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_navigateNext, id.navigateNext());
final boolean navigatePreviousMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_navigatePrevious, id.navigatePrevious());
final boolean passwordInputMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_passwordInput, id.passwordInput());
final boolean clobberSettingsKeyMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_clobberSettingsKey, id.mClobberSettingsKey);
final boolean languageSwitchKeyEnabledMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_languageSwitchKeyEnabled,
id.mLanguageSwitchKeyEnabled);
final boolean isMultiLineMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_isMultiLine, id.isMultiLine());
final boolean imeActionMatched = matchInteger(caseAttr,
R.styleable.Keyboard_Case_imeAction, id.imeAction());
final boolean isIconDefinedMatched = isIconDefined(caseAttr,
R.styleable.Keyboard_Case_isIconDefined, mParams.mIconsSet);
final Locale locale = id.getLocale();
final boolean localeCodeMatched = matchLocaleCodes(caseAttr, locale);
final boolean languageCodeMatched = matchLanguageCodes(caseAttr, locale);
final boolean countryCodeMatched = matchCountryCodes(caseAttr, locale);
final boolean showMoreKeysMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_showExtraChars, id.mShowMoreKeys);
final boolean showNumberRowMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_showNumberRow, id.mShowNumberRow);
final boolean selected = keyboardLayoutSetMatched && keyboardLayoutSetElementMatched
&& keyboardThemeMatched && modeMatched && navigateNextMatched
&& navigatePreviousMatched && passwordInputMatched && clobberSettingsKeyMatched
&& languageSwitchKeyEnabledMatched
&& isMultiLineMatched && imeActionMatched && isIconDefinedMatched
&& localeCodeMatched && languageCodeMatched && countryCodeMatched
&& showMoreKeysMatched && showNumberRowMatched;
return selected;
} finally {
caseAttr.recycle();
}
}
private boolean parseCaseCondition(final XmlPullParser parser) {
final KeyboardId id = mParams.mId;
if (id == null) {
return true;
}
final AttributeSet attr = Xml.asAttributeSet(parser);
final TypedArray caseAttr = mResources.obtainAttributes(attr, R.styleable.Keyboard_Case);
try {
final boolean keyboardLayoutSetMatched = matchString(caseAttr,
R.styleable.Keyboard_Case_keyboardLayoutSet,
id.mSubtype.getKeyboardLayoutSetName());
final boolean keyboardLayoutSetElementMatched = matchTypedValue(caseAttr,
R.styleable.Keyboard_Case_keyboardLayoutSetElement, id.mElementId,
KeyboardId.elementIdToName(id.mElementId));
final boolean keyboardThemeMacthed = matchTypedValue(caseAttr,
R.styleable.Keyboard_Case_keyboardTheme, mParams.mThemeId,
KeyboardTheme.getKeyboardThemeName(mParams.mThemeId));
final boolean modeMatched = matchTypedValue(caseAttr,
R.styleable.Keyboard_Case_mode, id.mMode, KeyboardId.modeName(id.mMode));
final boolean navigateNextMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_navigateNext, id.navigateNext());
final boolean navigatePreviousMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_navigatePrevious, id.navigatePrevious());
final boolean passwordInputMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_passwordInput, id.passwordInput());
final boolean clobberSettingsKeyMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_clobberSettingsKey, id.mClobberSettingsKey);
final boolean hasShortcutKeyMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_hasShortcutKey, id.mHasShortcutKey);
final boolean languageSwitchKeyEnabledMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_languageSwitchKeyEnabled,
id.mLanguageSwitchKeyEnabled);
final boolean isMultiLineMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_isMultiLine, id.isMultiLine());
final boolean imeActionMatched = matchInteger(caseAttr,
R.styleable.Keyboard_Case_imeAction, id.imeAction());
final boolean isIconDefinedMatched = isIconDefined(caseAttr,
R.styleable.Keyboard_Case_isIconDefined, mParams.mIconsSet);
final Locale locale = id.getLocale();
final boolean localeCodeMatched = matchLocaleCodes(caseAttr, locale);
final boolean languageCodeMatched = matchLanguageCodes(caseAttr, locale);
final boolean countryCodeMatched = matchCountryCodes(caseAttr, locale);
final boolean splitLayoutMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_isSplitLayout, id.mIsSplitLayout);
final boolean selected = keyboardLayoutSetMatched && keyboardLayoutSetElementMatched
&& keyboardThemeMacthed && modeMatched && navigateNextMatched
&& navigatePreviousMatched && passwordInputMatched && clobberSettingsKeyMatched
&& hasShortcutKeyMatched && languageSwitchKeyEnabledMatched
&& isMultiLineMatched && imeActionMatched && isIconDefinedMatched
&& localeCodeMatched && languageCodeMatched && countryCodeMatched
&& splitLayoutMatched;
if (DEBUG) {
startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE,
textAttr(caseAttr.getString(
R.styleable.Keyboard_Case_keyboardLayoutSet), "keyboardLayoutSet"),
textAttr(caseAttr.getString(
R.styleable.Keyboard_Case_keyboardLayoutSetElement),
"keyboardLayoutSetElement"),
textAttr(caseAttr.getString(
R.styleable.Keyboard_Case_keyboardTheme), "keyboardTheme"),
textAttr(caseAttr.getString(R.styleable.Keyboard_Case_mode), "mode"),
textAttr(caseAttr.getString(R.styleable.Keyboard_Case_imeAction),
"imeAction"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_navigateNext,
"navigateNext"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_navigatePrevious,
"navigatePrevious"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_clobberSettingsKey,
"clobberSettingsKey"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_passwordInput,
"passwordInput"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_hasShortcutKey,
"hasShortcutKey"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_languageSwitchKeyEnabled,
"languageSwitchKeyEnabled"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_isMultiLine,
"isMultiLine"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_isSplitLayout,
"splitLayout"),
textAttr(caseAttr.getString(R.styleable.Keyboard_Case_isIconDefined),
"isIconDefined"),
textAttr(caseAttr.getString(R.styleable.Keyboard_Case_localeCode),
"localeCode"),
textAttr(caseAttr.getString(R.styleable.Keyboard_Case_languageCode),
"languageCode"),
textAttr(caseAttr.getString(R.styleable.Keyboard_Case_countryCode),
"countryCode"),
selected ? "" : " skipped");
}
return selected;
} finally {
caseAttr.recycle();
}
}