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
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をオーバーライドする
// オーバースクロール @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メソッドに通知されます。サンプルではデバッグ表示のためにのみ利用しています。
//オーバースクロール発生時 @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
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
<?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
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とかわりありません。