【Android】 WebViewのheightがなかなか表示コンテンツのheightに合ってくれなくて困ったお話
お久しぶりです。しんちゃんだゾ。(大嘘) 意気揚々と初回エントリ書いて1ヶ月が経ってしまいましたが、今からちょっとずつ日々得たTipsを発信できればと思います。
今日はWebView周りで少し困ったことがあったので、備忘録で残しておきたいと思います。 重箱の隅をつつくようなTipsですが、温かい目で見ていただけると幸いです。
実現したいこと
AppBarLayoutとBehaviorを連動させたWebViewを表示したい!
困ったこと
AppBarLayoutとWebViewのBehaviorを連動させるには、WebViewをNestedScrollViewでネストさせ、android:isScrollContainer="false"
を設定する必要があります↓
<android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <WebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="wrap_content" android:isScrollContainer="false"/> </android.support.v4.widget.NestedScrollView>
これで、無事AppBarLayoutとBehaviorが連動するようになりましたが、今度はWebViewで表示している表示コンテンツのheightとNestedScrollViewのheightが合ってくれない・・・
じゃあNestedScrollViewのheightをwrap_contentにすればいいんじゃない?
と思い書いてみたら、なんかIDEから嫌な赤線が引かれた。
Placing a <WebView> in a parent element that uses a wrap_content size can lead to subtle bugs; use match_parent
・・・
WebViewをネストするViewはwrap_content
になってるとバグ起こすからmatch_parent
を使え!! とのこと・・・
コンパイルエラーを起こすわけじゃなく、tools:ignore="WebViewLayout"
をWebViewに追記すれば警告をsuppressすることはできます。
だけど「バグ起こすぞ」って言われたことを無視するまるで反抗期の子供みたいなことはしたくないので、なるべくバグがない安全な方法で実現したいわけです。
試してみたこと
その1: WebViewClient#onPageFinishedでWebView.contentHeightを取得してNestedScrollViewのHeightにセットする
ページのロードが終了したタイミングでコールバックされるonPageFinished()
を使ってWebViewのcontentHeightを取得して、それをNestedScrollViewのheightにセットすればいいんじゃないか?
override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) binding.scrollView.layoutParams = FrameLayout.LayoutParams( FrameLayout.LayoutParams.MATCH_PARENT, view?.contentHeight ?: 0 ) }
結果: onPageFinished()で正しいcontentHeightは取得できず撃沈
その2: WebViewのレイアウトが再レンダリングされる時にcontentHeightを捕まえに行く
だったら、WebViewのcontentHeightが変更され、再度レンダリングされるタイミングでNestedScrollViewのHeightにセットすれば・・・!!
結果: そんなコールバックメソッドなんてなかった
こうやってできた
方法: WebViewをScrollViewでネストして、それを丸ごとNestedScrollViewでネストする
<android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="wrap_content"> <!-- NestedScrollViewのlayout_heightをwrap_contentにすることで、子のコンテンツに応じてheightを変えるようにする --> <ScrollView android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- WebViewの直接ネストしているScrollViewのlayout_heightはmatch_parentにする--> <WebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="wrap_content" android:isScrollContainer="false"/> </ScrollView> </android.support.v4.widget.NestedScrollView>
単純だったよ・・・パトラッシュ・・・
おわりに
レイアウト上で簡単に対応できて良かったです。(傷だらけ)
コード上でダイナミックに変更すると、ある条件では動作しなかったり、ヒューマンエラーを起こす可能性も高くなるので。
同じことでお困りの方がいらっしゃれば、手助けになると幸いです。
じゃ、そゆことで〜〜