機能追加検討 (続々)

ええと TODO が以下らしい。

  • リスト選択して次画面表示
  • 更新処理
  • 更新後のリスト再表示
  • 削除処理における選択状態の表示

あとはサーバサイドとのやりとりになるのか。つうか複数削除って色々な意味でアレなんですが、とりあえず機能だけ盛り込む方向で。

とりあえず色が云々から

以下を参考にしつつ。

ええと、とりあえずレイアウトを作ります。今はデフォで用意されてるソレを使ってるのか。これはやっぱ adapter を自分で、って世界になるのかな。ハンズオン的にハードル高そうではありますが、拡張版向けってことで用意はしておくべきですね。
以下なカンジの行レイアウト作っておいて (名前は res/layout/row.xml で)、

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:background="@color/list_item"
>
<TextView 
  android:id="@+id/row_textview"
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content"
  android:layout_weight="1"
  android:textSize="20sp"
  android:padding="10dip"
  android:textColor="#000000"
/>
</LinearLayout>

あと、res/color/list_item.xml として以下を投入。

<?xml version="1.0" encoding="utf-8"?>
<selector 
  xmlns:android="http://schemas.android.com/apk/res/android">
<item 
  android:state_selected="false"
  android:state_pressed="false" 
  android:drawable="@color/white" />
<item 
  android:state_pressed="true" 
  android:drawable="@color/blue" />
<item 
  android:state_selected="true"
  android:state_pressed="false" 
  android:drawable="@color/blue" />
</selector>

で、以下な res/values/colors.xml を投入。

<resources>
<color name="white">#ffffff</color>
<color name="blue">#00ffff</color>
</resources>

あと、onCreate あたりで

        getListView().setBackground(R.color.white);

とかってしとくのかな。で、オレ Adapter を以下なカンジで定義するのかどうか。

    public class MyAdapter extends ArrayAdapter<String> {
        private String [] items;
        private LayoutInflater     inflater;
 
        public MyAdapter(Context context, int resourceId,
                String[] items) {
            super(context, resourceId, items);
            this.items = items;
            this.inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }
 
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = convertView;
            if (view == null) {
                view = inflater.inflate(R.layout.row, null);
            }
            String item = items[position];
            TextView textView = (TextView) view
                    .findViewById(R.id.row_textview);
            textView.setText(item);
            return view;
        }
    }

コンストラクタに String な配列を、って形でイージーにしてます。

盛り込み

盛り込んでみたんですが、青のまんまにはならないですね。とりあえずここはスルーして複数選択できてるか、な確認をしてみました。再び ActionBar Hands-on なナニを参考にしつつ以下。

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch (item.getItemId()) {
                case R.id.delete:
                    ListView lv = getListView();
                    SparseBooleanArray checkedItemPositions = lv.getCheckedItemPositions();
                    MyAdapter adapter = (MyAdapter) lv.getAdapter();
                    for (int i = 0; i < adapter.getCount(); i++) {
                        boolean checked = checkedItemPositions.get(i);
                        if (checked) {
                            Log.d(TAG, "posision (" + i + ") is checked");
                        }
                    }

                    mode.finish();
                    return true;

ええと位置が分かれば id 取得して云々、は可能なのか。

とりあえず

エントリ投入。サーバサイドとのやりとりを書いたら追記します。

追記

その前に修正な次画面表示を、ですね。以下なカンジで。

        lv.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> container, View view, int position,
                    long id) {
                Intent i = new Intent(RoRClientActivity.this, RoRClientEdit.class);
                try {
                    i.putExtra(NAME, mList.getJSONObject(position).getString("name"));
                    i.putExtra(ID, mList.getJSONObject(position).getString("id"));
                } catch (JSONException e) {
                    Log.e(TAG, "JSON Error : " + e);
                }
                i.setAction(Intent.ACTION_EDIT);
                startActivity(i);

大丈夫かな。新規か更新かは向こうでナニ。

紆余曲折の末

新規なソレが動いた。
もりこんだこととしては、サーバサイドとのやりとり以外で言うと編集画面から更新して戻ったら再検索して再表示あたりになるのかどうか。

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
     
        switch (requestCode) {
        case 123:
            if (resultCode == RESULT_OK) {
                updateList();
            }
        }
    }

で、編集画面なソレですが以下になっちゃいました。超微妙。

package jp.shuri.yamanetoshi.rorapiclient;

import java.util.ArrayList;
import java.util.List;

import jp.shuri.yamanetoshi.json.JSONFunctions;

import org.apache.http.NameValuePair;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class RoRClientEdit extends Activity {
    private final String TAG = "RoRClientEdit";
    
    private String mode;
    private String id;
    private String name;
    
    private String URL = "http://shrouded-tundra-4125.herokuapp.com/";
    private DefaultHttpClient mDefaultHttpClient = new DefaultHttpClient();
    private String POST = "tasks";
    private String PUT = "tasks/";
    private String PLEASE_WAIT = "please wait...";
    
    private EditText mEditText;
    private ProgressDialog mProgressDialog;
    
    private List<NameValuePair> mParams;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        id = getIntent().getStringExtra(RoRClientActivity.ID);
        name = getIntent().getStringExtra(RoRClientActivity.NAME);
        mode = getIntent().getAction();
        
        Log.d(TAG, "id is " + id);
        Log.d(TAG, "name is " + name);
        Log.d(TAG, "mode is " + mode);
        
        mProgressDialog = new ProgressDialog(this);
        mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        mProgressDialog.setMessage(PLEASE_WAIT);
        
        mEditText = (EditText)findViewById(R.id.edittext);
        mEditText.setText(name);
        
        Button btn = (Button)findViewById(R.id.button);
        btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                mParams = new ArrayList<NameValuePair>();
                SpannableStringBuilder sb = (SpannableStringBuilder)mEditText.getText();
                String str = sb.toString();
                mParams.add(new BasicNameValuePair("[task][name]", str));

                mProgressDialog.show();
                                
                if (mode.equals(Intent.ACTION_INSERT)) {
                    new Thread(new Runnable() {

                        @Override
                        public void run() {
                            try {
                                 JSONFunctions.POSTfromURL(URL + POST, mDefaultHttpClient, mParams);
                                setResult(RESULT_OK, new Intent());
                                mProgressDialog.dismiss();
                                finish();
                            } catch (Exception e) {
                                   Log.e(TAG, "Exception + " + e);
                            }
                        }
                            
                    }).start();
                } else if (mode.equals(Intent.ACTION_EDIT)) {
                    new Thread(new Runnable() {

                        @Override
                        public void run() {
                            try {
                                 JSONFunctions.PUTfromURL(URL + PUT + id, mDefaultHttpClient, mParams);
                                setResult(RESULT_OK, new Intent());
                                mProgressDialog.dismiss();
                                finish();
                            } catch (Exception e) {
                                   Log.e(TAG, "Exception + " + e);
                            }
                        }
                            
                    }).start();
                    
                }
            }
            
        });
    }
}

削除を盛り込んだら機能的にはひとまず、なのかどうか。削除も微妙に苦労。削除処理のトリガが以下で

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch (item.getItemId()) {
                case R.id.delete:
                    SparseBooleanArray checkedItemPositions = getListView().getCheckedItemPositions();
                    MyAdapter adapter = (MyAdapter) getListView().getAdapter();
                    
                    //mProgressDialog.show();
                    mHandler.post(new Runnable() {

                        @Override
                        public void run() {
                            mProgressDialog.show();
                        }
                        
                    });

                    requestDelete(mode, adapter, checkedItemPositions);

requestDelete の定義が以下。

        private void requestDelete(ActionMode mode, MyAdapter adapter, 
                SparseBooleanArray checkedItemPositions) {
            Log.d(TAG, "requestDelete() start");

            mMode = mode;
            mAdapter = adapter;
            mCheckedItemPositions = checkedItemPositions;
            
            new Thread(new Runnable() {

                @Override
                public void run() {
                    Log.d(TAG, "adapter.getCount() is " + mAdapter.getCount());
                    for (int i = 0; i < mAdapter.getCount(); i++) {
                        boolean checked = mCheckedItemPositions.get(i);
                        if (checked) {
                            Log.d(TAG, "posision (" + i + ") is checked");
                            try {
                                String id = mList.getJSONObject(i).getString("id");
                                Log.d(TAG, "URL is " + BASE_URL + DELETE + id);
                                JSONFunctions.DELETEfromURL(BASE_URL + DELETE + id, 
                                        mHttpClient);
                            } catch (Exception e) {
                                Log.d(TAG, "e is " + e);
                            }
                        }
                    }
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mMode.finish();
                            mProgressDialog.dismiss();
                            updateList();
                        }
                    });
                }
                
            }).start();
        }

リファクタ必須と言っても過言ではないですね。

とは言え

JSONFunctions なソレはきちんと動いている様子なので Github に push しておく方向。他のソレ達も Github に置くか。
あと、基本的に ActionBar Hands-on なソレを手本にすれば何とかなるようなので、こっちも Final なソレを見える場所に置いておく方向。