2011-12-04 2 views
7

Android用のカスタムXMLデータ型を作成する方法はありますか?カスタムXMLデータ型を作成しますか?

私は、自分のエンティティのすべての統計情報を含むクラスModelを持っています。私は同様にxmlからModelクラスを膨らませることができるようにしたい - よく、ビューのようにexaclty。これは可能ですか?

例:

<?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. 
    } 
    // ... 
} 

答えて

8

慎重に選択された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などを使用して、コードを簡単に修正することもできます。

+0

非常に詳細な回答はありがとうございます。あなたは私のヒーローです。 – AedonEtLIRA

0

XMLのシリアル化メカニズムがAndroidで一貫していません。おそらくGsonライブラリでJsonを代わりにお勧めします。

1

TextView、EditTextなどの既存のビュークラスを拡張すると、xmlレイアウト内で呼び出すことができます。

これはカスタムコンポーネントのAndroid Referenceです。

カスタムxml属性も定義できます。これはexampleanother oneです。

私はあなたに役立つことを願っています!

+0

入力いただきありがとうございますが、私はViewやその他のウィジェットを拡張していません。私は文字列と整数xmlファイル[R]で定義したリソースを指す生のXMLファイルを持っています。 – AedonEtLIRA

関連する問題