こんにちは。iOS アプリ開発担当の宮本です。
Hold And Go はリンクを長押しした時に背面で新規タブしてくれる Sleipnir Mobile の便利機能です。以前のバージョンではリンクがハイライトするにも関わらず、背面でタブが開かれずに何も起きないことがありました。せっかくの便利な機能がもったいないので、バージョン1.3 で改善をしました。
今回は、なぜ Hold And Go がたまに失敗するのか、またそれをどうやって改善したのかについて説明しようと思います。
■ Hold And Go の仕組み
Hold And Go は次の流れで実行されます。
1. iOS でのタッチポイントを HTML 上の座標に変換する
2. JavaScript の elementFromPoint でその座標にある DOM の要素を取得する
3. 取得した要素にリンクがあれば、その URL を背面のタブで開く
UIWebView の API はかなり貧弱なので、基本的になにもできません。もちろん、リンクが長押しされたといったイベントもきません。タッチされた位置から頑張ってリンクを探すしかありません。
■ iOS の UIWebView はリンクの当たり判定が大きい
iPhone のコントロールはどれも大きめに作られていて、タッチしやすいようになっています。しかし UIWebView ではテキスト自体が反応するコントロールになるので、そのままの大きさでは押しにくいです。そのため、iPhone の UIWebView は本当のリンクの大きさ以上に当たり判定が広くなっています。
この当たり判定を広くしている部分だと、elementFromPoint でリンクを取得できていないようです。
■ 色々調べたが、解決する方法はみつからず
ハイライトしているリンクを取得する方法が他にないか、UIWebView についてかなり調べてみましたが全然情報がありませんでした。
次に、elementFromPoint で取得できなくても、リンクに対して touchstart はきているのではないかということで、全てのリンクの touchstart をフックしてみることにしました。しかし、イベントがきません。DOM のイベントも発生していないようでした。
もう力技しかありません。
■ タッチした位置だけでなく、その周辺にもリンクがないかを探す
当たり判定が広くなっている部分でリンクを見つけられないなら、広くなっている分だけ周りを調べてみればどこかでリンク上にくるはずです。そこで、elementFromPoint でリンクが見つからない時は、上下に少し座標を動かしたポイントでもリンクがないかを調べることにしました。
状況によって当たり判定の広さが変わるかもしれないので完全ではないですが、たったこれだけでかなり精度があがりました。
1.3 の修正で Hold And Go は良くなりましたが、まだ改善の余地はあります。今後も、使いやすくなるよう改善していきたいです。