android – 创建自定义XML数据类型?

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

我有一个类模型,其中包含我的实体的所有统计信息.我希望能够从xml类似地扩展Model类 – 嗯,exaclty就像View一样.这可能吗?

例:

<?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文件和引用自定义XML文件中的任意资源一样.您无法直接挂入现有的LayoutInflater,因为该类只能处理膨胀的视图.为了使下面的代码能够工作,请将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;
    }
}

上面我通过字符串表示引用了属性.如果你想更进一步,你可以定义特定于应用程序的属性资源并使用它们,但这会使事情变得复杂(见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

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

相关文章

Android性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...