NotePad Exercise 2
これは次の参考資料(webページ)の補足です。
http://developer.android.com/intl/ja/resources/tutorials/notepad/index.html
>>Resourcesタブ>>左欄 チュートリアル NotePad Tutorial
全訳ではありません。上記の資料とあわせて参考にして下さい。特に、ソースコードは本資料(いま読んでいる資料)には載せていませんので上記の原資料を見て下さい。
第2のActivityを追加します。これによってユーザはメモを作成し編集できます。コンテキストメニューを使ってメモを削除できます。
狙い
* 新Activityの作成とmanifestへの追加.
* startActivityForResult()を使って他のActivityを起動する。
* BundleオブジェクトでActivity間でデータの受け渡しをする。Passing data between
* 進んだlayout
* コンテキストメニューの作成
Step 1
Eclipseのプロジェクトを作る。
Notepadv1と同じ。
* strings.xml 追加された文字列がある。
* Notepadv2 class, 新しい定数、新フィールド(mNotesCursor)
* fillData() 新しいフィールド追加onCreate()は変わらず。
* オーバライドされたメソッドが新しく追加
onCreateContextMenu(), onContextItemSelected(), onListItemClick(), onActivityResult())
Step 2
コンテキストメニューを作成するメソッドを作成 onCreateContextMenu()
メモを削除するのに使う。
Notepadv2 class.
1. ListViewの各行にコンテキスト]メニューを追加する。registerForContextMenu()(Activityのメソッド) を呼び、ListView(一般にはコンテキストメニューを設定するView)を引数として渡す。(onCreate()内)。ListViewの参照はgetListView()(ListActivityのメソッド)で取得する。
2. onCreateContextMenu() メソッドの処理を作ります。オプションメニューとよく似ている。. (この演習では)メモを削除するために1行だけ追加します。
オプションメニューに比較して、引数として、Viewと選択されたオブジェクトに関する情報を含むクラスが増えています。
onCreateContextMenu(Menu menu, View v ,ContextMenuInfo menuInfo)
Step 3
コンテキストメニューのイベントリスナーonContextItemSelected()
分かりにくい点:item. getMenuInfo() の戻り
android.view.ContextMenu.ContextMenuInfo(interface)
ここに何を設定するかはコンテキストメニューの作成者に依存する。AdapterViewクラスを使った場合は、android.widget.AdapterView.AdapterContextMenuInfoクラスが実装している。その内容はAPIリファレンスに記述されている。ただし、idはArrayAdapterの場合どうなるか?(明記されていないのでテストして確認要)
こうして取得したidを使ってDBから対応する行を削除する。
Step 4
createNote()
NoteEdit クラスを使って、メモを作るためのIntentを作ります。startActivityForResult()メソッドを呼び出してIntentを発火します(Intentはこのような用語が使われている---イベント扱い)
Intent i = new Intent(this, NoteEdit.class); --- NoteEditクラスはの後で実装
startActivityForResult(i, ACTIVITY_CREATE);
このIntentの形式は特定のクラスを的にします。この場合はNoteEdit。IntentはAndroid OSと対話する必要があるのでContext(this)を引数にします。
startActivityForResult()は的になったActivityが完了すると、呼び出したActivityを呼び出します。そのリスナーはonActivityResult() 後に実装。
Step 5
onListItemClick()
onContextItemSelected()は長押しするときの処理。onListItemClick()はクリックの処理。対象のView(リストの行)は同じ。
引数ListView object、クリックされたView リスト内の位置、クリックされた項目の行Id(mRowId)
この演習で使うのはリスト内の位置
Intentを作り、編集するデータ(title ,body,mRowId)をそのIntentに追加する。
step4と同じNoteEdit Activityを起動する。
* putExtra() 編集するデータ(title ,body,mRowId)をBundleクラスに設定.
* the moveToPosition() 該当するデータ行をポイントする。
* 起動されたActivityから戻ってきたときに、どのIntentに対応するか分かるようにrequest code(ACTIVITY_CREATE、ACTIVITY_EDIT)を付ける。
Step 6
onActivityResult()
createNote() と onListItemClick() は非同期のIntent呼び出しを使う。そのため、callbackのためのハンドラーが必要です。それがonActivityResult()。
onActivityResult()はオーバライドされるメソッドで、Activityが結果を戻すときに呼ばれる(startActivityForResult()で起動した場合だけ)。
引数
* requestCode —元のIntent呼び出しの際、指定されたrequest code(今回はACTIVITY_CREATE 又は ACTIVITY_EDIT のどちらか)。
* resultCode —呼び出しの結果コード(又はエラーコード)。すべて問題がないときはゼロであるはずだ。非ゼロは何かが失敗したことを意味します。標準の結果コードが利用できます。または自身でコード(定数)を作ることもできます。
* intent —結果を戻したActivityが作成したIntent。この中のextrasの中に戻すデータを設定できます。
startActivityForResult() と onActivityResult() の組み合わせは非同期のRPC(remote procedure call) と考えられます。Activityが他のActivityや共有のServiceを起動する、お薦めの方法です。
* ACTIVITY_CREATE と ACTIVITY_EDIT のactivity結果を扱う。」
* createの場合、extrasからtitle と body を引き出し、それを新しいメモを作るのに使います。
* editの場合、同じようにmRowIdを引き出し、DBの中のメモを更新するのに使います。
* fillData()は最後に最新のデータにします。
Step 7
note_edit.xml
これはNote EditorのUIコードです。
これは、われわれが扱った今までのUIのうち一番洗練されたものです。
コードをタイプする際、忍び込む問題を避けるためにソースを提供しています(研修の場合、その間違いが、理解を深める最大のチャンスなので、自分でタイプしたほうがいい)。xmlは大文字/小文字の違いと構造について厳しいので、これらがlayoutに伴う問題の通常の原因です)
新しいパラメータ
android:layout_weight この演習では1を設定している。
layout_weightはLinearLayoutsの中で使われ、そのlayout内でのViewへの重要度を割り当てます。すべてのViewのlayout_weightのデフォルトは0です。これは、各Viewが、自身を表示するのに最小の領域を確保する意味です。正の数を与えることは、親のViewの利用できる領域の残りの部分をlayout_weightの値に応じて分割します。
例 text label layout_weight設定なし text editは2個ありlayout_weight設定あり。一つが1、もう一つが2であるとすると、text labelに必要な最小領域をとった後、2個のtext editは1:2に領域を分ける。
ネストしたlayout
この例では、水平方向のLinearLayoutが垂直のLinearLayoutの中にネスとしている。
Step 8
NoteEdit class :android.app.Activityを継承
NoteEditクラス新規作成
1. com.android.demo.notepad2 パッケージを右クリック >>New >> Class
2. ダイアログの各フィールドに入力する。
3. 継承するクラスのフィールド:enter android.app.Activity (Activityとだけ入力し、Ctrl-Spaceを入力するとコード支援が表示され正しいパッケージとクラスが分かる。
4. Finish.
onCreateの(宣言)作成
5. できたNoteEditクラスのソース画面で右クリック、select Source > Override/Implement Methods...
6. onCreate(Bundle)を見つけ、隣のチェックボックスをチェック。
7. Click OK.
Step 9
NoteEditクラスのonCreate()メソッド
(onCreateの完成版はStep10)
1.note_edit.xml layout fileを使ってcontent viewを設定する。
2.titleとbody及び確認ボタンへのハンドルを取得する。NoteEditはこのハンドルでtitleとbodyの値を取り出したり設定したりする 確認ボタンにユーザが押したときに発行するイベントを付ける。
3.クラスの上部にprivateフィールドLong mRowId を宣言する。onCreate()内で初期化
4.呼び出しのIntentの付けられたextras BundleでActivityに渡された値をunbundleする(Bundleはname-value対。unbundleはその対のうち、値を各変数に設定すること)。それらの値をtitleとbody用のtext editに設定し、ユーザが編集できるようにする。mRowIdを取り出し保存する。mRowIdでユーザが編集しているメモを特定できる。nullが設定されないように判断を含める。
5. 確認ボタンのリスナーonClickListener() を作成
匿名内部クラスを使います。(匿名内部クラスがよく理解できない人は、将来、このコードを参考にしてbuttonに貼り付ければいい--- 原本にはこう書いていますが理解しないでできるとは思わないので、市販本等で習得して下さい)
Step 10
onClick()(OnClickListenerの実装--- 続き)
ユーザが確認ボタンを押したときに走るコード
コードの目的は、edit textからtitleとbodyを取り出し、それを戻りBundleに詰めて、NoteEdit Activityを呼び出したActivityに戻す。編集操作の場合は、mRowIdもBundleに含める。NotepadV2クラスがそのメモの変更を(DBに)書き戻せる。
1. Bundleを生成しtitleとbodyをそれに入れる
2. このBundleを新Intentに設定する。
* (startActivityForResult()の結果戻しの場合) Intentはデータの運び屋に過ぎない。。
* setResult() は結果コードと戻りIntentを設定する。
* finish()はActivityが完了したことをシグナルするために使う。このとき、呼んだActivityに結果が戻る。
Step 11
新Activityをmanifestに登録する。
1. AndroidManifest.xml をダブルクリック
2. 底部のApplicationタブ
3. Application ノードセクションのAdd...をクリック
上部にラジオボタンが現れると、"Create a new element at the top level, in Application"をチェック。.
4. "(A) Activity"がダイアログペインの中で選択されていることを確認する。
5. 新 "Activity"ノードをクリック。nameフィールドにNoteEdit とタイプ。enter
(この段階ではxmlを直接編集することをお薦めします)
Step 12
実行
======
メモ(資料と関係ありません)
MenuItem(interface)
android.view.ContextMenu.ContextMenuInfo
item.getMenuInfo => 戻りの型ContextMenu.ContextMenuInfo(interface, Marker? APIリファレンスにメソッドは規定されていいない)
(実装)=> android.widget.AdapterView.AdapterContextMenuInfo
フィールドが規定されている。
public long id The row id of the item for which the context menu is being displayed.
public int position The position in the adapter for which the context menu is being displayed.
public View targetView The child view for which the context
以上