タスクオブジェクトをボタンとして表示する
それでは、上記の仕様を実現するコードをみていきましょう。なお、本稿のサンプルコードは記事に添付していますので、ダウンロードし、併せてご覧ください。
まず、MainActivityのレイアウトファイルである「activity_main.xml」を変更します。
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ScrollView" android:layout_height="match_parent" android:layout_width="match_parent"> <LinearLayout android:id="@+id/main_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="vertical" > </LinearLayout> </ScrollView>
各タスクはボタンとしてコードによってLinearLayout内に縦に配置していくのですが、タスクをたくさん登録すると、スマホの画面に収まらなくなります。そんなときには、スクロールバーが出れば便利なのですが、LinearLayoutはスクロールバーを表示しません。そこで、ScrollViewを使います。LinearLayoutをScrollViewで囲むことで、ボタンが1画面に収まらないときにスクロールバーが表示されます。
ScrollView―複数のButtonという単純な階層構造にしたい所ですが、ScrollViewは子コンポーネントを一つしか持つことができないため、ScrollView―LinearLayout―複数のButtonという形をとっています。
次にタスクをボタンとして、表示するコードをみていきましょう。onCreateメソッドで呼び出しているcreateButtonsメソッドがボタンを作成していきます。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // SDKの初期セットアップ(アプリで一回だけ) NCMB.initialize(getApplication(), getString(R.string.app_key), getString(R.string.client_key)); currentUser = NCMBUser.getCurrentUser(); if (currentUser == null) { // 未ログインのときは、 Intent intent = new Intent(MainActivity.this,LoginActivity.class); startActivity(intent); } else { createButtons(); } } private void createButtons() { LinearLayout LLayout = (LinearLayout) findViewById(R.id.main_layout); LLayout.removeAllViews(); Button btn0 = new Button(this); btn0.setText("タスクはまだ選択されていません"); btn0.setId(0); btn0.setBackgroundColor(Color.GRAY); btn0.setOnClickListener(new OnClickListener() { public void onClick(View v) { if (v.getTag() == null) { } else { // 計測中のタスクがあるとき finCurTask();(a) } } }); Space spc = new Space(this);(1) LLayout.addView(spc,600,10); LLayout.addView(btn0,600,160); getCurTask();(b)
まず、findViewById(R.id.main_layout)で、LinearLayoutオブジェクトを見つけて、removeAllViews()ですべての子コンポーネントを削除しています。onCreateメソッドが複数回呼びされても大丈夫なようにボタンを一旦、全部削除してから作成します。
btn0として「タスクはまだ選択されていません」とテキスト表示するボタンを作成します。このボタンが押された場合の処理は後述します。(1)でコンポーネント(ビュー部品)に空白をあけるためのSpaceのオブジェクトを作成し、まず配置します。縦方向に少し空白をあけてから、btn0を配置します。
getCurTaskメソッドの説明も後回しにして、タスクをボタンとして表示する部分の説明に進みましょう。
NCMBでは、データストアのクラスに対してクエリを発行して、オブジェクトを検索、取得することができます。
NCMBQuery<NCMBObject> query = NCMBQuery.getQuery("TaskClass");(2) query.orderByDescending("updateDate"); query.findInBackground(new FindCallback<NCMBObject>() { @Override public void done(List<NCMBObject> result, NCMBException e){ for (int i =0 ,n = result.size(); i < n; i++ ) { NCMBObject task = result.get(i);(3) createButton(i,task.getObjectId(),task.getString("taskName")); } } }); }
(2)では、NCMBQueryクラスのgetQueryメソッドでTaskClassから、クエリを作成しています。NCMBQueryでは、RDB同様に条件式によるレコードの抽出や並び替えが可能です。このサンプルではorderByDescending("updateDate")と更新日の降順に並べ替えしています。
findInBackgroundメソッドで非同期にオブジェクトを取得します。取得したオブジェクトはNCMBObject型のListであるresultに格納されますので、(3)で一つずつtaskオブジェクトに取り出します。そして、インデックスであるiとtask.getObjectId()で取得したオブジェクトID,task.getString("taskName")で取得したタスク名を引数にcreateButtonメソッドを呼び出します。
createButtonメソッドが各タスクをボタンとして、LinearLayoutに追加します。
private void createButton(int i,String objId,String taskName) { LinearLayout LLayout = (LinearLayout) findViewById(R.id.main_layout); Button btn = new Button(this);(4) btn.setText(taskName); btn.setTag(objId); btn.setId(i+1); btn.setOnClickListener(new OnClickListener() { public void onClick(View v) { // 各タスクのボタンが押されたら Button btn0 = (Button) findViewById(0);(5) if (btn0.getTag() == null) { // タスクが未選択のとき // タスク名とObjIdのセット Button btn = (Button)v; btn0.setText(btn.getText()); btn0.setTag(btn.getTag()); btn0.setBackgroundColor(Color.RED); getTask((String)btn.getTag());(6) } else { } } }); Space spc = new Space(this); LLayout.addView(spc,600,10); LLayout.addView(btn,600,160); }
(4)でButtonオブジェクトbtnを生成して、setTextメソッドでタスク名を、setTagメソッドでオブジェクトIDを、setIdメソッドでインデックス+1をボタンのプロパティにセットします。setOnClickListenerメソッドで登録しているこのボタンのonClick時の処理の説明はちょっと後回しにします。addViewメソッドでSpaceとともにButtonを追加しています。
たとえば、TaskClassに「テスト」と「メールサーバー構築」というタスク名のレコードが登録されていると、次のようにボタンが3つ表示されました。
最初のボタンに「タスクはまだ選択されていません」と表示されているときは、まだ時間の計測を開始していません。
データストアのクラスに登録するオブジェクトのことをレコードと呼んだり、オブジェクトと呼んだりしています。NCMBのデータストアにおいてはレコード=オブジェクトと考えてください。RDBとの比較でレコードと考えた方がわかりやすいときはレコードと呼んでいます。