2つを比べてみると、iPhoneでは最上部までスクロールしてもまだスクロールすることができるのに対し、Androidではコンテンツの最上部までスクロールしてしまうと、それ以上スクロールを試みてもうんともすんとも言わないといった違いがあり、これがストレスの原因の一つと思われる。
そこで、Androidでもびろーんってのを実装してみようと考えたわけだが、Androidでは簡単に実現する方法が見当たらない。※Android 2.3 (Gingerbread)ではOverscrollを使う簡単な方法があるらしい。
なので今回は、OverscrollをAndroid 2.2以下でも簡単に実装することができる方法を考えてみた。そんでもってついでに公開してみた。Google Codeにサンプルプロジェクトごと公開してみたので、興味があればご参照あれ。
まず、画面を構成する要素はScrollViewとその子要素(今回はLinearLayoutとした)である。ScrollViewは子要素を一つしか設定できない。子要素の中身には適当なViewを配置してみる。
- <ScrollView
- android:id="@+id/scroll_view"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <LinearLayout
- android:id="@+id/content"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- android:paddingTop="200dip"
- android:paddingBottom="200dip">
- <TextView
- android:layout_width="fill_parent"
- android:layout_height="300dip"
- android:text="First Content."
- android:textSize="50dip"/>
- <TextView
- android:layout_width="fill_parent"
- android:layout_height="300dip"
- android:text="Second Content."
- android:textSize="50dip"/>
- <TextView
- android:layout_width="fill_parent"
- android:layout_height="300dip"
- android:text="Third Content."
- android:textSize="50dip"/>
- </LinearLayout>
- </ScrollView>
ScrollViewの子要素であるLinearLayoutには、OverScrollするための余白としてpaddingTopおよびpaddingBottomに200dipを設定しておく。
次にTouchEventListenerを作成し、ScrollViewへ登録する。
- scrollView.setOnTouchListener(new MyOnTouchListener(scrollView, contentView));
TouchEventListenerではACTION_UPをフックし、ScrollViewのgetScrollY()メソッドで現在のスクロール位置を取得する。現在のスクロール位置がpadding領域であった場合は、画面の端にpadding領域を除いたContent部分がぴったり表示されるようにスクロールする。といった感じ。
多分、コードのほうがわかり易い。
- @Override
- public boolean onTouch(View v, MotionEvent event)
- {
- scroller.forceFinished(true);
- mScrollView.removeCallbacks(task);
- if (event.getAction() == MotionEvent.ACTION_UP)
- {
- int displayHeight = mScrollView.getHeight();
- int contentTop = mContentView.getPaddingTop();
- int contentBottom = mContentView.getHeight() - mContentView.getPaddingBottom();
- int lastPageTop = contentBottom - displayHeight;
- int currScrollY = mScrollView.getScrollY();
- scroller.startScroll(0, currScrollY, 0, lastPageTop - currScrollY, 500);
- mScrollView.post(task);
- return true;
- }
- return false;
- }
ちなみに、scrollerはアニメーション付きのスクロール量計算をカプセル化したクラスで、下記のようなコードでインスタンスを生成しておく。
- scroller = new Scroller(mScrollView.getContext(), new OvershootInterpolator());
また、taskの実体はRunnableであり、scrollerの計算結果取得とScrollView#scrollTo()メソッドの呼び出しを行っている。
- task = new Runnable()
- {
- @Override
- public void run()
- {
- scroller.computeScrollOffset();
- mScrollView.scrollTo(0, scroller.getCurrY());
- if (!scroller.isFinished())
- {
- mScrollView.post(this);
- }
- }
- };
結果はこれ。
画像だと伝わりにくいが、タッチして下へぐぐっと引っ張ることができる。
指をはなすとびろーんアニメーション(Overshoot)でもとに戻る。
0 件のコメント:
コメントを投稿