Apps Amuck Blog 2日目

Apps Amuck Blog
http://appsamuck.com/blog/index.php/2008/11/01/full-list-of-31-days-of-iphone-sdk-apps/

2日目:"UIImageView Animations"
2日目は画像でアニメーションを作成するアプリ。がんばるぞー。


■新規プロジェクトを作成
新規Xcodeプロジェクトを作成
iOS > Application > View-based Applicationを選択し、「選択」ボタン
プロジェクト名 bonfire

■UI設計用のウィンドウを起動
"xxxViewController.xib"をダブルクリックし、Interface Builderを起動。

■アニメーションに使用する画像を追加
以下のリンクからソースコードをダウンロード。bonfire/imagesにある。
ソースコード

XcodeのResources > 追加 > 既存のファイル追加
デスティネーショングループのフォルダに項目をコピーする(必要な場合)にチェックをつけて、追加。

■UIImageViewの追加
InterfaceBuilderのViewにライブラリにあるUIImageViewをドラッグ。

■bonfireViewController.h
UIImageViewの宣言を追加。

@interface bonfireViewController : UIViewController {
	IBOutlet UIImageView *imageView;
}


■bonfireViewController.m
アニメーションを設定。

- (void)viewDidLoad {
    [super viewDidLoad];
	imageView.animationImages = [NSArray arrayWithObjects:    
	[UIImage imageNamed:@"campFire01.gif"],
	[UIImage imageNamed:@"campFire02.gif"],
	[UIImage imageNamed:@"campFire03.gif"],
	[UIImage imageNamed:@"campFire04.gif"],
	[UIImage imageNamed:@"campFire05.gif"],
	[UIImage imageNamed:@"campFire06.gif"],
	[UIImage imageNamed:@"campFire07.gif"],
	[UIImage imageNamed:@"campFire08.gif"],
	[UIImage imageNamed:@"campFire09.gif"],
	[UIImage imageNamed:@"campFire10.gif"],
	[UIImage imageNamed:@"campFire11.gif"],
	[UIImage imageNamed:@"campFire12.gif"],
	[UIImage imageNamed:@"campFire13.gif"],
	[UIImage imageNamed:@"campFire14.gif"],
	[UIImage imageNamed:@"campFire15.gif"],
	[UIImage imageNamed:@"campFire16.gif"],
	[UIImage imageNamed:@"campFire17.gif"], nil];
	imageView.animationDuration = 1.75;
	imageView.animationRepeatCount = 0;
	[imageView startAnimating];
	[self.view addSubview:imageView];
}


■InterfaceBuilder上のUIImageViewとソースコードの関連付け
bonfireViewController.xibのFile 's Ownerを選択し、Attributes InspectorのConnectionsのOutletsにあるimageViewの右の○をデザイン上のUIImageViewにドラッグ。

■実行すれば動くはず。

Apps Amuck Blog 1日目

Hello Worldを表示するiphoneアプリを作った後に、いったい何を作ろうかと悩んでいたところ、こんなものを発見。

Apps Amuck Blog
http://appsamuck.com/blog/index.php/2008/11/01/full-list-of-31-days-of-iphone-sdk-apps/

1日1つ簡単なアプリを作ろうというもの。
1日目は、明日(深夜0時)までの残り時間を表示するアプリ。

URLの内容に沿って進めてみるものの、よくわからなくなってしまう。結局最終的に同じようなものができればいいかなということで、途中違うやり方になってしまったが、なんとか完成。

■新規プロジェクトを作成
OS > Application > View-based Applicationを選択し、「選択」ボタン
プロジェクト名:MinutesToMidnight

■InterfaceBuilder起動
"xxxViewController.xib"をダブルクリックし、Interface Builderを起動。

■ウィンドウの背景を黒に変更Attribute Inspector(デフォルトで右にあるウィンドウ)のAttributesタブのBackgroundをBlack Colorに設定。

■表示用ラベルの設定
Library(デフォルトで左にあるウィンドウ)からLabelをView(デフォルトで真ん中にあるウィンドウ)にドラッグ。適当な大きさに変更。font sizeは40ぐらい。"Label"はLibraryウィンドウの下の検索フィールドに入力すれば探せる。
LayoutのAlignmentを真ん中寄せにして、TextをRedに設定。

MinutesTomidnightViewController.h
Xcodeに戻って、LabelとTimerの宣言。Timerは一定間隔で特定メソッドを繰り返し呼び出すのに使用する。updateLabelはラベルに表示する時刻を計算するメソッド。

@interface MinutesToMidnightViewController : UIViewController {
	IBOutlet UILabel *countdownLabel;
	NSTimer *timer;
}
-(void)updateLabel;
@end


■MinutesTomidnightViewController.m
updateLabelメソッド詳細。

-(void)updateLabel {
    NSDate *now = [NSDate date];
	NSCalendar *calendar = [NSCalendar currentCalendar];
	NSDateComponents *comps = 
	[calendar components:(NSHourCalendarUnit | NSMinuteCalendarUnit 
						  | NSSecondCalendarUnit) fromDate:now];
	
	NSInteger hour = 23 - [comps hour];
	NSInteger min = 59 - [comps minute];
	NSInteger sec = 59 - [comps second];
	countdownLabel.text = [NSString stringWithFormat:@"%02d:%02d:%02d", hour, min,sec];
}


updateLabelメソッドを1秒ごとに呼び出す部分

- (void)viewDidLoad {
	timer = [NSTimer scheduledTimerWithTimeInterval: 1.0
		target: self
		selector: @selector(updateLabel)
		userInfo: nil
		repeats: YES];
    [super viewDidLoad];
}


■ラベルとcountdownLabelの関連付け
InterfaceBuilderでラベルを選択。Attribute InspectorのConnectionsタブでnew Referencing Outletsの右の○をMinutesToMidnightViewController.xibのFile's Ownerにドラッグし、countdownLabelを選択。

■実行すれば動くはず。

ソーシャルアプリに挑戦

mixiアプリを作ってみよう。

「そのためには、Webアプリケーションサーバが必要です。」

えー。個人ではとても用意できない。

そこで、これ。

Google App Engine

クラウドサービスでWebアプリケーションを公開できる。
無料。月間500万PVまでOK。

十分過ぎる。Googleすごいな。

Android翻訳目次

Android1.1 ディベロッパーガイド

Android開発者ブログ

Android1.0 SDKドキュメント(一部)

メモ帳エクササイズ1

2009/4/7 まだ途中ですが、長いので一旦アップします。原文では、step13まであります。
2009/4/22 随分久しぶりの更新となってしまいましたが、Step6〜8を追加しました。

原文: http://developer.android.com/guide/tutorials/notepad/notepad-ex1.html

                                                                                                              • -

このエクササイズでは、メモを新規追加できる簡単なメモリストを作成します。ただし、メモの編集はここではまだできません。実際に手を動かしながら、以下の項目を学習していきます。

  • ListActivitiesの基礎とメニューオプションの作成や処理
  • メモの保存に必要なSQLite databaseの使い方
  • SimpleCursorAdapterを使ってデータベースのカーソルからListViewに対してデータをバインドする方法
  • リストのViewを配置する方法、メニューに項目を追加する方法、メニュー選択時の処理方法等の画面レイアウトの基礎

ステップ1
EclipseでNotepadv1プロジェクトを開きましょう。

Notepadv1プロジェクトが出発点です。まずは、Hello Worldチュートリアルでも見かけたお決まりの手順を実行します。
1. ファイル > 新規 > Androidプロジェクトで新規Androidプロジェクトを作成します。
2. 新規Androidプロジェクトダイアログで、外部ソースからプロジェクトを作成を選択します。
3. 参照をクリックし、(準備段階でダウンロードした)NotepadCodeLabをコピーした場所まで移動します。その後、Notepadv1を選択し、選択をクリックしてください。
4. プロジェクト名にNotepadv1、ロケーションに選択したパスが入力されているか確認してください。
5. 完了をクリックしてください。Notepadv1プロジェクトが開き、Eclipseのパッケージエクスプローラ上に表示されます。

AndroidManifest.xmlでエラーが発生した場合や、Android zipファイルに関する問題が発生した場合は、プロジェクトを右クリックして、Androidツール > プロジェクトプロパティを修正を選択してください(プロジェクトがライブラリファイルの間違った場所を参照していた場合は、修正してくれます)。

ステップ2
NotesDbAdapterクラスを見てみましょう。このクラスは、メモデータを保持したり更新したりすることができるSQLiteデータベースへのデータアクセス処理をカプセル化しています。

クラスの最上部には定数が宣言されていて、アプリケーションがデータベースの適切なフィールド名からデータを取得する際に使われます。また、データベース作成用文字列も定義されており、データベースが存在しない場合には新規のデータベースを作成します。

今回はデータベース名を”data”とし、テーブルは”notes”というテーブル1つだけです。”notes”テーブルには3つのフィールド”_id”, “title”, “body”があります。”_id”は通常、データベースを参照または更新する際に一意に特定できるものでなければなりません。他の2つのフィールドはデータを保存する単純なテキストフィールドです。

NoteDbAdapterのコンストラクタにはContextが渡されており、Androidオペレーティングシステムの一部分と何らかのやり取りをすることができるようになっています。これは、Androidシステムを利用したいクラスに一般的に用いられる手法です。ActivityクラスはContextクラスの派生クラスなので、Contextが必要な時に単にActivityからthisを渡せばいいだけです。

open()メソッドは内部クラスDatabaseHelperのインスタンスを生成しています。DatabaseHelperはSQLiteOpenHelperのサブクラスです。データベースを作成またはオープンするのにgetWriteableDatabase()を呼んでいます。

close()は単にデータベースをクローズし、コネクションに関連するリソースを解放します。

createNote()は渡された新規メモのタイトルとボディをもとに、データベースにメモデータを作成します。新規メモの作成が成功すると、メソッドは新規作成したメモの_id値を返します。

deleteNote()は渡されたrowIdからメモを特定し、データベースから削除します。

fetchAllNotes()はデータベースの全メモのカーソルを返すクエリを発行します。query()メソッドの呼び出しをもう少し深く見てみましょう。最初のフィールドは問い合わせを行うデータベースのテーブル名です(この例では、定数DATABASE_TABLEの値として”notes”が渡されています)。次のフィールドは、取得したい列のリストです。今回の場合は、_id, title, bodyを受け取りたいので、String配列で列名を指定しています。残りのフィールドは、順にselection, selectionArgs, groupBy, having, orderByです。nullを渡すと全データがグルーピングなしのデフォルト順で返ってきます。詳細は、「SQLiteデータベース」を参照してください。


問い合わせの結果は、行の集合ではなくカーソルで返されます。これにより、Androidはリソースを効率的に使用できます。メモリ上に大量のデータを直接展開する代わりに、カーソルが必要に応じてデータを取得・解放するため、行数が多いテーブルをより効率的に処理できるようになります。

fetchNote()は、fetchAllNotes()と類似していますが、指定したrowIdに一致するメモを1つだけを返します。fetchNote()で使用しているquery()メソッドは、fetchAllNotes()で使用しているものと若干異なります。(trueをセットしている)最初の引数は結果を重複なしで返すかどうかを指定するものです。selection(4つ目の引数)では、”where _id =”の後に続くrowidに一致するデータだけを検索するよう指定しています。最終的には、1行だけを指し示すカーソルが返されます。


データへのアクセスと編集
このエクササイズでは、データを格納するのにSQLiteデータベースを使用しています。あなたのアプリケーションだけがデータへアクセスしたり、データを編集したりする場合には、SQLiteでも構いません。ただ、他のActivityにアクセスさせたり、データを編集させたりしたい場合には、ContentProviderを利用してデータを吐き出さなければなりません。
詳細は「ContentProvier」や「データストレージ」の章に記述されています。SDKのsamples/フォルダのメモ帳サンプルには、ContentProviderの作成方法例も記述されています。

ステップ3
res/layoutのnotepad_list.xmlを開いて、中を見てみましょう(XMLを表示するため、場合によっては下のxmlタブを選択する必要があるかもしれません)。

現時点では、ほとんど何も記述されていないレイアウト定義ファイルが表示されるはずです。レイアウトファイルについて学習すべきことを以下に挙げます。

  • 全てのAndroidレイアウトファイルは、以下のヘッダ行から始めなければなりません
<?xml version="1.0" encoding="utf-8"?>
  • その次の行はレイアウトの指定である場合が多いです(必ずという訳ではありません)。今回の例では、LinearLayoutを使用します。
  • AndroidXMLネームスペースは、最上位のコンポーネント内、もしくはXMLレイアウト内で必ず定義しなければなりません。例えば以下の記述を追加することで、ファイルの以降の行でandroid:タグを使用することができます。xmlns:android="http://schemas.android.com/apk/res/android"


レイアウトとActivity
ほとんどのActivityクラスは、自分に関連するレイアウトを保持しています。レイアウトは、Activityがユーザに見せる”顔”なのです。今回の場合のレイアウトは、画面全体に表示され、メモリストを表示します。
ただし、Activityに対して画面全体に表示するレイアウトしか設定できない訳ではありません。フローティングレイアウト(例えば、ダイアログやアラートなど)を設定することもできますし、レイアウトを全く使わなくても構いません(使用するレイアウトを指定しなかった場合、Activityはユーザに表示されません)。


ステップ4
リストを保持するレイアウトを作成してみましょう。以下のようにLinearLayout要素の内部にコードを追加してください。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

  <ListView android:id="@android:id/list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
  <TextView android:id="@android:id/empty"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/no_notes"/>

</LinearLayout>
  • ListViewとTextViewのid文字列の@記号は、XMLパーサが以降のid文字列をIDリソースとして解析すべきであることを意味しています。
  • ListViewとTextViewは同時には表示されず、一度に表示されるものはどちらか一方だけです。ListViewはノートリストを表示される際に使われます。一方、TextViewはノートが1つも存在しない場合に表示されます(res/values/strings.xmlで文字列リソースにデフォルト値として”No Notes Yet!”が定義されています)。
  • idであるlistとemptyは、Androidプラットフォームのよって提供されるため、android:のプレフィックスが必要です(e.g. @android:id/list)
  • idにemptyとあるViewはListAdapterにListViewのデータが存在しない場合に、自動的に表示されます。データが存在しない時、ListAdapterはデフォルトでidがemptyのViewを検索しますが、ListViewのsetEmptyView(View)メソッドを利用して、データが存在しない場合のデフォルトViewを変更することもできます。

皆さんのプロジェクトにあるRクラスがプロジェクトで定義したリソースであるのに対して、android.Rクラスはプラットフォームで提供されている定義済みリソースです。android.Rクラスにあるリソースは、”android:”のプレフィックスを利用することで、XMLファイルで使用することができます。

ステップ5
ListViewでノートリストを作成するために、各行のViewを定義しましょう。

1. res/layoutの下にnotes_row.xmlという名前の新規ファイルを作成します。
2. 以下を追加してください(注記:XMLヘッダが再び登場します。最初のノードではAndroidXMLネームスペースを定義しています。)

<?xml version="1.0" encoding="utf-8"?>
<TextView android:id="@+id/text1"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>


上記のViewは各行のタイトルを表示するもので、テキストフィールドを1つだけ保持しています。

今回の例では、text1という名前の新規idを作成します。idの@の後にある+は、もしそのidが存在しなければ、リソースとして自動的に作成されることを意味しています。
3. ファイルを保存します。

プロジェクトのR.javaクラスを開いて、中を見てみましょう。notes_rowとtext1の新規定義があるはずです。R.javaに定義があれば、ソースコードからリソースを参照することができます。


リソースとRクラス
Eclipseプロジェクトのres/以下のフォルダは、リソース置き場です。res/以下のフォルダやファイルは特殊な構造になっています。
このフォルダで定義されたリソースとファイルは、Rクラスの項目と対応しており、アプリケーションから簡単にアクセスすることができます。Rクラスは、eclipseプラグインによって、res/フォルダの内容をもとに自動生成されます(コマンドラインを使用している場合は、aaptツールによって生成されます)。それだけではなく、アプリケーションの一部としてバンドルされデプロイも実行されます。

ステップ6
次に、Notepadv1クラスのソースコードを開いてみましょう。以下のステップでは、このクラスを修正し、メモを表示するリストアダプタにしていきます。また、新規メモの追加にも対応します。

最初に、Notepadv1をListActivityと呼ばれるActivityのサブクラスから派生したクラスにします。このクラスはリストを処理する機能を保持し、例えば、画面上にリスト項目番号を表示したり、リスト内の項目を移動したり、選択したりできるようにします。

Notepadv1クラスの既存のコードを見てみましょう。メモ番号を作成するmNoteNumberという、現時点では使用されていないprivateフィールドがあります。

onCreate, onCreateOptionsMenu, onOptionsItemSelectedの3つのオーバーライドメソッドも用意されています。これから、このメソッドを実装していきます。

  • onCreate()メソッドはActivityが開始された際に呼び出されます。Activityのmainメソッドのようなものです。実行時にリソースやアクティビティの状態を設定するのに使われます。
  • onCreateOptionsMenu()メソッドは、アクティビティをメニューに配置する際に使われます。ユーザがメニューボタンを押した際に表示される選択可能なリスト(新規メモ作成など)を保持します。
  • onOptionsItemSelected()メソッドは、メニューから発生するイベントを処理するのに使われます(ユーザが「メモの作成」項目を選択した場合など)

ステップ7
ActivityからListActivityへNotepadv1の継承元を変更しましょう。

public class Notepadv1 extends ListActivity


注記: Eclipseを使ってListActivityをNotepadv1にインポートする場合、上記の変更を反映後、WindowsLinuxの場合はctrl-shift-O、Macの場合はcmd-shift-Oでインポートを実行することができます。

ステップ8
onCreate()メソッドを実装しましょう。

(画面の上端に表示される)Activityのタイトルをセットし、XMLで作成したnotepad_listレイアウトを使って、メモデータにアクセスするNotesDbAdapterインスタンスを生成し、メモタイトルと一緒にリストを配置します。

1. onCreateメソッドでは、savedInstanceStateを引数としてsuper.onCreate()を呼び出します。
2. setContentView()を呼び、R.layout.notepad_listを渡します。
3. クラスのトップで、型がNotesDbAdapter のprivateクラス変数mDbHelperを宣言します。
4. onCreate()メソッドに戻り、NotesDbAdapterインスタンスを生成して、mDbHelperフィールドに代入します(thisをDBHelperのコンストラクタに渡します)。
5. mDbHelperのopen()メソッドを呼び出し、データベースを開きます(または作成します)。
6. 最後に、新規メソッドfillData()を呼び、データを取得して、helperを使ってListViewに配置します。このメソッドはまだ定義していません。

onCreate()はこのようになります。

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.notepad_list);
        mDbHelper = new NotesDbAdapter(this);
        mDbHelper.open();
        fillData();
    }


mDbHelperフィールドも忘れずに宣言してください(mNoteNumber宣言の下に適切に)。

private NotesDbAdapter mDbHelper;

メモ帳チュートリアル

Android 1.0とほとんど変わっていませんでした。
原文: http://developer.android.com/guide/tutorials/notepad/index.html

                                                                                                              • -

チュートリアルでは、実際に手を動かしてメモ帳アプリケーションを開発しながら、Androidフレームワークの理解を深めていきます。Androidフレームワーク上のアプリケーションをビルドするツールについても併せて学習します。プロジェクト未作成の状態からスタートし、シンプルなメモ帳アプリケーションを開発する過程をご紹介します。その際、プロジェクトのセットアップ方法、アプリケーションロジックやユーザインターフェースの開発方法、アプリケーションのコンパイルや実行方法についても具体例とともに解説していきます。

チュートリアルでは、メモ帳アプリケーションの開発過程をいくつかのエクササイズに分割しています(詳細は下記を参照)。各エクササイズは複数のステップから成り立っています。各エクササイズのステップに従って進めていけば、徐々にアプリケーションが構築され、洗練されていくでしょう。エクササイズの各ステップは詳細に解説されており、アプリケーションを完成するための全ソースコードも提供しています。

チュートリアルを終わらせた頃には、正常に動作するAndroidアプリケーションが完成し、Android開発で重要な多くの考え方を体得しているはずです。さらに複雑な機能をアプリケーションに追加したければ、サンプルコードドキュメントのメモ帳アプリケーションにある別の実装方法を参考にすることもできます。

チュートリアルの対象読者
チュートリアルは開発経験者、特にJava言語の知識を持っている方を対象にしています。Javaアプリケーションを実装したことがない方でも、本チュートリアルを進めることできますが、進むペースが落ちてしまうかもしれません。

チュートリアルは、AndroidプラグインがインストールされたEclipse開発環境を使用しています。Eclipseを使わなくてもエクササイズに従ってアプリケーションを構築することはできますが、Eclipse特有のステップに対してご自身の環境ではどのように実行すれば良いのかを知っておく必要があります。

エクササイズの準備
チュートリアルは、Androidアプリケーションの基本的な考え方と専門用語を理解していることが前提となります。先に進む前に「アプリケーションの基礎」を読んでおくことをお勧めします。

また、本チュートリアルは”Hello World”で提供されている基礎的な知識の上に構成されています。”Hello World”には、Androidアプリケーションの構築に必要なEclipse開発環境のセットアップについて解説されていますので、本チュートリアルを読む前に読んでおくことをお勧めします。

本章で準備すること
1. project exercises archive (.zip)のダウンロード
2. アーカイブファイルを解凍して、マシンの任意の位置に配置
3. NotepadCodeLabフォルダを開く

NotepadCodeLabフォルダ中には、6つのプロジェクトファイルがあります(Notepadv1, Notepadv2, Notepadv3, Notepadv1Solution, Notepadv2Solution, Notepadv3Solution)。Notepadv#は各エクササイズのスタート時点のプロジェクトです。Notepadv#Solutionはエクササイズの結果出来上がるプロジェクトです。もしエクササイズ実行中に問題が発生した場合には、Notepadv#Solutionと作業中のプロジェクトとを比較してみてください。

エクササイズ
以下のテーブルには、チュートリアルの各エクササイズがカバーする開発範囲が示されています。各エクササイズは前のエクササイズが完了していることが前提となっています。

Ex1 ここがスタートです。簡単なメモリストを作って新規メモを追加できるようにします。ただし、編集はまだできません。ListActivityの基礎とメニューオプションの作成や処理について実際に手を動かしながら学ぶことができます。メモを保存するためにSQLite databaseを使います。
Ex2 アプリケーションに2個目のActivityを追加し、新規Activityの構築、Androidマニフェストの追記、Activity間のデータの受け渡し、より高度な画面レイアウトの使用についてデモを行います。また、startActivityForResult()を使用して別のActivityを呼び出し、結果を返す方法についても解説します。
Ex3 アプリケーションにライフサイクルイベントの処理を追加し、ライフサイクルを通してアプリケーションの状態を保持します。
補足 Eclipseデバッガの使い方と、生成されるライフサイクルイベントをデバッガで参照するデモを行います。本セクションは必須ではありませんが、一読することを強くお勧めします。

その他参考資料

  • チュートリアルでカバーしていない概念を浅く広く紹介した資料として、「Android共通タスク」を参照してください。
  • Android SDKには完全に動作するサンプルアプリケーションが多数含まれており、さらに学習したい方にとっては最高の教材となるでしょう。サンプルアプリケーションはダウンロードしたSDKのsamples/か、本ドキュメントのサンプルコードのセクションで参照することができます。
  • チュートリアルSDKのsamples/に含まれるメモ帳アプリケーションの一部を抽出したものであり、完全に同じものではありません。チュートリアル完了後、samples/にあるメモ帳アプリケーションを読み解いてみることを強くお勧めします。チュートリアルで作成したアプリケーションにはなかった、以下のような興味深い点が数多くあります。
    • メモリストをストライプ表示するカスタムリストを設定する。
    • draw()メソッドをオーバーライドして、ライン入りメモを表示するカスタムテキスト編集Viewを作成する。
    • メモ用のContentProviderを完全に実装する。
    • 自動的に保存するだけではなく、変更点を廃棄し元に戻す。
                                                                                                                        • -


Android翻訳目次へ

レイアウトの宣言

この章は、親なのか子なのかが入り組んでいて、ややこしかったです。
原文: http://developer.android.com/guide/topics/ui/declaring-layout.html

                                                                                                              • -

レイアウトとは、Activity(アクティビティ)が保持するユーザインターフェース構造を表しています。UIの配置構成やユーザに表示する全ての要素を保持しています。レイアウトは以下の2種類の方法で定義することができます。

  • XMLでUIの要素を定義する

Androidでは、View(ビュー)クラスと、ウィジェットやレイアウトのようなViewクラスのサブクラスを処理するわかりやすいXML言語を提供しています。

  • ランタイムでレイアウト要素を生成する。

ソースコード上でViewとViewGroup(ビューグループ)オブジェクトを生成し、そのプロパティを操作することができます。

Androidフレームワークでは、アプリケーションのUIを開発するために、上記の方法のどちらか、または両方を使えるように柔軟性を持たせています。例えば、デフォルトのレイアウトはXMLで定義しておいて、実行時に画面に表示するオブジェクト(XMLで定義したレイアウト要素も含む)を変更するようなソースコードを記述することも可能です。

XMLでUIを定義することの利点は、アプリケーションのプレゼンテーション処理を、振る舞いを制御するコードから分離できることです。UIの記述がソースコードから分離されているので、ソースコードの修正や再コンパイルをせずにUIを修正することができます。異なる画面環境、異なる画面サイズ、異なる言語ごとにXMLレイアウトを作成することも可能です。加えて、XMLでレイアウトを宣言すれば、UI構造の可視化が容易になり、プログラムをデバッグしやすくなります。そのようなことから、本ドキュメントでは、XMLでレイアウトを定義する方法に焦点を当てて解説します。実行時にViewオブジェクトを生成する方法については、ViewGroupとViewクラスのリファレンスを参照してください。

一般的に、UIのエレメントを宣言するXMLの語句は、クラスやメソッドのネーミングルール及び構造にほぼ準拠しており、エレメント名がクラス名、属性名がメソッド名に対応しています。この対応関係はとても直感的ですので、エレメントに対応するクラスや、属性に対応するメソッドを推測することができます。しかしながら、全ての語句が完全にこのルールに従ってはいないことに注意してください。ごく稀に若干ネーミングルールが違う場合があります。例えば、EditTextエレメントはtext属性を持っていますが、対応するメソッドはEditText.setText()です。


「一般的なレイアウトオブジェクト」では、様々なレイアウトタイプを学習することができます。開発チュートリアルとして、「Hello Views」もあります。

EclipseAndroid Development Tools(ADT)プラグインでは、XMLのレイアウトプレビューを提供しています。XMLファイルを開いて、レイアウトタブを選択してみてください。
レイアウトのデバッグ時には、Hierarchy Viewerツールも試してみてください。エミュレータや端末上でデバッグ中にレイアウトのプロパティ値が表示されるだけでなく、パディング/マージンの指標が付いたワイヤフレームの描画や、レンダリング済のViewの表示もサポートします。


【ページ内目次】

XMLの記述
Androidでは、XMLを利用してUIのレイアウトと画面エレメントを素早く設計することができます。入れ子構造のエレメントを利用して、HTMLのウェブページを作成することもできます。

各レイアウトファイルには、ルートエレメントを必ず1つ含めなければなりません。ルートエレメントはViewかViewGroupでなければなりません。ルートエレメントを定義した後は、子エレメントとしてレイアウトオブジェクトやウィジェットを追加し、徐々にView階層を組み立てていきます。以下は、TextViewとButtonを保持する LinearLayoutを使ったXMLレイアウトの例です。


    
    


XMLでレイアウトを定義後、Androidプロジェクトのres/layoutディレクトリに拡張子が.xmlのファイルを保存すれば、適切にコンパイルされます。

各属性については、後ほど解説します。


APIリファレンスドキュメントのUI関連のクラスには、クラスのメソッドに対応するXML属性がリスト化されています。利用可能なXMLのエレメントや属性に加え、XMLファイルのフォーマットについての詳細は、「レイアウトリソース」を参照してください。

XMLリソースのロード
アプリケーションのコンパイル時に、各XMLレイアウトファイルもコンパイルされ、Viewリソース内に配置されます。コンパイルされたレイアウトリソースは、Activity.onCreate()コールバックメソッドでロードしてください。setCotentView()を呼び出して、引数にレイアウトリソースの参照をR.layout.の形式で渡します。例えば、XMLレイアウトをmain_layout.xmlで保存した場合、以下のようになります。

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView.(R.layout.main_layout);
}


ActivityのonCreate()コールバックメソッドは、Activityが起動されたときに、Androidフレームワークによって呼び出されます(詳細は、「アプリケーションの基礎」のライフサイクルを参照してください)。

属性
各ViewとViewGroupは、様々なXML属性をサポートしています。特定のViewオブジェクトに特化した属性(例えばTextViewがtextsize属性をサポートしているなど)は、Viewクラスの拡張クラスで定義されている属性です。全てのViewオブジェクトで共通の属性もありますが(id属性など)、これはルートのViewクラスで定義されている属性です。その他に、”レイアウトパラメータ”属性も存在します。これは、Viewオブジェクトの親にあたるViewGroupによって定義されている属性で、Viewオブジェクトのレイアウトを決定付ける属性です。

ID
どんなViewオブジェクトでも、ツリー内のViewを一意に識別することができるIDを持っています。アプリケーションコンパイル時に、このIDはInteger型として参照されますが、XMLレイアウトファイルでは多くの場合、String型として割り当てられています。IDは、すべてのViewオブジェクトで共通のXML属性であり、頻繁に使われます。ID体系に関しては、以下のXMLタグを見てください。

android:id="@+id/my_button"


文字列の最初にあるアットマーク記号(@)は、XMLパーサが@以下の文字列をリソースIDとして解析すべきであることを示しています。プラス記号(+)は、リソース(R.javaファイル内)に新規に追加する名前であることを意味しています。ちなみに、Androidフレームワークでは様々なリソースIDを標準で提供しており、このAndroidリソースIDを参照する際にはプラス記号は必要なく、代わりに以下のようにandroidパッケージのネームスペースを追記しなければなりません。

android:id="@android:id/empty"


上記は、ローカルリソースクラスを参照する代わりに、androidパッケージのネームスペースを使ってandroid.RリソースクラスからIDを参照しています。


Viewを作成し、アプリケーションからViewを参照する一般的な方法を以下に示します。

1. レイアウトファイル内にViewまたはウィジェットを定義し、それにユニークIDを割り当てる。


2. レイアウトのIDを利用して、Viewオブジェクトのインスタンスを取得する(一般的にはonCreate()メソッドで取得する場合が多い)。

Button myButton = (Button) findViewById(R.id.my_button);


ViewオブジェクトのID定義は、RelativeLayout(相対レイアウト)を作成する際に重要になります。相対レイアウトでは、ユニークなIDを利用して、あるViewが関連する別の兄弟Viewのレイアウトを定義できるからです。

IDはツリー全体を通してユニークにする必要はありませんが、検索を実行したい部分はユニークにすべきです(ツリー全体を検索する場合もあるので、可能であればツリー全体を通して完全にユニークにするのがベストな方法です)。

レイアウトパラメータ
layout_somethingという名前のXMLレイアウト属性はViewのレイアウトを定義するものであり、自分の親に当たるViewGroupによって定義する内容が決められます。

各ViewGroupクラスでは、ViewGroup.LayoutParamsを拡張したクラスを保持しています。このサブクラスは、自分の子Viewのサイズや位置を定義するプロパティを保持しています。つまり、下記の図のように、親であるViewGroupが子であるView(ViewGroupも含む)のレイアウトパラメータを保持しています。


LayoutParamsのサブクラスごとに、値をセットする方法が異なることに注意してください。子であるViewがそれぞれ異なるLayoutParamsクラスを定義するような場合であったとしても、子Viewはその親にとって適切なLayoutParamsを判断して設定しなければなりません。

すべてのViewGroupは幅と高さ(layout_width, layout_height)を保持しており、各Viewがそれらを定義しなければなりません。また、多くのLayoutParamsが任意項目としてマージンやボーダーを保持しているため、あまりやりたくはないでしょうが、正確なViewの大きさを自分で定義することができます。ただ、多くの場合は、Viewの表示内容に合わせたサイズにするか、親であるViewGroupと同じ大きさにするかのどちらかでしょう(前者はwrap_content, 後者はfill_parentを使います)。設定可能な項目は「利用可能なリソース」ドキュメントで定義されています。

レイアウト位置
Viewの形状は四角形です。Viewは位置情報(左端と上端の座標)と、サイズ情報(高さ、幅)を保持しています。位置とサイズはピクセル指定です。

getLeft(), getTop()メソッドを実行し、位置情報を取得することも可能です。前者の戻り値は四角形の左端のX座標です。後者は四角形の上端のY座標です。このメソッドはどちらも、親オブジェクトからの相対位置を返します。例えば、getLeft()が20を返したとしたら、それは親オブジェクトの左端から右へ20ピクセル進んだ位置にいることを意味しています。

加えて、不要な計算を避けるために、getRight()とgetBottom()メソッドも提供されています。前者は四角形の右端、後者は下端の位置を返します。例えば、getRight()の戻り値は以下の計算式の結果とほぼ同じ値となります。
getLeft() + getWidth()

サイズ、パディング、マージン
Viewのサイズは幅と高さで表現されます。実際には、Viewは幅と高さのペアを2つ保持しています。

最初のペアは、measured widthとmeasured heightです。このサイズ指定では、自分の親に対してどのぐらいの大きさにするかを定義します。getMeasuredWidth()とgetMeasuredHeight()で取得することができます。

2番目のペアは単純に、widthとheightです。drawing width、drawing heightとも呼ばれます。このサイズ指定は、描画時に描画される画面上の実際のViewサイズです。このサイズは、そうする必要性はないものの、measured widthやmesured heightとは異なる値にすることもできます。widthとheightはそれぞれgetWidth()とgetHeight()で取得することができます。

サイズを計算する際、Viewはパディングも考慮に入れます。パディングは、Viewの左、上、右、下に対してピクセルで指定できます。パディングは指定されたピクセル数だけ、Viewを余白で埋めてくれます。例えば左のパディングが2であれば、左端から2ピクセル右に進んだ位置からViewの内容が表示されます。パディングはsetPadding(int, int, int, int)メソッドで定義され、getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom()で取得できます。

Viewは、パディングはサポートしますが、マージンはサポートしません。ただし、ViewGroupではマージンをサポートしています。詳細は、ViewGroupとViewGroup.MarginLayoutParamsを参照してください。

サイズに関する詳細は、「サイズ指定」を参照してください。

                                                                                                                        • -


Android翻訳目次へ