Jakicc
Jakicc

Reputation: 47

Allocate fixed space for adaptive banner ad

How should I go about allocating fixed space for adaptive ad banners?

My XML adaptive banner

    <FrameLayout
    android:id="@+id/ad_view_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:layout_alignParentBottom="true"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    />

Inside my Fragment getting adaptive ad banner dimensions

    private val adSize: AdSize
    get() {
        val outMetrics = Resources.getSystem().displayMetrics;

        val density = outMetrics.density

        var adWidthPixels = adContainerView.width.toFloat()
        if (adWidthPixels == 0f) {
            adWidthPixels = outMetrics.widthPixels.toFloat()
        }

        val adWidth = (adWidthPixels / density).toInt()
        return AdSize.getCurrentOrientationBannerAdSizeWithWidth(context, adWidth)
    }

I would like to follow Googles guidlines and have an allocated fixed space reserved for my banner, so that if my banner "lags" for a second screen on mobile stays the same. How should I go about it, whats the proper way?

Upvotes: 1

Views: 1108

Answers (2)

Aorlinn
Aorlinn

Reputation: 778

If you have a more complex behavior, like I do, you can use the following implementation. I have a ConstraintLayout that splits my screen in two parts in portrait mode. The banner is within one of these two parts and the ratio between them is not fixed but depending on some logic. So this implementation also works with that requirement, as it overwrites onMeasure to determine the best size depending on the available width.

public class AdBanner extends FrameLayout
{
    private AdView mAdView;
    private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();

    public AdBanner(Context context)
    {
        super(context);
    }

    public AdBanner(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public AdBanner(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        if (!isShowBanner())
        {
            super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.AT_MOST));
            return;
        }
        int width = MeasureSpec.getSize(widthMeasureSpec);
        if (width <= 0)
        {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // That's where we determine the most accurate banner format.
        AdSize adSize = AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(getContext(), getDpWidth(width));
        int height = adSize.getHeightInPixels(getContext());
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        if (heightMode != MeasureSpec.UNSPECIFIED)
        {
            height = Math.min(height, MeasureSpec.getSize(heightMeasureSpec));
        }
        setMeasuredDimension(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.getMode(heightMeasureSpec)));
    }

    protected int getDpWidth(int width)
    {
        Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        display.getMetrics(mDisplayMetrics);
        return (int) (width / mDisplayMetrics.density);
    }

    protected boolean isShowBanner()
    {
        // Do your checks here, like whether the user payed for ad removement.
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b)
    {
        if (!isShowBanner())
        {
            return;
        }
        int width = r - l;
        if (width <= 0)
        {
            return;
        }
        AdSize adSize = AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(getContext(), getDpWidth(width));

        // Prevent the ad from beeing added with each layout cicle,
        // by checking, whether or not available size actually changed the format of the banner
        if (mAdView == null || !adSize.equals(mAdView.getAdSize()))
        {
            removeAllViews();
            mAdView = new AdView(getContext());
            mAdView.setAdSize(adSize);
            ((GameApplication) getContext().getApplicationContext()).androidInjector().getAdService().loadBannerAd(getRootActivity(this), mAdView);
            this.addView(mAdView);
        }
        mAdView.layout(0, 0, width, b - t);
    }
}

Upvotes: 0

voytez
voytez

Reputation: 1842

when starting the app you can get the adaptive banner height straight away by calling something like adSize.getHeight(). This will give you banner height in dps.

You then convert that heigth dps in px and set this height to your ad frame layout programatically by calling setLayoutParams with acquired height in pixels.

This way you dont need to wait for the ad to load to apply proper height and risk ad overlapping policy violation or conent shifting (which would happen if you depend on wrap_content)

Upvotes: 2

Related Questions