バナー広告の表示があるアプリで、広告の読み込みに時間がかかってその表示が遅れたとき、
画面がカクつく現象のことです。
例えば、ConstraintLayout の最上部にバナー広告のビューAがあって、
そのビューAの下に何らかのビューBがあるとします。
(ビューAの id
が adView で、ビューBに layout_constraintTop_toBottomOf="@id/adView"
が設定されている)
①アクティビティの onCreate で、広告の読み込み処理(loadAd)をコール。
↓
②読み込み処理中はビューAの高さがゼロになる(onWindowFocusChanged で確認済)。
↓
③ネットワークの問題などで読み込み処理に時間がかかる。
↓
④読み込み処理が終わる前に画面表示が行われ、レイアウトの最上部にビューBが表示されて見える。
↓
⑤読み込み処理が終わってビューAの高さがゼロではなくなり、広告の高さの分だけビューBが下にずれる。
結果、画面がカクついてダサいという具合です。
ボタンやリンクなどがずれて押し間違えたりするとイラっとします。
対処方法を考えたので投稿します。
前提
adSize
は SMART_BANNER
のみで確認しています。
firebase-ads
のバージョン 17.1.1 を使っています。
どのバージョンでも起きる現象なのかどうかは把握していないです。
少なくとも 17.0.0 と 15.0.1 でも起きていました。
もっと前のバージョンも使ってはいましたが、広告の読み込みが早く終わると気付かない(?)ので、
昔からあったものなのかどうかは、よく分からないまま。
複数種のスマホ実機で見られたので、メーカーや機種へ依存したものではなさそう。
対処方法
loadAd
を呼ぶ前に、AdView
の minimumHeight
に対して SMART_BANNER
の高さの規定値をセットして、ゼロにならないようにする。
こうすると広告の読み込み中でも、AdView
の表示エリアは潰されずに空白としてそのまま表示されます。
class MainActivity : AppCompatActivity() {
private lateinit var mAdView: AdView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
MobileAds.initialize(this, "ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX")
mAdView = findViewById(R.id.adView)
// AdView の minimumHeight に規定値の高さをセットして広告読み込み中に高さゼロにならないようにする
mAdView.minimumHeight = AdSize.SMART_BANNER.getHeightInPixels(this)
// 広告の読み込みに失敗したら AdView の minimumHeight をデフォルトのゼロに戻す
mAdView.adListener = object : AdListener() {
override fun onAdFailedToLoad(p0: Int) {
super.onAdFailedToLoad(p0)
mAdView.minimumHeight = 0
}
}
// 広告の読み込み処理をコール
mAdView.loadAd(AdRequest.Builder().build())
}
}
補足
上記の対処方法を使ったとしても、広告の読み込みに失敗した場合では注意点が1つあります。
それは広告の表示エリアを高さゼロに戻しているために、読み込み失敗までに時間がかかってしまうと、
広告用の空白エリアが潰れるのが見えて、やっぱり画面をカクつかせてしまうという点です。
ネットにつながらない場合なら対応しようがないので、これはもうしょうがないですね。
広告切れで読み込み失敗が起きる(真偽は不明)というのも聞いたことがあるので、
onAdFailedToLoad
で別の広告ネットワークに切り替えるのもありかもしれません。
広告を読み込めなかったときに空白エリアを残しておくのが問題ないレイアウトであれば、
minimumHeight
をゼロに戻さずにそのままにしておいてもいいです。
(そういうレイアウトなら今回紹介した方法自体が不要だと思いますが)
ちなみに、AdView - REFERENCE を見ても minimumHeight
のデフォルト値についての説明などは見つけられませんでした。