慎重に選択されたAPIを使用するカスタムコードでは、AndroidがレイアウトXMLファイルを膨張させる方法を模倣することができ、XMLファイルのコンパイルやカスタムXMLファイル内の任意のリソースへの参照などAndroidのXML最適化やメリットの恩恵を受けます。 LayoutInflater
に直接フックインすることはできません。そのクラスは、View
を膨らませることしかできないからです。以下のコードを動作させるには、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;
}
}
、あなたはView
はそれをしないのと同じよう、Model
クラス内の属性の「パース」を置くことができます。
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
を持つことはできませんresource
はないので有効なリソースタイプですが、@string/foo
は問題ありません。 @drawable/foo
などを使用して、コードを簡単に修正することもできます。
非常に詳細な回答はありがとうございます。あなたは私のヒーローです。 – AedonEtLIRA