Skip to content

[iOS] Banner ad left-aligned instead of centered when container is wider than ad's natural size #186

Description

@khanisak

Description

On iOS, RNAppodealBannerView.m's bannerViewDidLoadAd: resets the banner's frame to origin (0, 0) once the ad loads, ignoring the container's actual bounds:

- (void)bannerViewDidLoadAd:(APDBannerView *)bannerView isPrecache:(BOOL)precache {
    ...
    CGSize bannerSize = self.bannerView.adSize;
    self.bannerView.frame = CGRectMake(0, 0, bannerSize.width, bannerSize.height);
    ...
}

This conflicts with layoutSubviews in the same file, which correctly centers the ad when the container is larger than the ad's natural size:

- (void)layoutSubviews {
    [super layoutSubviews];
    if (self.bannerView) {
        CGSize bannerSize = self.bannerView.adSize;
        if (CGRectGetWidth(self.bounds) > bannerSize.width || CGRectGetHeight(self.bounds) > bannerSize.height) {
            CGRect bannerFrame = CGRectMake(
                (self.bounds.size.width - bannerSize.width) / 2.0,
                (self.bounds.size.height - bannerSize.height) / 2.0,
                bannerSize.width,
                bannerSize.height
            );
            self.bannerView.frame = bannerFrame;
        } else {
            self.bannerView.frame = self.bounds;
        }
    }
}

Because bannerViewDidLoadAd: runs after the ad loads and hardcodes the origin to (0, 0), the centering logic in layoutSubviews gets overridden the moment the ad actually has content, and the ad appears left-aligned instead of centered whenever the RN-side container is wider than the ad's natural size (e.g. a full-width container with a standard 320x50 banner).

This doesn't affect Android, since its RCTAppodealBannerView.kt/RNAppodealBannerViewManagerImpl.kt stretches the ad view to fill the full measured bounds of its container rather than relying on the ad's own natural size.

Reproduction

  1. Render <AppodealBanner style={{ width: '100%' }} adSize="phone" /> inside a wider container (e.g. full device width) on iOS with the New Architecture (Fabric) enabled.
  2. Load a test ad (Appodeal.setTesting(true)).
  3. Observe: once loaded, the ad renders flush against the left edge instead of centered.

Expected behavior

The ad should stay centered after loading, consistent with layoutSubviews' existing centering logic.

Suggested fix

In bannerViewDidLoadAd:, compute the frame the same way layoutSubviews does, instead of hardcoding (0, 0):

CGSize bannerSize = self.bannerView.adSize;
self.bannerView.frame = CGRectMake(
    MAX(0, (self.bounds.size.width - bannerSize.width) / 2.0),
    MAX(0, (self.bounds.size.height - bannerSize.height) / 2.0),
    bannerSize.width,
    bannerSize.height
);
[self invalidateIntrinsicContentSize];
[self setNeedsLayout];

Environment

  • react-native-appodeal: 4.2.0
  • react-native: 0.86.3
  • New Architecture (Fabric): enabled
  • Platform: iOS only (Android unaffected)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions