【Android】ネイティブからWebView内の要素を非表示にする/特定の位置までスクロールする

## はじめに
AndroidのWebViewはただページを表示して終わりではありません。
JavaScriptのコードをネイティブ側で書くことで、WebView内の部品をあれこれいじることができます！
今回は下記の2つのサンプルコードをご用意しました。
* WebView内の部品を非表示にする
* ネイティブ側で設置したボタンからWebViewの特定の位置にニュルっとスクロールする

なお、筆者はJavaScript一切経験していない人間なので書き方などお見苦しい点があるかと思いますがご容赦ください。

## WebView内の部品を非表示にする
Android Developersのヘッダー部分を非表示にする形で試してみようと思います。
修正前はこのような形で、上部にハンバーガーメニューやログインボタンが配置されているヘッダーが存在しています。

![Screenshot_20240330_034944.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1274260/17e6c171-8880-0bd7-1207-d2e9a58bfa34.png)


まずは該当のWebサイトを[Chromeの検証ツール](https://developer.chrome.com/docs/devtools/overview?hl=ja)などを用いて開き、非表示にしたい要素を見つけます。
どうやらこの`devsite-top-logo-row-wrapper-wrapper`というのがヘッダー部分の要素のようですね。

![スクリーンショット 2024-03-30 3.13.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1274260/88100c80-2723-cfd3-bfa0-8ec57bf7fdb0.png)


次に、ネイティブのコード内で下記のようにjsのコードを書き、これをonPageFinished()など任意の場所で呼びます。

```MainActivity.kt

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding?.root)

        val webView = binding?.webview
        webView?.settings?.javaScriptEnabled = true
        webView?.webViewClient = object: WebViewClient() {
            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                view?.loadUrl(
                    "javascript:(function() { " +
                            "document.getElementsByClassName('devsite-top-logo-row-wrapper-wrapper')[0].style.display = 'none';" +
                            "})()"
                )
            }
        }

        webView?.loadUrl("https://developer.android.com/?hl=ja")
    }
```

通常のJavaScriptの関数だとKotlinのように`fun test(){...}`のように書くのですが、loadUrl内で関数を実行する場合は記法が若干異なるので注意が必要です。
（JavaScriptと同じような関数の記法で試したところ正常に動きませんでした）

これを実行すると下記のような形でヘッダー部分が非表示になっています！

![none.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1274260/be717356-24f5-6eef-5444-5055131b0065.png)


ちなみに上記では`style.display = 'none'`を使用していますが、`style.visibility = 'hidden'`を使用すると下記のような形でスペースは確保されたまま要素が非表示になります。

![hidden.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1274260/92990822-fe64-dd20-7a2f-023fcaa4afe2.png)


## ネイティブ側で設置したボタンからWebViewの特定の位置にニュルっとスクロールする
次はサイト下部にあるYouTubeのボタンまでニュルっとスクロールさせてみましょう。

これまでと同じように検証ツールで該当の要素を確認します。

![スクリーンショット 2024-03-30 3.51.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1274260/4b3d8e1f-2bb8-f785-bf7f-20b09e1a74ea.png)

要素名は「devsite-footer-promo」だとわかりましたが、XやLinkedInも同じ要素名になっていますね。
このような場合は、index指定することによって該当の要素を抜き出せます。
今回はX→[0], YouTube→[1], LinkedIn→[2]という形で並んでいるため、[1]を指定します。

肝心のスクロール処理に関してはJavaScriptのelement.scrollIntoViewメソッドを使用します。

```MainActivity.kt

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding?.root)

        val webView = binding?.webview
        webView?.settings?.javaScriptEnabled = true
        webView?.webViewClient = object : WebViewClient() {
            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                view?.loadUrl(
                    "javascript:document.getElementsByClassName('devsite-footer-promo')[1].scrollIntoView({behavior: 'smooth'});"
                )
            }
        }

        webView?.loadUrl("https://developer.android.com/?hl=ja")
    }
```

こうすることで指定の位置までニュルッとスクロールするようになります！


![scrollToYouTube.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1274260/594dcfab-d9ad-0fea-29e0-e38c50068c67.gif)

ちなみにニュルッとスクロールさせたくない場合は`scrollIntoView()`とすればOKです。



## 所感
フロントエンドのエンジニアの方に依頼しなくてもこのようにネイティブからある程度サイト内を編集することができるのはとても助かるなと思いました。
今回ご紹介したのはほんの一部ですが、JavaScriptのメソッドをそのまま書いているだけなのでやりようによってはかなり色んなことができるのではないかと思います。
一方で、コード内のJavaScript構文は全てダブルクオーテーションで囲まなければならず、補完やコンパイルエラーを検知できないのはなかなか辛いなといった印象です。
この辺りうまいやり方があったら知りたいですね！

## ソースコード
こちらに格納しております。
https://github.com/bayastea/EditWebView

## 参考サイト
* [Inject JS into Android’s WebView](https://medium.com/@skywall/inject-js-into-androids-webview-8845fb5902b7)
* [JavaScriptで指定した要素の位置までスクロールするには2022年現在なら scrollIntoView() が便利](https://zenn.dev/junki555/articles/ba0ff1973182e8)