2013年12月7日土曜日

PullToRefreshで下からの引っ張りにも対応する(実装編)

さて、前回準備した環境で実際に「引っ張って更新」を試してみます。

いまもう27時とかめっちゃ眠いので文章で説明するより実際にコードを
見た方がわかりやすいかと思いますので、詳細はコードを貼るとして
とりあえず要点だけ。

・通常の ListView のかわりに PullToRefreshListView を使用

・上下両方の引っ張りに対応するよう Mode.BOTH を設定

・ PullToRefreshListView の setOnRefreshListener にて
 「引き下げ/上げて更新」の挙動を設定
 →OnRefreshListener2 で、引き下げ/上げ のそれぞれについて
  異なる動作を設定できます。
 →ただ、前回書いた通り、同名(PullToRefresh)の異なるライブラリを
  使用している場合、OnRefreshListener2 がなかったりしますので
  ご注意ください。


で、実際のサンプルコードはこんな感じになります。
(上から引っ張る→初期状態に戻す、下から引き上げ→項目を追加する)

■MainActivity のレイアウト(activity_main.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <com.handmark.pulltorefresh.library.PullToRefreshListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>


■リストの項目用レイアウト(list_item.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/listItemText"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center" />

</LinearLayout>


■コード(MainActivity.java)
public class MainActivity extends Activity {

    private ArrayList<String> mListItems;
    private PullToRefreshListView mListView;
    private SampleListAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //項目初期化
        initializeItems();

        //ListView 設定
        mListView = (PullToRefreshListView)findViewById(R.id.listView);
        mAdapter = new SampleListAdapter();
        mListView.setAdapter(mAdapter);

        //PullToRefresh 設定
        mListView.setMode(Mode.BOTH);//モード指定:上下からの引っ張りに対応
        mListView.setOnRefreshListener(new OnRefreshListener2<ListView>(){

            //上から引っ張った場合
            @Override
            public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
                initializeList();
                new FinishRefresh().execute();
            }

            //下から引き上げた場合
            @Override
            public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
                addItem();
                new FinishRefresh().execute();
            }

        });
    }

    //項目を初期化
    private void initializeItems(){
        mListItems = new ArrayList<String>(Arrays.asList("Item 1", "Item 2", "Item 3"));
    }

    //リストを初期状態に戻す
    private void initializeList(){
        initializeItems();
        mAdapter.notifyDataSetChanged();
    }

    //リストにアイテムを追加
    private void addItem(){
        int count = mListItems.size();
        mListItems.add("Item " + Integer.toString(++count));
        mAdapter.notifyDataSetChanged();
    }

    //アダプタクラス
    private class SampleListAdapter extends BaseAdapter{

        @Override
        public int getCount() {
            return mListItems.size();
        }

        @Override
        public Object getItem(int index) {
            return mListItems.get(index);
        }

        @Override
        public long getItemId(int index) {
            return index;
        }

        @Override
        public View getView(int index, View view, ViewGroup arg2) {
            if(view == null){
                LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                view = inflater.inflate(R.layout.list_item, null);
            }
            TextView textView = (TextView)view.findViewById(R.id.listItemText);
            textView.setText(mListItems.get(index));
            return view;
        }
    }

    //リスト更新終了
    private class FinishRefresh extends AsyncTask<Void, Void, Void>{
        @Override
        protected Void doInBackground(Void... params) {
            return null;
        }

        @Override
        protected void onPostExecute(Void result){
            mListView.onRefreshComplete();//更新アニメーション終了
        }
    }
}


で、細かいことは確認してないんですが、どうやら onPullDownToRefresh
とかの中で直接  onRefreshComplete を呼んでも効かない模様?
(「更新中」状態のままとなってしまうみたいです。)

onPullDownToRefresh とかって非メインスレッドで呼ばれてるってこと
なんですかね?あ、「自分でソース確認しろ」とか言うの禁止ね。
 とりあえず↑みたいに AsyncTask の onPostExecute で呼び出してやると
期待する挙動になるみたいですが。。。


一応こんな感じで動きます。

【上から下に引っ張る】


【下から上に引き上げる】




どうでもいいけど、最近ホント夜更かしできなくなったなぁ…
昔はゲーム買ったら31時とかまで平気でやってたのになw
コレがアラサークオリティってやつか。

0 件のコメント:

コメントを投稿