👏
InAppWebViewでスクロール検知👆
やりたいこと
InAppWebViewで表示している画面で、特定のスクロール位置を検知してボタンの活性/非活性の制御をしたい。
なぜwebview_flutterではないのか
- 現時点でwebview_flutterにスクロール位置を検知するメソッドがなさそう。
- どうしてもの場合はアプリ-Web間はJavaScriptチャネルを介してWebviewのイベントを検知することができるが、そもそもWeb側からチャンネルに通知>アプリからイベントを検知するという仕組みが必要で、今回の仕様に適していなかったため。
sample.dart
..addJavaScriptChannel(
‘ScrollChannel’,
onMessageReceived: (message) {
if (message.message == ‘reachedBottom’) {
reachedBottom.value = true;
}
},
)
使用したライブラリ
対応と説明
sample.dart
child: InAppWebView(
gestureRecognizers: {}..add(
const Factory<VerticalDragGestureRecognizer>(
VerticalDragGestureRecognizer.new, //縦方向のスワイプジェスチャーを認識
),
),
onScrollChanged: (controller, x, y) async {
// スクロールが変化したときに実行されるコールバック関数
final height = await controller.getContentHeight() ?? 0;
if (Platform.isAndroid) {
if (y.h >= height.h) {
// イベント
}
} else if (Platform.isIOS) {
if (y.h >= height.h / 2) {
// イベント
}
}
},
initialUrlRequest: URLRequest(
url: Uri.parse(
'https://www.sample.com',
),
),
),
OS別の注意点
↑がちょっと特殊で、取得したInAppWebViewのコンテンツの高さとスクロール検知したい高さはandroidとiOSでそれぞれ以下のようになった。
Android
エミュレータ 取得した高さ 6451:検知したい高さ 12450
実機 取得した高さ 6871:検知したい高さ 14550
iOS
エミュレータ 取得した高さ 6414:検知したい高さ 4403
※エミュレータと実機で各高さに差異が出る
※androidは取得した高さ<検知したい高さ
※iOSは取得した高さ>検知したい高さ
今回は途中までユーザーに目を通してもらう(スクロールしてもらう)程度で問題ないということで認識が合わせられたため、iOSの挙動をAndroidに似せて
y.h >= height.h / 2
という仕様にした。
また、機種によって取得しているコンテンツの高さが異なるため、完璧に同じ位置でのスクロール検知が難しく、今後この部分の対応を改善できるものがあれば記事を修正したい。
Discussion
一番上や一番下に到達したことの検知だけでよければ、
InAppWebViewのonOverScrolledでイベントが拾えるみたいです!
(5.2.0で追加されたようです)
@opzeinさん
ありがとうございます!
InAppWebViewのonOverScrolled、勉強になりました!!
後ほど記事を更新させていただきます🙌