Flutter中Admob Banner广告截断/拉伸:如何适配全屏正常显示?
问题描述
使用Admob Banner广告时遇到以下问题:
- 使用
AdSize.banner时,广告组件无法占满屏幕宽度,但广告内容显示正常; - 使用
AdSize.fullBanner时,广告会被拉伸,内容出现变形。
需要实现横幅广告适配屏幕全屏宽度,同时保证广告内容无截断、无拉伸。
用户当前代码
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(); } }
解决方案:使用自适应横幅广告
要实现全屏宽度适配且内容正常,需要使用内联自适应横幅广告(Inline Adaptive Banner),它会根据屏幕宽度自动调整广告的高度和内容布局,避免拉伸或截断。
具体修改步骤:
获取屏幕可用宽度并创建自适应尺寸
在_loadAd方法中,替换固定的AdSize.fullBanner,改为基于屏幕宽度生成自适应尺寸:void _loadAd() async { await _inlineAdaptiveAd?.dispose(); setState(() { _inlineAdaptiveAd = null; _isLoaded = false; }); // 获取屏幕可用宽度(减去左右安全区域) final mediaQuery = MediaQuery.of(context); final availableWidth = mediaQuery.size.width - mediaQuery.padding.left - mediaQuery.padding.right; // 创建自适应横幅尺寸,第二个参数为最小高度(设为0让广告自动适配) AdSize size = AdSize.getInlineAdaptiveBannerAdSize(availableWidth.toInt(), 0); _inlineAdaptiveAd = BannerAd( adUnitId: AdHelper.bannerAdUnitId, size: size, request: const AdRequest(), listener: BannerAdListener( onAdLoaded: (Ad ad) async { debugPrint('Inline adaptive banner loaded: ${ad.responseInfo}'); BannerAd bannerAd = (ad as BannerAd); _finalSize = await bannerAd.getPlatformAdSize(); if (_finalSize == 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(); }调整布局,避免强制拉伸
在build方法中,移除Expanded(它会强制占用父组件剩余空间,导致广告拉伸),直接用SizedBox将宽度设为屏幕宽度,高度使用广告加载后返回的实际高度:@override Widget build(BuildContext context) { return (_inlineAdaptiveAd != null && _isLoaded && _finalSize != null) ? SizedBox( width: MediaQuery.of(context).size.width, height: _finalSize!.height.toDouble(), child: AdWidget(ad: _inlineAdaptiveAd!), ) : const SizedBox(width: 0, height: 0); }
原理说明
- 自适应横幅广告会根据你提供的屏幕宽度,请求最匹配的广告尺寸,广告内容会自动适配该宽度,不会出现拉伸或截断;
- 加载完成后获取的
_finalSize是广告的实际高度,用这个高度设置容器,能保证广告内容完整显示; - 移除
Expanded避免了强制拉伸广告组件,让广告保持自身的合理比例。
内容的提问来源于stack exchange,提问作者Patola
相关产品推荐
相关产品推荐

