👏

InAppWebViewでスクロール検知👆

2023/08/10に公開2

やりたいこと

InAppWebViewで表示している画面で、特定のスクロール位置を検知してボタンの活性/非活性の制御をしたい。

なぜwebview_flutterではないのか

  • 現時点でwebview_flutterにスクロール位置を検知するメソッドがなさそう。
  • どうしてもの場合はアプリ-Web間はJavaScriptチャネルを介してWebviewのイベントを検知することができるが、そもそもWeb側からチャンネルに通知>アプリからイベントを検知するという仕組みが必要で、今回の仕様に適していなかったため。
sample.dart
..addJavaScriptChannel(ScrollChannel,
              onMessageReceived: (message) {
                if (message.message == ‘reachedBottom’) {
                  reachedBottom.value = true;
                }
              },
            )

使用したライブラリ

https://pub.dev/packages/flutter_inappwebview

対応と説明

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別の注意点

Android コンテンツの高さ

↑がちょっと特殊で、取得したInAppWebViewのコンテンツの高さとスクロール検知したい高さはandroidとiOSでそれぞれ以下のようになった。

Android
エミュレータ  取得した高さ 6451:検知したい高さ 12450
実機  取得した高さ 6871:検知したい高さ 14550
iOS
エミュレータ  取得した高さ 6414:検知したい高さ  4403

※エミュレータと実機で各高さに差異が出る
※androidは取得した高さ<検知したい高さ
※iOSは取得した高さ>検知したい高さ

今回は途中までユーザーに目を通してもらう(スクロールしてもらう)程度で問題ないということで認識が合わせられたため、iOSの挙動をAndroidに似せて

y.h >= height.h / 2

という仕様にした。

また、機種によって取得しているコンテンツの高さが異なるため、完璧に同じ位置でのスクロール検知が難しく、今後この部分の対応を改善できるものがあれば記事を修正したい。

Discussion

opzeinopzein

一番上や一番下に到達したことの検知だけでよければ、
InAppWebViewのonOverScrolledでイベントが拾えるみたいです!
(5.2.0で追加されたようです)

mashmash

@opzeinさん
ありがとうございます!
InAppWebViewのonOverScrolled、勉強になりました!!
後ほど記事を更新させていただきます🙌