もぐてっく

人は1つ歳をとるたび、1ビットづつ大きくなれると信じてた。

AndroidのレイアウトXMLからビュークラスのインスタンス生成コードを生成するスクリプト

二、三日前からAndroidのプログラムを書いてるんですが・・・いやぁ、色々面倒臭い。
ビューを弄るだけでもいちいちキャスト付きでfindViewByIdを呼ばんといかんとかもうね。
MFCのClass Wizardみたく、IDをビューのクラスでラッピングするコードを自動生成してくれたらいいのに・・・。

と、思ったのでレイアウトXMLからビュークラスのインスタンスを得るためのジェネレータもどきをRubyにょろーんと書いてみた。

#! /usr/bin/ruby

require "rexml/document"
include REXML

doc = Document.new($stdin)

declare = [];
constructor = [];

XPath.each(doc,"//*") { |elem|

        /^\@\+id\/(.+)$/ =~ elem.attributes["android:id"]
        id = $1


        if id != nil
                # declare
                line = "public " + elem.name + " " + id + ";"
                declare << line

                # constructor
                line = "this." + id + " = (" + elem.name + ")this.findViewById(R.id." + id + ");"
                constructor << line
        end
}

puts "***declare***"
puts declare

puts "***constructor***"
puts constructor

このスクリプトのstdinにレイアウトXMLを食わせて使用する。

akari:/usr/local/bin# ruby create_declare.rb << EOF
> <?xml version="1.0" encoding="utf-8"?>
> <LinearLayout
>   xmlns:android="http://schemas.android.com/apk/res/android"
>   android:layout_width="match_parent"
>   android:layout_height="match_parent" android:orientation="vertical">
>     <TextView android:text="TextView" android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
>     <ListView android:layout_height="wrap_content" android:id="@+id/listView1" android:layout_width="match_parent" android:layout_weight="1"></ListView>
>     <LinearLayout android:layout_height="wrap_content" android:layout_width="match_parent" android:id="@+id/linearLayout1" android:orientation="horizontal">
>         <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="OK"></Button>
>         <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="Cancel"></Button>
>     </LinearLayout>
> </LinearLayout>
> EOF
***declare***
public TextView textView1;
public ListView listView1;
public LinearLayout linearLayout1;
public Button button1;
public Button button2;
***constructor***
this.textView1 = (TextView)this.findViewById(R.id.textView1);
this.listView1 = (ListView)this.findViewById(R.id.listView1);
this.linearLayout1 = (LinearLayout)this.findViewById(R.id.linearLayout1);
this.button1 = (Button)this.findViewById(R.id.button1);
this.button2 = (Button)this.findViewById(R.id.button2);

declare以下をクラスのフィールド宣言としてコピペ。
constructor以下をonCreateのsetContentView()の直下に貼り付ければ、どこからでもビューにアクセスできるようになると。