SwipeRefreshLayout覚え書き

SwipeRefreshLayout

Support Library revision 19.1.0からSwipeRefreshLayoutという新しいViewGroupが追加された。 これはいままで引っ張って更新とかPullToRefreshとか呼ばれていた機能を実装できるものになる。 以後長々と書くが、公式サンプルのほうがわかりやすくてタメになるのでそっちを見たほうがいい。

実装

まず、Support Library revision 19.1.0が使える状態にしておく。

次に、利用したい画面のレイアウトファイルにSwipeRefreshLayoutを配置する。 この時、SwipeRefreshLayoutの直接の子はひとつだけになるようにする。

<android.support.v4.widget.SwipeRefreshLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/swipelayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ListView
        android:id="@id/android:list"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</android.support.v4.widget.SwipeRefreshLayout>

ソースコード側ではSwipeRefreshLayout.OnRefreshListenerの実装を行う。 このインターフェイスにはジェスチャ操作が発生したときに呼び出されるonRefresh()というメソッドしかない。 大半のアプリはここから通信などの非同期処理を呼び出すことになるはずだ。 また、ローディング中インジケータの色設定も画面側で行う。 SwipeRefreshLayout#setColorScheme()に4色も渡さないといけないので大変だ。 ちなみに渡さないとインジケータが真っ黒になる。

public class RefreshFragment extends Fragment implements 
        SwipeRefreshLayout.OnRefreshListener {

    private SwipeRefreshLayout mSwipeRefreshLayout;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.refreshlayout, null);
        mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipelayout);
        
        // 色設定
        mSwipeRefreshLayout.setColorSchemeResources(R.color.red,
                R.color.green, R.color.blue,
                R.color.orange);
        // Listenerをセット
        mSwipeRefreshLayout.setOnRefreshListener(this);
        return view;
    }

    @Override
    public void onRefresh() {
        // 更新処理を実装する
        // ここでは単純に2秒後にインジケータ非表示
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                // 更新が終了したらインジケータ非表示
                mSwipeRefreshLayout.setRefreshing(false);
            }
        }, 2000);
    }
}

追記:SwipeRefreshLayout.setOnRefreshListenerをしていないとプルダウン時にNullPointerExceptionが発生するので注意!

ListFragmentでは

ListFragmentの場合、レイアウトファイルを直接触りたくない。 そこで、onCreateViewの中でListViewの親レイアウトとしてコード内で挿入を行う。 しかもAndroidのバージョンによってcanChildScrollUpの処理を変えなくてはいけないため、SwipeRefreshLayoutも継承が必要…。 結構無理矢理感があるが、公式のサンプルでもそうなっているので、多分これでいいんだろう。

おまけ

SwipeRefreshLayout.setEnabled(false)でジェスチャと表示中のプログレスインジケータが無効化される。 ただし、無効化されたあとにSwipeRefreshLayout.setRefreshing()によってプログレスインジケータの表示/非表示を切り替えることができる。 これにより、プログレスインジケータを表示するだけのレイアウトとして利用することもできるようだ。 便利な場面もあるかもしれない。