创建自定义 XML 数据类型?

2024-02-07

有没有办法为 Android 创建自定义 XML 数据类型?

我有课Model其中包含我的实体的所有统计数据。我希望能够充气Model与 xml 中的类类似 - 嗯,就像视图一样。这可能吗?

Example:

<?xml version="1.0" encoding="utf-8"?>
<models xmlns:android="http://schemas.android.com/apk/res/android">
    <model name="tall_model"
        type="@string/infantry"
        stat_attack="5"
        >Tall Gunner</model>

    <model name="short_model"
        type="@string/infantry"
        stat_attack="3"
        ability="@resource/scout"
        >Short Gunner</model>

    <model name="big_tank"
        type="@string/vehicle"
        stat_attack="7"
        armour="5"
        >Big Tank</model>
</models>

我想扩充的课程。

class Model [extends Object] {
    public Model(Context context, AttributeSet attrs) {
        // I think you understand what happens here.
    }
    // ...
}

通过使用精心选择的 API 的一些自定义代码,您可以模仿 Android 扩展布局 XML 文件的方式,并且仍然受益于 Android 的 XML 优化和优点,例如编译的 XML 文件以及对自定义 XML 文件中任意资源的引用。您不能直接连接到现有的LayoutInflater因为该类只能处理膨胀Views。为了使下面的代码正常工作,请将 XML 文件放入应用程序的“res/xml”中。

首先,这是解析(编译的)XML 文件并调用Model构造函数。您可能想要添加一些注册机制,以便可以轻松地为任何标记注册类,或者您可能想要使用ClassLoader.loadClass()这样您就可以根据类的名称加载类。

public class CustomInflator {
    public static ArrayList<Model> inflate(Context context, int xmlFileResId) throws Exception {
        ArrayList<Model> models = new ArrayList<Model>();

        XmlResourceParser parser = context.getResources().getXml(R.xml.models);
        Model currentModel = null;
        int token;
        while ((token = parser.next()) != XmlPullParser.END_DOCUMENT) {
            if (token == XmlPullParser.START_TAG) {
                if ("model".equals(parser.getName())) {
                    // You can retrieve the class in other ways if you wish
                    Class<?> clazz = Model.class;
                    Class<?>[] params = new Class[] { Context.class, AttributeSet.class };
                    Constructor<?> constructor = clazz.getConstructor(params);
                    currentModel = (Model)constructor.newInstance(context, parser);
                    models.add(currentModel);
                }
            } else if (token == XmlPullParser.TEXT) {
                if (currentModel != null) {
                    currentModel.setText(parser.getText());
                }
            } else if (token == XmlPullParser.END_TAG) {
                // FIXME: Handle when "model" is a child of "model"
                if ("model".equals(parser.getName())) {
                    currentModel = null;
                }
            }
        }

        return models;
    }
 }

完成此操作后,您可以将属性的“解析”放在Model类,很像View可以:

public class Model {
    private String mName;
    private String mType;
    private int mStatAttack;
    private String mText;

    public Model(Context context, AttributeSet attrs) {
        for (int i = 0; i < attrs.getAttributeCount(); i++) {
            String attr = attrs.getAttributeName(i);
            if ("name".equals(attr)) {
                mName = attrs.getAttributeValue(i);
            } else if ("type".equals(attr)) {
                // This will load the value of the string resource you
                // referenced in your XML
                int stringResource = attrs.getAttributeResourceValue(i, 0);
                mType = context.getString(stringResource);
            } else if ("stat_attack".equals(attr)) {
                mStatAttack = attrs.getAttributeIntValue(i, -1);
            } else {
                // TODO: Parse more attributes
            }
        }
    }

    public void setText(String text) {
        mText = text;
    }

    @Override
    public String toString() {
        return "model name=" + mName + " type=" + mType + " stat_attack=" + mStatAttack + " text=" + mText;
    }
}

上面我通过字符串表示引用了属性。如果您想更进一步,您可以定义应用程序特定的属性资源并使用它们,但这会使事情变得相当复杂(请参阅使用 XML 声明自定义 Android UI 元素 https://stackoverflow.com/questions/2695646/declaring-a-custom-android-ui-element-using-xml)。无论如何,在虚拟活动中设置所有资源:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    try {
        for (Model m : CustomInflator.inflate(this, R.xml.models)) {
            Log.i("Example", "Parsed: " + m.toString());
        }
    } catch (Exception e) {
        Log.e("Example", "Got " + e);
    }
}

你会得到这个输出:

I/Example ( 1567): Parsed: model name=tall_model type=Example3 stat_attack=5 text=Tall Gunner
I/Example ( 1567): Parsed: model name=short_model type=Example3 stat_attack=3 text=Short Gunner
I/Example ( 1567): Parsed: model name=big_tank type=Example2 stat_attack=7 text=Big Tank

请注意,您不能拥有@resource/scout在您的 XML 文件中,因为resource不是有效的资源类型,但是@string/foo工作正常。您还应该能够使用例如@drawable/foo对代码进行一些简单的修改。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

创建自定义 XML 数据类型? 的相关文章

随机推荐