概要
スクロールを伴うアプリはたいていListViewでやっちゃう事が多いと思うのですが、独自の巨大なコンテンツをスクロールさせたい時にはScrollViewを使うと思います。
で、わざわざScrollViewを使うからには、あまりヒュンヒュン慣性スクロールして欲しくない場合もありますね。
対応策として、独自にUIScrollViewなりScrollViewなりを拡張してカスタムすればいいんですけど、そこまでするほど暇じゃないって方向けの方法をご紹介しようと思います。
Android
Javaはオブジェクト指向の模範生みたいな言語であると思いますが、さりげなくその概念をぶっ壊すリフレクションという仕組みが用意されています。
今回はこれを使います。
例として、
<ScrollView id="scrollView" orientation="horizontal" ~略~>
~略~
</ScrollView>
みたいにScrollViewが定義されてたとします。
orientationがhorizontalなので、実体はAndroidのHorizontalScrollViewとなります。
verticalを指定した場合はVerticalScrollViewになるのは火を見るより明らかで眩しいでしょう。
Androidはオープンソースという開発者がフライング感謝するようなプラットフォームなので、ソースを眺めていると、ScrollViewのスクロール量などを制御しているのは、OverScrollerというクラスなのがわかります。
このOverScrollerのインスタンスでsetFriction()メソッドの引数に大きな値を与えるほどスクロールがとろくさくなります。
んでは、さっそくリフレクションでいじりましょう。
let scrollView = page.getViewById('scrollView');
let ScrollViewClass = android.widget.HorizontalScrollView.class;
let scrollerField = ScrollViewClass.getDeclaredField('mScroller');
scrollerField.setAccessible(true);
let scroller: android.widget.OverScroller = scrollerField.get(scrollView.android);
scroller.setFriction(android.view.ViewConfiguration.getScrollFriction() * 3);
1行目でいじりたいScrollViewを取ってきます。
2行目では、いじりたいScrollViewの実体クラス、今回のケースではHorizontalScrollViewをいったん変数に入れています。
3行目からさっそく激しくリフレクるのですが、privateなインスタンス変数mScroller(OverScrollerクラス)を操作できるインスタンスをとってきてます。
4行目で、これからこのprivateな変数を丸裸にするぞと宣言します。Java環境によっては、そんな横暴は許されないといって落ちるのですが、Androidでは大丈夫でした。
5行目でやっとOverScrollerのインスタンスをゲットします。
6行目で目的のsetFrictionをやっているわけですね。今回は通常の3倍遅くしています。逆シャアです。
この方法ではmScrollerという変数名とOverScrollerというクラスを決めうちなので、将来的に使えなくなるかもしれません。
その時は、またAndroidのソースをなめ回して、SDKバージョンによって処理を分岐させれば良いと思います。
iOS
iOSはUIScrollViewに専用のプロパティがあるので、それを使えば良いです。
let scrollView = page.getViewById('scrollView');
(<UIScrollView>scrollView.ios).decelerationRate = UIScrollViewDecelerationRateFast;