I am using the AdMob Adaptive banner for my app that changes width and height accordingly to the device.
With AdMob only, the ad dimensions are ([DEVICE_WIDTH] x [50dp min]). On most devices the height changes to 60dp+.
The problem occurs with mediation partners that have banners limited to 50dp height. This is causing layout shifting from 60dp to 50dp and vice versa (depending on the ad provider) which is not recommended in AdMob policy.
Any idea on how to stop the layout shift?
XML
Fragment container
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@id/constraintLayoutAds"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/mobile_navigation" />
Ad container
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayoutAds"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<FrameLayout
android:id="@+id/frameLayoutAdContainerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
android:minHeight="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Java
Load ad
AdView adView = new AdView(ActivityMain.this);
adView.setAdSize(FindAdSize.adSize(ActivityMain.this));
frameLayoutAdContainerView.addView(adView, layoutParams);
AdRequest adRequest = new AdRequest.Builder().build();
adView.loadAd(adRequest);
Kotlin
Calculate AdSize
class FindAdSize : AppCompatActivity() {
companion object {
@Suppress("DEPRECATION")
@JvmStatic
fun adSize(activity: Activity): AdSize {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(
activity,
activity.resources.configuration.screenWidthDp
) else {
val display = activity.windowManager.defaultDisplay
val outMetrics = DisplayMetrics()
display.getMetrics(outMetrics)
val density = outMetrics.density
val adWidthPixels = outMetrics.widthPixels.toFloat()
val adWidth = (adWidthPixels / density).toInt()
AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(activity, adWidth)
}
}
}
}
Mediation providers in use: Meta, AppLovin, AdColony, Vungle, Tapjoy, and IronSource.
You can try the following approach to ensure that the ad container height is always equal to the height of the ad:
With this approach, the ad container will always have a minimum height of 50dp, but the actual height of the ad will be determined by the AdView, which will fill the entire height of the ad container.
I'm thinking that setting the height of the AdView to "match_parent" might not be ideal for all devices and screen sizes, ad the available space for the ad might vary. This could be a trade-off to ensure that the ad container height is always equal to the height of the ad and avoid layout shifts.