如何让Xamarin.Forms的Google AdMob控件页面加载时正常显示
Xamarin.Forms Google AdMob 广告需交互才显示问题修复
问题现象
当前基于 ViewModel 绑定 ContentPages 架构的 Xamarin.Forms 应用,其余功能(API拉取、页面导航、AdMob测试广告请求)均正常,但存在以下异常表现:
- 页面初始加载时广告不渲染,仅当用户点击页面任意控件产生交互后广告才显示
- About 页面存在完全相同的问题
- 手动修改XAML中
<ads:AdBanner />控件的任意布局属性(如HorizontalOptions)会立即触发广告显示 - 跨页面导航后原页面已显示的广告会消失,再次修改对应页面AdBanner的XAML属性可恢复显示
对应现象截图:


根因说明
该问题是Xamarin.Forms自定义AdBanner渲染器的经典布局同步bug:AdMob原生广告加载完成后,没有主动向Xamarin.Forms布局系统传递尺寸变更通知,导致控件始终处于未测量、未排列的状态,仅当用户交互、XAML属性变更触发全局布局刷新时,才会完成广告控件的渲染流程。
修复步骤
1. 补全平台渲染器的加载完成回调逻辑
在Android、iOS项目的AdBanner自定义渲染器中,监听广告加载完成事件,在主线程强制触发原生控件布局,并同步尺寸到Forms层:
Android 渲染器代码示例:
// 绑定广告加载完成事件 adView.AdListener = new CustomAdListener(); // 自定义AdListener实现 public class CustomAdListener : AdListener { public override void OnAdLoaded() { base.OnAdLoaded(); // 所有UI操作切主线程执行 Device.BeginInvokeOnMainThread(() => { var nativeAdView = (AdView)Control; // 强制触发原生控件测量、布局 nativeAdView.Measure(Android.Views.ViewGroup.LayoutParams.WrapContent, Android.Views.ViewGroup.LayoutParams.WrapContent); nativeAdView.Layout(nativeAdView.Bounds); // 同步广告尺寸到Forms层控件,触发布局刷新 var formsAdView = (AdBanner)Element; formsAdView.WidthRequest = nativeAdView.AdSize.Width; formsAdView.HeightRequest = nativeAdView.AdSize.Height; }); } }
iOS 渲染器代码示例:
adView.AdReceived += (sender, args) => { Device.BeginInvokeOnMainThread(() => { var nativeAdView = (BannerView)Control; // 强制触发原生控件布局 nativeAdView.SetNeedsLayout(); nativeAdView.LayoutIfNeeded(); // 同步尺寸到Forms层 var formsAdView = (AdBanner)Element; formsAdView.WidthRequest = nativeAdView.Bounds.Width; formsAdView.HeightRequest = nativeAdView.Bounds.Height; }); };
2. 页面生命周期主动触发布局刷新
在所有承载AdBanner控件的ContentPage中,重写OnAppearing方法,页面显示时主动给广告控件赋值尺寸参数,避免跨页面导航返回后广告被布局系统标记为待刷新但未触发渲染:
// XAML中需给AdBanner控件配置x:Name="AdBanner" protected override void OnAppearing() { base.OnAppearing(); // 根据平台设置对应标准Banner尺寸,可按需替换为你使用的广告尺寸 if (Device.RuntimePlatform == Device.Android) { AdBanner.WidthRequest = AdSize.Banner.Width; AdBanner.HeightRequest = AdSize.Banner.Height; } else { AdBanner.WidthRequest = 320; AdBanner.HeightRequest = 50; } // 若广告未加载则主动触发加载 if (!AdBanner.IsLoaded) { AdBanner.LoadAd(); } }
3. 布局结构优化
- 不要将AdBanner控件放在
ScrollView、ListView、CollectionView这类可滚动、带虚拟回收的容器内部,固定放在页面底部/顶部的非滚动布局区域 - 不要给AdBanner设置
HorizontalOptions="CenterAndExpand"这类动态拉伸的布局属性,广告控件需使用固定尺寸,避免布局系统无法计算控件位置导致跳过渲染
所有广告加载、UI修改逻辑必须在主线程执行,后台线程触发的回调不会触发Xamarin.Forms的布局刷新流程,会导致修复不生效。
修复完成后,每次页面加载、导航进入页面时,广告控件都会自动完成测量、排列、渲染流程,无需用户交互即可稳定显示,跨页面返回也不会出现广告消失的问题。
内容的提问来源于stack exchange,提问作者Drew Morgan
相关产品推荐
相关产品推荐

