/** * Inflate a menu hierarchy from the specified XML resource. Throws {@link InflateException} if * there is an error. * * @param menuRes Resource ID for an XML layout resource to load (e.g., <code>R.menu.main_activity * </code>) * @param menu The Menu to inflate into. The items and submenus will be added to this Menu. */ public void inflate(int menuRes, Menu menu) { XmlResourceParser parser = null; try { parser = mContext.getResources().getLayout(menuRes); AttributeSet attrs = Xml.asAttributeSet(parser); parseMenu(parser, attrs, menu); } catch (XmlPullParserException e) { throw new InflateException("Error inflating menu XML", e); } catch (IOException e) { throw new InflateException("Error inflating menu XML", e); } finally { if (parser != null) parser.close(); } }
/** * Called internally to fill the given menu. If a sub menu is seen, it will call this recursively. */ private void parseMenu(XmlPullParser parser, AttributeSet attrs, Menu menu) throws XmlPullParserException, IOException { MenuState menuState = new MenuState(menu); int eventType = parser.getEventType(); String tagName; boolean lookingForEndOfUnknownTag = false; String unknownTagName = null; // This loop will skip to the menu start tag do { if (eventType == XmlPullParser.START_TAG) { tagName = parser.getName(); if (tagName.equals(XML_MENU)) { // Go to next tag eventType = parser.next(); break; } throw new RuntimeException("Expecting menu, got " + tagName); } eventType = parser.next(); } while (eventType != XmlPullParser.END_DOCUMENT); boolean reachedEndOfMenu = false; while (!reachedEndOfMenu) { switch (eventType) { case XmlPullParser.START_TAG: if (lookingForEndOfUnknownTag) { break; } tagName = parser.getName(); if (tagName.equals(XML_GROUP)) { menuState.readGroup(attrs); } else if (tagName.equals(XML_ITEM)) { menuState.readItem(attrs); } else if (tagName.equals(XML_MENU)) { // A menu start tag denotes a submenu for an item SubMenu subMenu = menuState.addSubMenuItem(); // Parse the submenu into returned SubMenu parseMenu(parser, attrs, subMenu); } else { lookingForEndOfUnknownTag = true; unknownTagName = tagName; } break; case XmlPullParser.END_TAG: tagName = parser.getName(); if (lookingForEndOfUnknownTag && tagName.equals(unknownTagName)) { lookingForEndOfUnknownTag = false; unknownTagName = null; } else if (tagName.equals(XML_GROUP)) { menuState.resetGroup(); } else if (tagName.equals(XML_ITEM)) { // Add the item if it hasn't been added (if the item was // a submenu, it would have been added already) if (!menuState.hasAddedItem()) { if (menuState.itemActionProvider != null && menuState.itemActionProvider.hasSubMenu()) { menuState.addSubMenuItem(); } else { menuState.addItem(); } } } else if (tagName.equals(XML_MENU)) { reachedEndOfMenu = true; } break; case XmlPullParser.END_DOCUMENT: throw new RuntimeException("Unexpected end of document"); } eventType = parser.next(); } }