Admob Banner ad is cut off on flutter
As shown in the image admob banner ad is cut off or stretched.
If I use AdSize.banner widget does not take the entire width but shows the ad correctly. If I use full-banner the ad is stretched.
How do I get the banner to fit the full width of the screen and show the content correctly (without cut off or streached)?
class _AdBannerState extends State<AdBanner>{ BannerAd? _inlineAdaptiveAd; bool _isLoaded = false; AdSize? _finalSize; @override void didChangeDependencies() { super.didChangeDependencies(); _loadAd(); } void _loadAd() async { await _inlineAdaptiveAd?.dispose(); setState(() { _inlineAdaptiveAd = null; _isLoaded = false; }); // Get an inline adaptive size for the current orientation. AdSize size = AdSize.fullBanner; _inlineAdaptiveAd = BannerAd( adUnitId: AdHelper.bannerAdUnitId, size: size, request: const AdRequest(), listener: BannerAdListener( onAdLoaded: (Ad ad) async { debugPrint('Inline adaptive banner loaded: ${ad.responseInfo}'); // After the ad is loaded, get the platform ad size and use it to // update the height of the container. This is necessary because the // height can change after the ad is loaded. BannerAd bannerAd = (ad as BannerAd); _finalSize = await bannerAd.getPlatformAdSize(); // if (size == null) { // debugPrint( // 'Error: getPlatformAdSize() returned null for $bannerAd'); // return; // } setState(() { _inlineAdaptiveAd = bannerAd; _isLoaded = true; }); }, onAdFailedToLoad: (Ad ad, LoadAdError error) { debugPrint('Inline adaptive banner failedToLoad: $error'); ad.dispose(); }, ), ); await _inlineAdaptiveAd!.load(); } @override Widget build(BuildContext context) { return (_inlineAdaptiveAd != null && _isLoaded && _finalSize != null) ? Expanded( child: SizedBox( width: _finalSize!.width.toDouble(), height: _finalSize!.height.toDouble(), child: AdWidget( ad: _inlineAdaptiveAd!, ))) : const SizedBox( width: 0, height: 0, ); } @override void dispose() { _inlineAdaptiveAd?.dispose(); super.dispose(); } }
This is apparently a known issue. Tracked by the developers. Not solved yet.
Workaround can be found here. Not perfect.
https://github.com/googleads/googleads-mobile-flutter/issues/261#issuecomment-1293001373
To make it responsive,
Please use MethodChannel to call any native java/kotlin method which is written as part of the android native code which can be invoked from your .dart file
Example Resource folder: Flutter Official Example
Example MethodChannel: Flutter Official MethodChannel Example
You need to create the below folders and files inside android/app/src/main/res folder yourself and put those values yourself and adjust accordingly
Option 1: to mathematically handle _finalSize and AdWidget sizes based on the values from dimension resource files dimens.xml using folder names Configuration qualifier names
values-sw720dp 10.1” tablet 1280x800 mdpi values-sw600dp 7.0” tablet 1024x600 mdpi values-sw480dp 5.4” 480x854 mdpi values-sw480dp 5.1” 480x800 mdpi values-xxhdpi 5.5" 1080x1920 xxhdpi values-xxxhdpi 5.5" 1440x2560 xxxhdpi values-xhdpi 4.7” 1280x720 xhdpi values-xhdpi 4.65” 720x1280 xhdpi values-hdpi 4.0” 480x800 hdpi values-hdpi 3.7” 480x854 hdpi values-mdpi 3.2” 320x480 mdpi values-ldpi 3.4” 240x432 ldpi values-ldpi 3.3” 240x400 ldpi values-ldpi 2.7” 240x320 ldpiDefine a fraction
<?xml version="1.0" encoding="utf-8"?> <resources> <fraction name="division_factor_width">0.31</fraction> <fraction name="division_factor_height">0.41</fraction> </resources>Get the fraction
child: SizedBox( width: _finalSize!.width.toDouble() / getResources().getFraction(R.dimen.division_factor_width, 1,1), height: _finalSize!.height.toDouble() / getResources().getFraction(R.dimen.division_factor_height, 1,1), child: AdWidget( ad: _inlineAdaptiveAd!, )))Option 2: Read constraints in the guide Understanding constraints in flutter
Option 3: Put the SizedBox inside another layout like linear and set the layout properties to center the box without streaching it
Option 4: create sized ads and call the AdHelper.bannerAdUnitId from a values.xml the values.xml will be placed in multiple size folders like hdpi ldpi ... etc
This is not applicable to Flutter, none of the methods exist.
wich method ? getResources()? you are talking about ?
yeah and also resource. xml
Please use MethodChannel docs.flutter.dev/platform-integration/platform-channels to call any native java/kotlin method which is written as part of the android native code which can be invoked from your .dart file
all those resource xml files belongs to native android code which inside your flutter project wich two folders android ios where the original native code is written
If I use AdSize.banner widget does not take the entire width but shows the ad correctly. If I use full-banner the ad is stretched.
That's because:
The AdSize.banner actual size is 320x50. The AdSize.fullBanner actual size is 468x60.Keep in mind that those sizes are fixed regardless of the actual device screen size. To clarify, it seems that the emulator screen width that you are using is less than 468, and more than 320.
Therefore, you need to provide a custom size as an AdSize. Instead of declaring size and _finalSize as
AdSize size = AdSize.fullBanner; _finalSize = const AdSize(height: 40, width: 320);they could be something like
// use it directly in the BannerAd creation AdSize size = AdSize( width: MediaQuery.of(context).size.width.toInt(), height: 40, ); // ... // then let _finalSize be the same size for later use (in the build method) _finalSize = size;At this point, I'd assume that there is no need to wrap the SizedBox in the build method with an Expanded.
Furthermore, here is a tip:
Use
SizedBox.shrink();instead of
const SizedBox( width: 0, height: 0, );Replace the Expanded widget with a LayoutBuilder and calculate the maximum available width (maxWidth) based on the constraints as below-
class _AdBannerState extends State<AdBanner>{ BannerAd? _inlineAdaptiveAd; bool _isLoaded = false; double _adHeight = 0; @override void didChangeDependencies() { super.didChangeDependencies(); _loadAd(); } void _loadAd() async { await _inlineAdaptiveAd?.dispose(); setState(() { _inlineAdaptiveAd = null; _isLoaded = false; }); // Get an inline adaptive size for the current orientation. AdSize size = AdSize.fullBanner; _inlineAdaptiveAd = BannerAd( adUnitId: AdHelper.bannerAdUnitId, size: size, request: const AdRequest(), listener: BannerAdListener( onAdLoaded: (Ad ad) async { debugPrint('Inline adaptive banner loaded: ${ad.responseInfo}'); setState(() { _inlineAdaptiveAd = ad as BannerAd; _isLoaded = true; }); }, onAdFailedToLoad: (Ad ad, LoadAdError error) { debugPrint('Inline adaptive banner failedToLoad: $error'); ad.dispose(); }, ), ); await _inlineAdaptiveAd!.load(); } @override Widget build(BuildContext context) { return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { double maxWidth = constraints.maxWidth; double maxHeight = maxWidth / _inlineAdaptiveAd!.size.width * _inlineAdaptiveAd!.size.height; _adHeight = maxHeight; return (_inlineAdaptiveAd != null && _isLoaded) ? SizedBox( width: maxWidth, height: _adHeight, child: AdWidget(ad: _inlineAdaptiveAd!), ) : SizedBox( width: 0, height: 0, ); }, ); } @override void dispose() { _inlineAdaptiveAd?.dispose(); super.dispose(); } }I hope this will work for you.
this still cut off content.