ListViewでOverScrollする
Android SDK 2.3より、OverScrollが利用できるようになりました。OverScrollとは画面端まで到達した段階から遊びを持ってスクロールできる機能で、UIの向上に寄与します。サンプルプロジェクトを用意しました。GoogleCodeのTechBoosterのこちら(SVNが必要です)からどうぞ。
OverScrollを使うのに必要な(代表的な)メソッドは以下の通りです
OverScroll関連メソッド
メソッド | 概要 |
---|---|
View#overScrollBy | オーバースクロールに関する設定 |
View#onOverScrolled | オーバースクロールした結果を受け取る |
AbsListView#setOverScrollMode | モード設定(ListViewなどで有効) |
上記のうち、View#overScrollByやView#onOverScrolledがproctectedなメソッドです。そのためオーバースクロールの実装に当たっては、ListViewなどを継承した独自クラスを作成する必要があります。
本記事は
- hdk_embeddedの日記 – OverScrollでListViewをビョーンってする方法
- Y.A.M の 雑記帳 – Android Overscroll を使う簡単な方法
を参考に作成しました。より詳しい情報を必要な場合は、上記サイトを是非、参考にしてみてください。
サンプルコードは続きから
OverScrollの実装(ListView)
まずは、オーバースクロールを実装するため、独自ListViewを作成します。
OverScrollListView.java
1 2 3 4 5 6 7 8 9 | public class OverScrollListView extends ListView { private final String TAG = "ListView" ; public OverScrollListView(Context context, AttributeSet attrs) { super (context, attrs); setOverScrollMode(OVER_SCROLL_ALWAYS); } ・・・省略・・・ } |
コンストラクタ内でsetOverScrollModeメソッドを呼び出しています。このメソッドはオーバースクロールのモード設定を行います。
6行目のOVER_SCROLL_ALWAYSは、Listがどのような状態であっても常にオーバースクロールを行います。
setOverScrollModeの引数には
- OVER_SCROLL_ALWAYS (デフォルト)
- OVER_SCROLL_IF_CONTENT_SCROLLS(スクロールが必要な時にのみ許可)
- OVER_SCROLL_NEVER(許可しない)
が指定できます。OVER_SCROLL_IF_CONTENT_SCROLLSでは表示したいコンテンツが画面より大きくて、はみ出ている、またはスクロールバーが表示されているときにのみオーバースクロールを許可します。
以下のようなリストをもったActivityでオーバースクロールを使ってみます。
(Android2.3ではListViewの端に到達した場合、標準ではオレンジ色に発光するエフェクトが追加されました)。
overScrollByをオーバーライドする
1 2 3 4 5 6 7 8 9 10 | // オーバースクロール @Override protected boolean overScrollBy( int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) { // オーバーライド return super .overScrollBy( 0 , deltaY, 0 , scrollY, 0 , scrollRangeY, 0 , 200 , isTouchEvent); } |
overScrollByメソッドは9つの引数を持ちます。これはX座標とY座標それぞれに指定が可能なためで、実際の要素として5つに分類できます。
詳しくは以下の表を確認してください。
overScrollByメソッドの引数
引数 | 概要 |
---|---|
int deltaX | スクロールした量のX方向の増分 |
int deltaY | スクロールした量のY方向の増分 |
int scrollX | X座標方向の量(今までのスクロールした総和) |
int scrollY | Y座標方向の量(今までのスクロールした総和) |
int scrollRangeX | X座標方向のスクロール幅 |
int scrollRangeY | Y座標方向のスクロール幅 |
int maxOverScrollX | X座標方向のスクロール最大量 |
int maxOverScrollY | Y座標方向のスクロール最大量 |
boolean isTouchEvent | TouchEventからの呼び出しフラグ |
第9引数のisTouchEventはonTouchEventからの呼び出しを判定するためのフラグです。overScrollByメソッドは実装者が独自に呼び出すことが可能な一方、onTouchEventの処理中にフレームワークによって呼び出されています。このような理由から第9引数は、onTouchEventでの処理と重複しないために必要とされています。
サンプルでは簡略化のためY座標(縦方向)に対する操作のみを行います。サンプルコードではXに関する要素を0として、Yに関する要素を残しています。第8引数のmaxOverScrollYに関しては互換性維持のためフレームワークのデフォルトでは0、つまりオーバースクロールしない設定になっています。ここは適当な値(今回は200)に変更します。
onOverScrolledメソッドの実装
オーバースクロールした結果はonOverScrolledメソッドに通知されます。サンプルではデバッグ表示のためにのみ利用しています。
1 2 3 4 5 6 7 8 9 10 11 | //オーバースクロール発生時 @Override protected void onOverScrolled( int scrollX, int scrollY, boolean clampedX, boolean clampedY) { Log.v( "myListView" , "scrollX:" + scrollX + " scrollY:" + scrollY + " clampedX:" + clampedX + " clampedY:" + clampedX); super .onOverScrolled(scrollX, scrollY, clampedX, clampedY); } |
サンプルをAndroid2.3に対応した端末で動かした場合、以下のようなログ出力になります。
LogCat
1 2 3 4 5 6 7 8 9 10 11 | 01 - 03 17 : 27 : 55.799 : VERBOSE/ListView( 330 ): scrollX: 0 scrollY: 0 clampedX: false clampedY: false 01 - 03 17 : 27 : 56.549 : VERBOSE/ListView( 330 ): scrollX: 0 scrollY: 10 clampedX: false clampedY: false 01 - 03 17 : 27 : 56.630 : VERBOSE/ListView( 330 ): scrollX: 0 scrollY: 28 clampedX: false clampedY: false 01 - 03 17 : 27 : 56.699 : VERBOSE/ListView( 330 ): scrollX: 0 scrollY: 52 clampedX: false clampedY: false 01 - 03 17 : 27 : 56.769 : VERBOSE/ListView( 330 ): scrollX: 0 scrollY: 89 clampedX: false clampedY: false 01 - 03 17 : 27 : 56.839 : VERBOSE/ListView( 330 ): scrollX: 0 scrollY: 116 clampedX: false clampedY: false 01 - 03 17 : 27 : 56.909 : VERBOSE/ListView( 330 ): scrollX: 0 scrollY: 138 clampedX: false clampedY: false 01 - 03 17 : 27 : 56.979 : VERBOSE/ListView( 330 ): scrollX: 0 scrollY: 149 clampedX: false clampedY: false 01 - 03 17 : 27 : 57.049 : VERBOSE/ListView( 330 ): scrollX: 0 scrollY: 165 clampedX: false clampedY: false 01 - 03 17 : 27 : 57.119 : VERBOSE/ListView( 330 ): scrollX: 0 scrollY: 192 clampedX: false clampedY: false 01 - 03 17 : 27 : 57.189 : VERBOSE/ListView( 330 ): scrollX: 0 scrollY: 200 clampedX: false clampedY: false |
補足
独自Viewを使う際はレイアウトファイルでのListViewの指定が多少変わった書き方にしないと動きません。
layout/main.xml
1 2 3 4 5 6 7 8 | <?xml version= "1.0" encoding= "utf-8" ?> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:orientation= "vertical" android:layout_width= "fill_parent" android:layout_height= "fill_parent" > <org.jpn.techbooster.sample.overscrolledActivity.OverScrollListView android:id= "@+id/listView" android:layout_width= "fill_parent" android:layout_height= "wrap_content" /> </LinearLayout> |
また、ListViewにつかうArrayに関しては詳細を省略しています。Activity側のコードは以下の通りです。
OverScrolledActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public class OverScrolledActivity extends Activity { private String[] list = { "alpha" , "bravo" , "charlie" , "delta" , "echo" , "foxtrot" }; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.main); //適当なArrayAdapterを作成。今回は簡単なStringで。 ArrayAdapter<String> adapter = new ArrayAdapter<String>( this , android.R.layout.simple_list_item_1, list); //Listにアダプタを設定 OverScrollListView listView = (OverScrollListView) findViewById(R.id.listView); listView.setAdapter(adapter); //Debug用にコールバックを登録 listView.setOnItemClickListener( new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { OverScrollListView listView = (OverScrollListView) parent; //ItemをToastで表示 String item = (String) listView.getItemAtPosition(position); Toast.makeText(OverScrolledActivity. this , item, Toast.LENGTH_LONG).show(); } }); } } |
Listの要素、ArrayAdapterの接続方法などは通常のListViewとかわりありません。
About The Author
ひつじ(mhidaka)
Software Engineerだよ。DroidKaigi Organizer / Androidと組込とRe:VIEW。techbooster主宰。mhidaka's writings http://booklog.jp/users/mhidaka 技術書典! http://techbookfest.org