如何获取枚举自定义属性的所有可能值?

时间:2017-01-19 11:30:49

标签: java android android-custom-attributes declare-styleable

假设我的观点有自定义属性my_custom_enum

<attr name="my_custom_enum" format="enum">
    <enum name="first_value" value="751"/>
    <enum name="second_value" value="2222"/>
    <enum name="third_value" value="1241"/>
    <enum name="fourth_value" value="4"/>
</attr>

<declare-styleable name="CustomViewOne">
    <attr name="my_custom_enum"/>
</declare-styleable>

<declare-styleable name="CustomViewTwo">
    <attr name="my_custom_enum"/>
</declare-styleable>

有没有办法在代码中获取此枚举的所有可能的值

换句话说:

我希望能够获得值751222212414。 <{1}}这些值也会很好,但不是强制性的。

1 个答案:

答案 0 :(得分:1)

我最终得到的解决方案是pskinkcomment建议的解决方案:解析attrs.xml并自行提取值。

有两个原因让这样做完全合理:

  1. 我需要这个用于单元测试(要了解更多相关内容,请在问题的评论中阅读我与pskink的对话)。
  2. 对名称/值不会存储在任何地方。使用ints时仅使用AttributeSet
  3. 我最终得到的代码是:

    public final class AttrsUtils {
    
        private static final String TAG_ATTR = "attr";
        private static final String TAG_ENUM = "enum";
        private static final String ATTRIBUTE_NAME = "name";
        private static final String ATTRIBUTE_FORMAT = "format";
        private static final String ATTRIBUTE_VALUE = "value";
    
        @CheckResult
        @NonNull
        public static Map<String, Integer> getEnumAttributeValues(String attrName)
                throws ParserConfigurationException, IOException, SAXException {
            final File attrsFile = new File("../app/src/main/res/values/attrs.xml");
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(attrsFile);
            doc.getDocumentElement().normalize();
    
            Map<String, Integer> fontAttributes = new ArrayMap<>();
    
            NodeList nList = doc.getElementsByTagName(TAG_ATTR);
            for (int temp = 0; temp < nList.getLength(); temp++) {
                Node attrNode = nList.item(temp);
                if (attrNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element attrElement = (Element) attrNode;
                    final String name = attrElement.getAttribute(ATTRIBUTE_NAME);
                    if (!attrElement.hasAttribute(ATTRIBUTE_FORMAT) || !name.equals(attrName)) {
                        continue;
                    }
    
                    final NodeList enumNodeList = attrElement.getElementsByTagName(TAG_ENUM);
                    for (int i = 0, size = enumNodeList.getLength(); i < size; ++i) {
                        final Node enumNode = enumNodeList.item(i);
                        if (enumNode.getNodeType() == Node.ELEMENT_NODE) {
                            Element enumElement = (Element) enumNode;
                            fontAttributes.put(
                                    enumElement.getAttribute(ATTRIBUTE_NAME),
                                    Integer.parseInt(enumElement.getAttribute(ATTRIBUTE_VALUE)));
                        }
                    }
                    break; // we already found the right attr, we can break the loop
                }
            }
            return fontAttributes;
        }
    
        // Suppress default constructor for noninstantiability
        private AttrsUtils() {
            throw new AssertionError();
        }
    }
    

    此方法返回Map name - value个对,表示具有attrName的属性。

    对于我在问题中写的示例,您将使用此方法:

    Map<String, Integer> enumAttr = AttrsUtils.getEnumAttributeValues("my_custom_enum");