iScrollでスマフォスクロール! | パークのソフトウエア開発者ブログ|ICT技術(Java・Android・iPhone・C・Ruby)なら株式会社パークにお任せください

パークのソフトウエア開発者ブログ|ICT技術(Java・Android・iPhone・C・Ruby)なら株式会社パークにお任せください

開発の解決方法や新しい手法の情報を、パークのエンジニアが提供します。パークのエンジニアが必要な場合は、ぜひお気軽にお問い合わせ下さい。 株式会社パーク:http://www.pa-rk.co.jp/

最近 WebView を利用したスマートフォン(iPhone/Android)アプリを
作成する機会がありました。

フリックで行を動かしたりページを変えてみたりしたのですが、
なんとこれでページのスクロールができなくなってしまいました!

原因は、touchstart、touchmove、touchendに紐づけていた
関数で利用したpreventDefault()。

touchイベントでpreventDefault()を使うと、
デフォルトのスクロールが効かなくなってしまうんですね!(@▽@)


これを回避するために、今回iScrollというものを使ってみました。


え?そもそもpreventDefault()使うのが間違っている?

おっしゃるとおりなんですが、画面の上をスワイプしたりページをAJAX通信で
変更させてみたりするときにpreventDefault()を使わざるをえなかったんですorz

----------

では、iScrollの基本的な使い方を解説していきます。

■この記事の対象者■
下記を満たす方
  • jQuery を触ってみたことがある
  • html を書いてみたことがある
  • cssでの「#hoge」や「.hoge」といった
    書き方が何を意味しているか分かる


■作成するページ■
ページの一部をスクロールできるページ



まずはiScroll 4から iscroll-4.zip をダウンロードします。

ダウンロードしたzipを解凍して、iscroll.jsがあるのを確認します。

iscroll.jsを入手できたら、htmlとcssを準備します。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title></title>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="application/javascript" src="./src/iscroll.js"></script>
<style type="text/css" media="all">
/* iscrollとは関係ないスタイル */
div {
margin: 0;
padding: 0;
}
#wrapper {
padding: 10px;
background-color: #ffaaff;
}
#wrapper-scroll {
height: 100px;
background-color: #ffffff;
}
#layer01 {
height: 150px;
background-color: #aaffff;
}
#layer02 {
height: 150px;
background-color: #ffffaa;
}
</style>
</head>
<body>
<div id="wrapper">
<div id="wrapper-scroll"> <!-- wrapper -->
<div id="layer01"> <!-- scroller -->
<script type="text/javascript">
for(var i = 1; i <= 9; i++) {
document.write(i + "行目<br />");
}
</script>
</div>
<div id="layer02">
<script type="text/javascript">
for(var i = 1; i <= 9; i++) {
document.write(i + "行目<br />");
}
</script>
</div>
</div>
</div>
</body>
</html>


見た目はこうなります。
iscroll:htmlとcss


1つ1つ説明していきますネ。

■プラグインへのリンク
<head>内で jQuery と flickSimple にリンクを張ります。

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="application/javascript" src="./src/iscroll.js"></script>

iScroll は jQuery を使用しているので、
iScroll の前に jQuery にリンクを張ってあげてください。

iScroll のスクリプトのパスは、どこに iScroll をダウンロードしたかで変わります。


■html

<div id="wrapper">
<div id="wrapper-scroll"> <!-- wrapper -->
<div id="layer01"> <!-- scroller -->
<script type="text/javascript">
for(var i = 1; i <= 9; i++) {
document.write(i + "行目<br />");
}
</script>
</div>
<div id="layer02">
<script type="text/javascript">
for(var i = 1; i <= 9; i++) {
document.write(i + "行目<br />");
}
</script>
</div>
</div>
</div>

id が「wrapper-scroll」の中身をスクロールできるように組んでいます。
iScroll適用後にスクロールしているのが分かりやすいよう、
wrapper-scroll の中身が wrapper-scroll より大きくなるように
CSSで設定しています。

Google Chrome の Developer tools で確認すると、wrapper-scroll の位置が分かりますネ。
iscroll:wrapper


スクロール時に見えている高さを決める wrapper-scroll 部分は
ページ全体で一意に決まる要素になっている必要があります。
なので、id名をふってあげましょう。


■iScroll を適用する。
細かい説明は後回しにして、iScroll を適用します。

<head>内に下記を追加してください。

<script type="text/javascript">
$(window).load(function(e) {
new iScroll("wrapper-scroll");
});
</script>

new iScroll()の引数にはフリックさせる範囲を示す要素の id 名を指定します。


iScroll を適用すると、見た目がこのように変わります。
iscroll:適用

一番下までスクロールするとこんな感じ。
iscroll:スクロール

iScroll 適用前と見た目がだいぶ変わりましたね。
id が layer02 の要素は見えもしません。

オマケに生成された html を Developer tools で確認すると、
なんだかごちゃごちゃしているのが分かります。
iscroll:適用後のhtml


ここで、iScroll の仕組みを説明しましょう。

iScroll は new iScroll() の引数で指定した要素をスクロールの表示画面に、
その要素の1番目の子供を実際にスクロールして見たい html とみなします。

なので、new iScroll() の引数に指定した id="wrapper-scroll" の要素の
範囲のみが見えるようになりました。

そして、1番目の子供の id="layer01" の要素をスクロールして見れるようになっています。

2番目の子供は無視されてしまうので、下までスクロールしても見えません。

でも、消されたわけではないので、ちゃんといます。
iscroll:2番目以降の子供


iScroll は実際にスクロールしたい要素を動かしてスクロールしているように見せかけています。
なので、id="layer01" に指定された style の値はスクロールする度に変化します。

また、iScroll は独自のスクロールバーを出すので
id="wrapper-scroll" の最後にスクロールバー用の<div>が追加されています。

スマフォではスクロール時だけスクロールバーが見えるようになります。

----------

この状態では画面の一部分しかスクロールできませんが、
wrapper-scroll と 1番目の子供を画面全体を囲む div にしてあげれば、
画面全体をスクロールすることができます。


■iScroll 注意点
iScroll を適用すると、長押し(ロングタップ)でコピー・ペーストダイアログが表示されなくなります。
これは、touchstart を受け取った場合に preventDefault() を実行しているためです。

長押し(ロングタップ)を無効化したくない場合は、
iscroll の iScroll = function・・・ 内を下記のように改造します。

onRefresh : null,
onBeforeScrollStart : function(e) {
// e.preventDefault(); // comment out : 長押し有効化のため
},
onScrollStart : null,
// onBeforeScrollMove: null, // comment out
onBeforeScrollMove : function(e) { // add : デフォルトスクロール無効化のため
e.preventDefault();
},



----------
では、今回はここまで!