3

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.

Miha M
  • 379
  • 1
  • 3
  • 14

1 Answers1

0

You can try the following approach to ensure that the ad container height is always equal to the height of the ad:

AdView adView = new AdView(ActivityMain.this);
adView.setAdSize(FindAdSize.adSize(ActivityMain.this));
adView.setAdUnitId("YOUR_AD_UNIT_ID");

// Set the minimum height of the ad container to 50dp
frameLayoutAdContainerView.setMinimumHeight((int) (50 * getResources().getDisplayMetrics().density));

// Set the height of the AdView to "match_parent"
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);

// Center the AdView vertically within the ad container
layoutParams.gravity = Gravity.CENTER_VERTICAL;
frameLayoutAdContainerView.addView(adView, layoutParams);

AdRequest adRequest = new AdRequest.Builder().build();
adView.loadAd(adRequest);

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.

Catalin Podariu
  • 148
  • 2
  • 8
  • 1
    I have already set minimum height in XML (android:minHeight="50dp"). While this works great, the problem arrives when Adaptive banner can increase banner height above 50px and causes layout shifts. Example: Banner loads from AdMob source (H: 60dp), after 30 seconds the ad refreshes and loads ad from different source (H: 50dp). The cycle continues and causes the layout to shift. – Miha M Feb 15 '23 at 18:47
  • I updated the answer above, to account for what you said here.. :) – Catalin Podariu Feb 16 '23 at 13:31
  • Unfortunately, this causes the ad to be cut on top and bottom. – Miha M Feb 16 '23 at 18:35