/res/layout/show.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="vertical" android:layout_marginLeft="10dip" android:layout_marginTop="20dip" android:layout_width="wrap_content" android:layout_height="wrap_content"> <!-- 会社名 --> <TextView android:id="@+id/companyNameLabel" android:text="@string/company_name" android:textSize="19dip" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <!-- 組織名 --> <TextView android:id="@+id/organizationNameLabel" android:text="@string/organization_name" android:layout_marginLeft="10dip" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <!-- 役職名 --> <TextView android:id="@+id/positionNameLabel" android:text="@string/position_name" android:layout_marginLeft="10dip" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout> <LinearLayout android:orientation="vertical" android:layout_marginTop="40dip" android:layout_marginRight="20dip" android:layout_width="fill_parent" android:layout_height="wrap_content"> <!-- 人名 --> <TextView android:id="@+id/personNameLabel" android:text="@string/person_name" android:textSize="25dip" android:gravity="right" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <!-- 住所 --> <TextView android:id="@+id/addressLabel" android:text="@string/address" android:textSize="20dip" android:layout_marginLeft="10dip" android:gravity="right" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <!-- 電話1 --> <TextView android:id="@+id/tel1Label" android:text="@string/tel1" android:autoLink="phone" android:textSize="20dip" android:gravity="right" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <!-- 電話2 --> <TextView android:id="@+id/tel2Label" android:text="@string/tel2" android:autoLink="phone" android:gravity="right" android:textSize="20dip" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <!-- メール --> <TextView android:id="@+id/mailLabel" android:text="@string/mail" android:autoLink="email" android:textSize="20dip" android:gravity="right" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout>
/src/com.example.bizcard/ShowActivity.java
public class ShowActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.show); } }
/AndroidManifest.xml
<activity android:name=".ShowActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> </intent-filter> </activity>
前回とほぼ同じです。
show.xmlはandroid:textSizeやandroid:layout_marginLeftなんかを使用してデザイン性がアップしています。
Eclipseのレイアウトエディタだと何故かうまく表示されません。
これに限らず、複雑なデザインをするとレイアウト表示では崩れてしまうようです。
↑Eclipse
↑エミュレータ
どうやってデバッグすればいいんだ。
毎回実機に送り込んで確認しないといけないのか?
Androidの記事
前回の続き。
これまでずっとアクティビティひとつで完結するアプリしか作っていませんでした。
複数アクティビティに挑戦してみます。
まずはビュー。
/res/layout/regist.xml
<?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:stretchColumns="1" android:shrinkColumns="1"> <!-- 名前 --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:text="@string/person_name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <EditText android:id="@+id/personNameText" android:layout_span="2" android:hint="@string/required" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </TableRow> <!-- 会社 --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:text="@string/company_name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <EditText android:id="@+id/companyNameText" android:layout_span="2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </TableRow> <!-- 部署 --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:text="@string/organization_name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <EditText android:id="@+id/organizationNameText" android:layout_span="2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </TableRow> <!-- 役職 --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:text="@string/position_name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <EditText android:id="@+id/positionNameText" android:layout_span="2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </TableRow> <!-- 郵便番号 --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:text="@string/zip_code" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" /> <EditText android:id="@+id/zipCodeText" android:minWidth="100dip" android:inputType="phone" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </TableRow> <!-- 住所 --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:text="@string/address" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <EditText android:id="@+id/addressText" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageButton android:id="@+id/mapButton" android:src="@drawable/map" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </TableRow> <!-- 電話1 --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:text="@string/tel1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <EditText android:id="@+id/tel1Text" android:layout_span="2" android:inputType="phone" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </TableRow> <!-- 電話2 --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:text="@string/tel2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <EditText android:id="@+id/tel2Text" android:layout_span="2" android:inputType="phone" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </TableRow> <!-- メール --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:text="@string/mail" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <EditText android:id="@+id/mailText" android:layout_span="2" android:inputType="textEmailAddress" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </TableRow> </TableLayout>当初自力でやろうと思ってたんだがめんどくさすぎたので結局コピペになった。
もう少しどうにかならんのか。
ビューはデフォルトでは全体を<LinearLayout>で囲まれますが、これを<TableLayout>に変更します。
LinearLayoutは一行にひとつの要素を記述する、まさにメニュー用途向けのレイアウトですが、逆に複雑なレイアウトは表示できません。
TableLayoutはHTMLの<table>とほぼ同じで、<tr>に相当する<TableRow>で行を指定し、中に各部品を配置していきます。
android:layout_spanはcolspanです。
rowspanは無いみたい?
android:inputTypeは入力文字種を指定できます。
"phone"であれば数値、"textPassword"であればパスワード等。
これを設定するとソフトウェアキーボードも自動的に変わったりします。
"textPersonName"とか"textPostalAddress"とかまであるみたいなんだがどう使うんだそれ。
android:hintは未入力時に表示されるヒントです。
カーソルを合わせると削除されます。
HTMLだとこの機能はJavaScriptで実装するしかないのですが、Androidでは予め用意されています。
ビューに配置されている@stringを設定。
/res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">BizCard</string> <string name="person_name">名前</string> <string name="company_name">会社</string> <string name="organization_name">組織</string> <string name="position_name">役職</string> <string name="zip_code">郵便番号</string> <string name="address">住所</string> <string name="tel1">電話1</string> <string name="tel2">電話2</string> <string name="mail">メール</string> <string name="required">必須</string> <string name="map">地図</string> <string name="map_satellite">衛星写真</string> <string name="current_location_on">現在地を中央に表示</string> <string name="current_location_off">現在地を中央に表示</string> </resources>
住所のところに<ImageButton android:src="@drawable/map">というのがありますが、これは画像ファイルです。
/res/drawableフォルダに画像を登録し、そのファイル名を指定することで画像表示が行えます。
拡張子は指定しないようです。
map.pngとmap.jpgがあったらどうするんだろうと思ったが登録できないみたい。
デフォルトではdrawable-hdpi、drawable-mdpi、drawable-ldpiといったフォルダがありますが、高解像度用、中解像度用、低解像度用の画像を入れておくと自動で出し分けされます。
drawableフォルダは該当解像度の画像が見つからなかった場合のデフォルトになります。
ようやく素材が完成したので次はアクティビティを作成します。
/src/com.example.bizcard/RegistActivity.java
package com.example.bizcard; import android.app.Activity; import android.os.Bundle; public class RegistActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.regist); } }
例によってpackageやimportはIDEが勝手にやってくれます。
ListActivityと違うところは、最後のsetContentViewのターゲットがR.layout.registになっています。
これによって/res/layout/regist.xmlがビューとして使用されることになります。
最後にAndroidManifest.xmlを記述します。
いくらアクティビティを作成しても、AndroidManifest.xmlに記述しないかぎり無かったもの扱いになるようです。
<application>内に今回作成したアクティビティを追加します。
/AndroidManifest.xml
<activity android:name=".RegistActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> </intent-filter> </activity>
<intent-filter>って何?というところですが、外部アプリから起動される際の関連付けの設定などを行うようです。
中でも特に、<action android:name="android.intent.action.MAIN" />を設定したアクティビティは、ランチャーから直接起動したときに実行されるアクティビティになります。
ところで現在ListActivityとRegistActivityの両方に<action android:name="android.intent.action.MAIN" />が設定される事態となっておりますが、この場合どちらが優先されるかはコンパイル時に決められます。
「実行」→「実行構成」→「LaunchAction」から指定を行えます。
ここをRegistActivityにし、実行すると無事入力画面が表示されました。
Androidの記事
http://codezine.jp/article/detail/4670
ということでまずはレイアウトを作成。
BizCard/res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ListView android:id="@+id/list" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout>
<LinearLayout>で全体のレイアウトを作成、<ListView>でその中に表示するコンテンツを並べています。
現在は"@+id/list"が空っぽなので何も表示されません。
ということで値を入れてみます。
BizCard/src/com.example.bizcard/ListActivity.java
package com.example.bizcard; public class ListActivity extends Activity { // 一覧表示用ListView private ListView listView = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 配列を作成 ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1); // 要素を追加 arrayAdapter.add("新規追加"); // main.xmlのandroid:id="@+id/list"を取得 listView = (ListView) findViewById(R.id.list); // 配列を突っ込む listView.setAdapter(arrayAdapter); } }
CodeZineの説明が正直よくわからなかったので俺語訳しています。
ListViewは突っ込んだ配列を全部順番に表示するビューです。
Androidのメニューはたいがいこれを使ってそうな見た目になっています。
えーと、<String>ってなんだったっけ。
Javaが久しぶりすぎて何もかもを忘れてしまった。
これでもSJC-PとSJC-WCとSJC-WS持ってるんだがこれはゴミか?ゴミです。
ArrayAdapterはあらゆるオブジェクトを突っ込めてしまうので、うっかりarrayAdapter.add(new Object())とか書かれてしまう可能性もあります。
まあObjectであればObject.toString()が発動して"java.lang.Object@43e9b648"とかなんだかよくわからない値が表示されるだけなのですが、想定外の動作にはかわりありません。
そこで<String>と型を指定することで、挿入も取得もString型しか使用できないように強制します。
arrayAdapter.add(new Object())と書いてもコンパイルで弾かれるようになります。
android.widget.ArrayAdapterの第二引数にはリソースを渡せるのですが、とりあえずどの値がどういう意味なのかがわからん。
http://developer.android.com/intl/ja/reference/android/widget/ArrayAdapter.html
http://developer.android.com/intl/ja/reference/android/R.layout.html
そんな数値だけ書かれても。
とりあえず以上で"新規追加"メニューが表示されました。
Androidの記事
前回の続き
ビルドからアプリケーション実行までの流れのあたりはEclipseが全自動で行ってくれるので開発時はあまり気にすることはありません。
まずはプロジェクトの作成。
プロジェクト名「BizCard」、アプリケーション名「BizCard」、パッケージ名「com.example.bizcard」、アクティビティ名「ListActivity」
ビルドターゲットはGoogleAPIsを選択します。
これAndroid2.1でかつGoogleAPIを使いたいとかだったらどうすればいいんだろうな。
何もしていないのにさくりと雛形ができあがりました。
この時点で実行するとデフォルトのHelloWorldが表示されます。
では早速実装を行っていきましょう。
最初に見るのがBizCard/AndroidManifest.xml。
ダブルクリックだと専用のビューアが立ち上がりますが、正直よくわかんないので下の「AndroidManifest.xml」タブをクリックしてXML状態で表示するようにしておきましょう。
AndroidManifest.xmlはアプリケーション全体の名前とか、起動したときにどのアクティビティが動作するかとを定義しているファイルです。
サーブレットで言うところのweb.xmlみたいなものです。
ただ、<intent-filter>のあたりはまだ何言ってるのかわかりません。
BizCard/gen/com.example.bizcard/R.javaはEclipseによって自動生成されるファイルで、編集することが出来ません。
src以下のJavaソースとres以下のXMLリソースを結びつける役目らしいです。
BizCard/res/layout/main.xmlが画面のレイアウトファイルです。
ダブルクリックやドラッグでボタンを配置とかが出来るのですが、そのボタンを真ん中に移動したりとかサイズを変更したりといった細かい編集は行えないのであまり意味がありません。
結局テキストエディタでXMLをかりかりする羽目になりそうです。
実質コードを書かないまま二日目終了。
Androidって、というかJava全体に感じるのですが、なんか「HelloWorld」と「実用アプリ」の間を埋めるようなサイトがほとんど無い気がする。
「HelloWorld」レベルであればインストールするだけで終わりなのでどこででも(ここでも)紹介されています。
でも自力でアプリ作れる程度の人のサイトを見ると、大抵ソースだけとか実行ファイルだけとかを公開して終わりという。
どのファイルのどの値がどうなってこうなってる、といった、PHPなんかだと腐るほどある中級者レベルの解説サイトがあまり見あたらない。
Javaは有段者用、ただし1段の次が10段目、みたいな。
JavaやAndroidのAPIリファレンスは、PHPの関数リファレンスと違って例題、ノートみたいなものがないのでどう使ってみればいいのかわかんないし。
あとあれだ、var_dump()をよこせ。頼むから。
そんな中、ようやくCodeZineでアプリ開発講座を見つけましたので試してみたいと思います。
一日目は開発環境構築とプロジェクト作成。
といってもここらへんは先日やったのでパス。
しかしこの講座が始まったのが半年前で使っているがSDK1.6なのに現在は既に2.2という。
そろそろいいかげん落ち着かないものですかね。
とりあえずはAPIデモプロジェクトをJDK2.2で作成してみます。
要は最初から付属しているサンプルのソースです。
新規Androidプロジェクトを作成→ビルドターゲットにAndroid2.2をチェック→Create peoject from existing demosと順に選択すると、サンプルアプリをインポートすることが出来ます。
早速実行してみると「Please execute 'adb uninstall com.example.android.apis' in a shell.」
そのアプリはエミュレータに最初から入っているからアンインストールしないと新たにインストールできないよ、ということらしい。
そういやエミュレータをインストールしたとき追加コンテンツを片端から入れていたようなないような。
cmdでコマンドプロンプトを起動し削除実行。
cd C:\android-sdk-windows\tools (emulator.exeのあるフォルダ)
adb uninstall com.example.android.apis
で削除できます。
再度Eclipseからサンプルアプリを実行すると、無事に立ち上がりました。
めでたしめでたし。
で、これ、どれがどうなってどう動いてるのかさっぱりわからない。
ある日突然EclipseからAndroidを起動できなくなった。
起動時のエラー。
ADB server didn't ACK
* failed to start daemon *
実行時のエラー。
The connection to adb is down, and a severe error has occured.
You must restart adb and Eclipse.
Please ensure that adb is correctly located at 'C:\android-sdk-windows\tools\adb.exe' and can be executed.
こういう場合は何もしてないとか言いつつ大抵何かやってたりするんだが、今回は見当が付かない。
特にAndroidのAVDManagerからは普通に起動できるので、ADBとかいうやつが原因のようだ。
http://d.hatena.ne.jp/Kazzz/20100104/p1
http://d.hatena.ne.jp/darupants/20091031/1256960749
http://groups.google.co.jp/group/android-developers/msg/28823b2510cb41cf
http://groups.google.co.jp/group/android-beginners/browse_thread/thread/633db2fe32cbff39
http://forum.xda-developers.com/archive/index.php/t-517153.html
いまいち関係なさげだったり解決策がわからなかったり。
そもそもADBって何。
http://www.terracehouse.org/blok/2010/01/17/android-sdk%E3%81%AE%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E3%81%A8adb-shell%E3%81%AE%E8%B5%B7%E5%8B%95%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/
http://typex2.wordpress.com/2009/02/19/android%E3%81%AEadb%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9/
http://www.taosoftware.co.jp/blog/2008/10/android_adb.html
どうやらAndroidと接続するコンソールのようだ。
コンソールから実行。
C:\>adb shell
* daemon not running. starting it now *
ADB server didn't ACK
* failed to start daemon *
error: cannot connect to daemon
ADB daemonって何だよ。
最終的には
adb start-server
に失敗しているらしい。
* daemon not running. starting it now *
のまま動かなくなる。
なんだこれ。
結局AndroidSDKとEclipseをインストールし直して事なきを得た。
何が原因だったのか今もって不明。
Androidアプリはデフォルトだと画面上に電波状態や時計、アプリ名などが表示されます。
これらを削除してフルスクリーンにすることができます。
まずアプリケーション名を削除する方法。
アクティビティ内でsuper.onCreateとsetContentViewの間にrequestWindowFeature(Window.FEATURE_NO_TITLE);を指定します。
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.requestWindowFeature(android.view.Window.FEATURE_NO_TITLE); setContentView(R.layout.main); }
次に時計なんかを削除する方法。
なんかよくわからないけどandroid.view.WindowManager.LayoutParams.FLAG_FULLSCREENというフラグを追加すればいいみたい。
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.main); }余談だけどこのWindowManager.LayoutParams、よくわかんないフラグがいっぱいある。
ということでこの両者を併せるとフルスクリーン表示ができました。
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.requestWindowFeature(android.view.Window.FEATURE_NO_TITLE); this.getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.main); }
めでたし。
実はマニフェストにthemeを追加するだけで同じことができたりします。
<activity android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" >特にBlackをWhiteに変えたりNoTitleBarをTitleBarにしたりとかそういう機能はなさそうです。
Eclipseだとビュー編集時に右上あたりに設定できるオプションが出てるので見てみるといいかも。
"Theme.Dialog"とかかっこよさげだと思って設定してみたら全然違う見た目になったりしてなんだこれ。
前回入力値を表示するアプリを作成しました。
main.xmlにおいて、値を指定する部分がandroid:text="@+id/TextView01"とかになっていましたが、その値を取得できないよ、ということのようです。
出力される文字を定義することにします。
まずmain.xmlを編集。
<TextView android:text="@string/TextView01" android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content"> </TextView> <EditText android:text="@string/EditText01" android:id="@+id/EditText01" android:layout_width="fill_parent" android:layout_height="wrap_content"> </EditText> <Button android:text="@string/Button01" android:id="@+id/Button01" android:layout_width="fill_parent" android:layout_height="wrap_content"> </Button> <TextView android:text="@string/TextView02" android:id="@+id/TextView02" android:layout_width="wrap_content" android:layout_height="wrap_content"> </TextView>textの項目が@+idから@stringになりました。
この@stringから始まる項目は、/res/values/strings.xmlで定義する各要素と結びつけられます。
@から始めず直接"テキスト"とか書いても問題無く動くのですが、国際化を考えると予め分けておいたほうが良さそうです。
strings.xmlは言語毎に簡単に切り替えることができるので、日本語を出力する部分を分けておけば、英語対応する際もプログラムは触らず英語用のstrings.xmlを作成するだけで済むのです。
/res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="TextView01">名前を入力してください</string> <string name="EditText01"></string> <string name="Button01">クリックしてください</string> <string name="TextView02"></string> </resources>予め"hello"と"app_name"が定義されていますが、"hello"はテスト用なので削除してもかまいません。
"app_name"はプロジェクト作成時に指定したアプリケーション名で、実行時に表示されるやつです。
実行時(コンパイル時?)に、"@string/TextView01"の部分が<string name="TextView01">の要素に差し替えられ、"名前を入力してください"が表示されます。
以上で、入力した名前を表示するアプリケーションが完成しました。
さて、参考サイトはここでおしまいですが、もう少し続けてみます。
せっかく文言を分離したのにDisplayTextActivity.javaに直接日本語が入っています。
これもstrings.xmlに分離してしまいましょう。
/src/com.example.display.text/DisplayTextActivity.java
// クリック実装 private class MyClickAdapter implements OnClickListener { public void onClick(View v) { Editable value = text.getText(); String editTextBefore = getString(R.string.editTextBefore); String editTextAfter = getString(R.string.editTextAfter); display.setText(editTextBefore + value + editTextAfter); } }
/res/values/strings.xml
<string name="editTextBefore">こんにちは、</string> <string name="editTextAfter">さん</string>
Context.getString()でRの要素を取得できるようです。
ちなみにこちらにthisを付けると、MyClickAdapter.getString()なんてメソッドはないと怒られてしまいます。
以上で、全ての日本語をstrings.xmlに排除することができました。
ということでせっかくだから英語対応してみましょう。
/res/values-en/strings.xmlを作成します。
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">DisplayText</string> <string name="TextView01">Please insert name</string> <string name="EditText01"></string> <string name="Button01">Click Here</string> <string name="TextView02"></string> <string name="editTextBefore">Hello,</string> <string name="editTextAfter"></string> </resources>
完成。
え?これだけ?
はい、これだけです。
本体設定を英語にすると、見事に英語のフォームが表示されました。
英語が出鱈目なのはスルーということでひとつ。
実行時に言語ファイルを見る順番として、本体設定が英語の場合はまずvalues-enフォルダを確認し、それが無ければデフォルトのvaluesフォルダを使用します。
同様に本体設定が日本語の場合はまずvalues-jaフォルダを確認することになっています。
今回の場合、本体が英語設定の場合はvalues-enフォルダの中身を利用し、それ以外の言語だった場合はvaluesフォルダを利用することになります。
完全に国際化対応した場合は、valuesフォルダを英語で作成し、日本語をvalues-jaフォルダに入れるとよいでしょう。
で、第二回はまだですか><
Javaのリハビリをかねて非常に単純なアプリを作成します。
インプットした値を表示するだけの内容。
http://d.hatena.ne.jp/hkhumanoid/20090117/1232194093
こちらのサイトが非常に平易な解説をしてくれていますのでパクって参考にしてみます。
まずはプロジェクトの作成。
プロジェクト名「DisplayText」、アプリケーション名「DisplayText」、パッケージ名「com.example.display.text」、アクティビティ名「DisplayTextActivity」
ビルドターゲットはGoogleAPIsを選択します。
これAndroid2.1でかつGoogleAPIを使いたいとかだったらどうすればいいんだろう。
というかこのターゲットの違いってどういう意味があるのかわからん。
リンク先ではR.javaがsrc配下にありますが、最近のEclipseではgen配下に作成されます。
このファイルは自動更新され、それどころか任意に編集することができません。
それ以外はだいたい同じ作りのはず。
デフォルトで"Hello world"と表示するアプリが完成していますので、これから改造していきます。
まずはビューであるところの/res/layout/main.xmlを編集。
「レイアウト」編集だとドラッグでボタンを追加したり出来ますが、その配置を自由に移動したりは残念ながら出来ません。
「レイアウト」で部品の設置を行ったあと、「main.xml」で調整を行う流れになるでしょう。
「レイアウト」からとりあえずTextView、EditText、Button、TextViewの順に画面に部品を配置します。
するとmain.xmlにこんなタグが自動的に追加されます。
<TextView android:text="@+id/TextView01" android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content"> </TextView> <EditText android:text="@+id/EditText01" android:id="@+id/EditText01" android:layout_width="wrap_content" android:layout_height="wrap_content"> </EditText> <Button android:text="@+id/Button01" android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content"> </Button> <TextView android:text="@+id/TextView02" android:id="@+id/TextView02" android:layout_width="wrap_content" android:layout_height="wrap_content"> </TextView>
TextViewはベタテキスト、EditTextが文字入力フォーム(<;input type="text">)、Buttonが押しボタン(<input type="button">)です。
属性値として、textはテキストとして表示する値、idは全ての部品につく部品IDとなります。
値が"@+id/**"とよくわからない値になっていますが、これはJavaがXMLとプログラムの値を付き合わせたりする設定らしいです。
よく見るとR.javaあたりになんか増えてます。
layout_widthとlayout_heightはそのまま表示幅と高さです。
値は"wrap_content"とか"fill_parent"とかの定数なのですが、これらが何処で定義されているのかよくわかりませんでした。
"wrap_content"は必要最小限の幅と高さ、"fill_parent"が横幅いっぱいのようです。
部品が出来たのでプログラム側を作ってみます。
/src/com.example.display.text/DisplayTextActivity.java
package com.example.display.text; public class DisplayTextActivity extends Activity { private Button button; private EditText text; private TextView display; }
まずは使用するインスタンス変数を追加しただけ。
一行書くごとにエラーが出ますが、エラーが出たところにカーソルを持っていくと、解決策として該当クラスをインポートしてくれます。
Buttonって書くだけで勝手にimport android.widget.Button;を出してくれるとか便利すぎる。
ちなみに元ソースにあるinfoは使用していないので不要です。
あってもかまいませんが、最近のIDEだと使ってないぞとNoticeが出ます。
次にデフォルトのonCreate()を変更。
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 各種コンポーネント button = (Button) this.findViewById(R.id.Button01); text = (EditText) this.findViewById(R.id.EditText01); display = (TextView) this.findViewById(R.id.TextView02); // クリックイベント button.setOnClickListener(new MyClickAdapter()); }
setContentView(R.layout.main);はビューとして/res/layout/main.xmlを適用するという意味の決まり文句です。
IDの値が"@+id/EditText01"であれば、それを見つける方法はActivity.findViewById(R.id.EditText01)となります。
JavaScriptで言うところのdocument.getElementByIdみたいなものでしょうか。
さて、ButtonやTextViewなんかはViewクラスを継承していますが、View.setOnClickListener()というリスナーインターフェイスがあります。
OnClickListenerインターフェイスを実装したクラスを突っ込むと、クリック時にOnClickListener.onClick()メソッドを実行してくれます。
MyClickAdapterクラスを突っ込むことにしたので、実装を行います。
// クリック実装 private class MyClickAdapter implements OnClickListener { @Override public void onClick(View v) { Editable value = text.getText(); display.setText("こんにちは、" + value + "さん。"); } }
Editableってなんかよくわからないんですが、EditText.getText()がEditableで返ってくるみたいです。
Textって名前なのにStringじゃないのか。
で、これをこのままコピペしたところpublic void onClick(View v)でコンパイルエラーが発生しました。
public static interface OnClickListener{ public abstract void onClick(View view); }
> 型 DisplayTextActivity.MyClickAdapter のメソッド onClick(View) はスーパークラスのメソッドをオーバーライドする必要があります
え?
いやいやオーバーライドしてるじゃん。
解決策として表示されるのが、
> '@Override'注釈を除去します
なぜ???
http://d.hatena.ne.jp/waman/20090421/1240325650
> インターフェースに宣言されているメソッドをオーバーライドする際にも @Override アノテーションを使えるように拡張されました
> Java SE 6 から@Override アノテーションを付加することが可能になったのは、拡張される型 (super) がインターフェースの場合です(黄色い部分)。
実はできないので正解だった。
ということで'@Override'を削除して完成。
実行すると入力フォームとボタンが現れ、ボタンを押すと「ようこそ○○さん」と表示するフォームが完成しました。
世界一有名なプログラム、HelloWorldを作ってみたいと思います。
まずEclipseを起動、ファイル→新規→Androidプロジェクト。
プロジェクト名は単にEclipse上での見た目だけなのでわかりやすく適当に。とりあえず"HelloWorldProject"。
アプリケーション名はAndroid上に表示される名前なので慎重に。全然慎重ではなく"hello,world"。
パッケージ名はJavaのpackageで、プロジェクト毎に一意にします。"com.example.hello.world"。
ビルドターゲットは特に古いものにする必要もないので2.1にしておきましょう。
CreateActivityは適当に指定しておくと何もないページを一枚デフォルトで作成してくれます。scaffoldみたいなものです。たぶん。
"HelloWorld"としておきましょう。
完了ボタンを押すとさっくりとプロジェクトを作成してくれました。
では早速実装します。
といいたいところですが実はCreateActivityでHelloWorldができてるんですよねこれが。
Ctrl+F11を押すといきなりAndroidが立ち上がって暗闇にHelloWorldが表示されます。
さてどこで実行されているかというと、HelloWorldProject/src/com.example.hello.world/HelloWorld.javaが本体です。
android.app.Activity.setContentView()でHelloWorldProject/gen/com.example.hello.world/R.javaという画面のレイアウトを読んでいるようです。
これはIDEが勝手に作ってくれるのでこちらで編集する必要はありません。むしろ編集することができません。
で、HelloWorldProject/res/layout/main.xmlがビューでありこれが表示されるのですが、どうやってHelloWorld.javaとmain.xmlが結びつけられてるのかが全然わかりません。
どうなってんのこれ?
ひとつ注意点があって、HelloWorldProject/res/layout/main.xmlを編集中のままプログラムを実行すると、Error parsing XML: no element foundとかいうエラーが発生してmain.out.xmlというファイルが勝手に出来ます。
うっかり発生こうなってしまった場合、もう一度実行しようとしてもYour Project contains error(s), please fix them before runnning your applicationとか言われて二度と動かなくなります。
ここから復帰するためには、まずmain.out.xmlを削除し、プロジェクト→クリーンを実行しましょう。
なんなんだこれ。
HelloWorldProject/res/layout/main.xmlをダブルクリックするとレイアウト編集画面が開きます。
GUIでボタンをはめ込んだりしていくだけで見た目どおりの画面を作成できます。
ただドラッグで任意の位置に置いたりとかは出来ないみたい。残念。
やはりこの手の記事は画像がないと殺風景なのだが、画像撮るのめんどくせえ。