---
metadata:
  - name: generator
    content: Diplodoc Platform v5.52.0
alternate:
  - https://ads.yandex.com/helpcenter/en/dev/android/adaptive-sticky-banner.md
  - https://ads.yandex.com/helpcenter/ru/dev/android/adaptive-sticky-banner.md
  - https://ads.yandex.com/helpcenter/zh/dev/android/adaptive-sticky-banner.md
  - href: zh/dev/android/adaptive-sticky-banner.md
    type: text/markdown
    title: Markdown version
  - href: llms.txt
    type: text/markdown
    title: llms.txt
---
> **Documentation Index:** Fetch the complete configuration index at https://ads.yandex.com/helpcenter/zh/llms.txt

# 自适应粘性横幅

<!-- source: zh/dev/_includes/adaptive-sticky-banner.md -->
自适应固定横幅广告是一种小型广告，会自动更新，并显示在应用屏幕的顶部或底部。它不会遮挡主要内容，常用于游戏应用中。
<!-- endsource: zh/dev/_includes/adaptive-sticky-banner.md -->

<!-- source: zh/dev/_includes/adaptive-sticky-banner.md -->
自适应固定横幅广告会针对每台设备优化广告尺寸，从而实现最佳效果。借助这种广告类型，开发者可设置广告允许的最大宽度，系统将自动确定最佳广告尺寸。
<!-- endsource: zh/dev/_includes/adaptive-sticky-banner.md -->

{% cut "外观" %}

<img src="https://yastatic.net/s3/doc-binary/src/docs/support/mobile-ads/zh/monetization/_images/banner-sticky-zh-ex.png" width="200">

{% endcut %}

本指南介绍了将自适应粘性横幅集成到 Android 应用的过程。
除了代码示例和说明之外，它还包含特定格式的建议以及指向其他资源的链接。


## 前提条件 {#pre}

<!-- source: zh/dev/_includes/pre-android.md -->
1. 按照[快速入门](https://ads.yandex.com/helpcenter/zh/dev/android/quick-start.md) 中描述的 SDK 集成步骤进行操作。
2. 首先，您需要[初始化](https://ads.yandex.com/helpcenter/zh/dev/android/quick-start.md#init) 广告 SDK。
3. 确保您使用的是[最新Yandex Mobile Ads SDK 版本](https://ads.yandex.com/helpcenter/zh/dev/android/changelog-android.md)。如果您使用的是广告中介服务，请更新至最新的[单一构建版本](https://ads.yandex.com/helpcenter/zh/dev/android/changelog-android.md)。
<!-- endsource: zh/dev/_includes/pre-android.md -->

## 实施 {#implement}

集成自适应粘性横幅的关键步骤：

* 创建并配置用于显示横幅广告的视图。
* 注册回调监听器。
* 加载广告。
* 如果您使用 Adfox，请传递 [其他设置](https://ads.yandex.com/helpcenter/zh/dev/android/target-adfox.md)。

## 自适应粘性横幅集成的特点 {#features}

1.所有调用 Yandex Mobile Ads SDK 方法的操作必须在主线程中完成。

2.如果 `onAdFailedToLoad()` 回调返回错误，请勿再次尝试加载新广告。如果没有其他选项，请限制广告加载重试次数。如果有限制，这将有助于避免频繁出现失败的请求和连接问题。

3.自适应粘性横幅在充分利用可用宽度时效果最佳。通常情况下，这将是设备屏幕的全宽。请确保考虑应用设置的填充参数和安全显示区域。

4.要获取广告尺寸，请使用 `BannerAdSize.stickySize(context, adWidth)` 方法，该方法接受上下文和广告容器的可用宽度作为参数。

5.如您已启用聚合，我们强烈建议等待初始化完成，然后再计算粘性横幅的尺寸。在初始化完成前只有初步尺寸可供使用，在获取精确设置后，该尺寸可能发生变化。

6.通过 `BannerAdSize.stickySize(context, adWidth)` 方法计算的 `BannerAdSize` 对象中的广告宽度和高度值在相同设备上是一致的。在特定设备上测试应用布局时，可以确保该设备的广告尺寸保持不变。

7.自适应粘性横幅的高度不得超过屏幕高度的 15%，且不得小于 50 dp。

## 将广告视图添加到应用布局 {#add-view}

要显示横幅广告，请将 BannerAdView 添加到应用布局中。您可以通过编程方式或使用 XML 文件来完成该操作。

将 BannerAdView 添加到应用屏幕布局的示例：

```xml
# activity.xml
...
<com.yandex.mobile.ads.banner.BannerAdView
        android:id="@+id/ad_container_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent" />
...
```

您还可以通过编程方式创建 BannerAdView 实例：

{% list tabs %}

   - Kotlin

     ```kotlin
     val bannerAd = BannerAdView(this)
     ```

   - Java

     ```java
     final BannerAdView bannerAd = new BannerAdView(this);
     ```
{% endlist %}

## 加载和呈现广告 {#load}

创建 BannerAdView 并将其添加到应用屏幕后，您需要加载广告。在加载自适应粘性横幅之前，请为每个设备计算相应的广告尺寸。

此操作通过以下 SDK API 方法自动完成：`BannerAdSize.stickySize(context, adWidth)`。

请将上下文以及可接受的广告容器宽度最大值作为参数进行传递。我们建议使用设备屏幕的全宽度或父容器的宽度。请确保考虑应用设置的填充参数和安全显示区域：

{% list tabs %}

   - Kotlin

     ```kotlin
     private val adSize: BannerAdSize
         get() {
             // 计算广告的宽度，同时考虑广告容器中的内边距。
             var adWidthPixels = binding.adContainerView.width
             if (adWidthPixels == 0) {
                 // 如果广告尚未布局，则默认为全屏宽度
                 adWidthPixels = resources.displayMetrics.widthPixels
             }
             val adWidth = (adWidthPixels / resources.displayMetrics.density).roundToInt()

             return BannerAdSize.stickySize(this, adWidth)
         }
     ```

   - Java

     ```java
     @NonNull
     private BannerAdSize getAdSize() {
         final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
         // 计算广告的宽度，同时考虑广告容器中的内边距。
         int adWidthPixels = mBinding.adContainerView.getWidth();
         if (adWidthPixels == 0) {
             // 如果广告尚未布局，则默认为全屏宽度
             adWidthPixels = displayMetrics.widthPixels;
         }
         final int adWidth = Math.round(adWidthPixels / displayMetrics.density);

         return BannerAdSize.stickySize(this, adWidth);
     }
     ```
{% endlist %}

要加载广告，您还需要 Activity 上下文以及在 Yandex Advertising Network 界面中获取的广告单元 ID (adUnitId)。

要启用广告加载或加载失败的通知并跟踪自适应粘性横幅的生命周期事件，请为 BannerAdView 类实例设置 `BannerAdEventListener` 回调监听器。

您可以借助 `AdRequest.Builder()` 类扩展广告请求参数，以在广告请求中包含有关用户兴趣、页面上下文、位置以及其他附加数据的信息。在广告请求中添加额外的上下文信息可以极大地提高广告质量。如需了解更多信息，请参阅[广告定位](https://ads.yandex.com/helpcenter/zh/dev/android/target.md)。

以下示例展示了如何加载自适应粘性横幅。加载后，横幅将自动显示：

{% list tabs %}

   - Kotlin

     ```kotlin
     class StickyBannerAdActivity : AppCompatActivity(R.layout.activity_sticky_banner_ad) {
         private var bannerAd: BannerAdView? = null
         private lateinit var binding: ActivityStickyBannerAdBinding

         private val adSize: BannerAdSize
             get() {
                 // 计算广告的宽度，同时考虑广告容器中的内边距。
                 var adWidthPixels = binding.adContainerView.width
                 if (adWidthPixels == 0) {
                     // 如果广告尚未布局，则默认为全屏宽度
                     adWidthPixels = resources.displayMetrics.widthPixels
                 }
                 val adWidth = (adWidthPixels / resources.displayMetrics.density).roundToInt()

                 return BannerAdSize.stickySize(this, adWidth)
             }

         override fun onCreate(savedInstanceState: Bundle?) {
             super.onCreate(savedInstanceState)
             binding = ActivityStickyBannerAdBinding.inflate(layoutInflater)
             setContentView(binding.root)

             // 由于我们根据 adContainerView 大小加载横幅，
             // 我们需要等到该视图布局完毕后才能获取宽度
             binding.adContainerView.viewTreeObserver.addOnGlobalLayoutListener(object :
                 ViewTreeObserver.OnGlobalLayoutListener {
                 override fun onGlobalLayout() {
                     binding.adContainerView.viewTreeObserver.removeOnGlobalLayoutListener(this);
                     bannerAd = loadBannerAd(adSize)
                 }
             })
         }

         private fun loadBannerAd(adSize: BannerAdSize): BannerAdView {
             return binding.banner.apply {
                 setAdSize(adSize)
                 setAdUnitId("your-ad-unit-id")
                 setBannerAdEventListener(object : BannerAdEventListener {
                     override fun onAdLoaded() {
                         // 如果此回调发生在活动被销毁之后，您
                         // 必须调用 destroy 和 return，否则可能会出现内存泄漏。
                         // 注意 `isDestroyed` 是 Activity 上的一个方法。
                         if (isDestroyed) {
                             bannerAd?.destroy()
                             return
                         }
                     }

                     override fun onAdFailedToLoad(adRequestError: AdRequestError) {
                         // 广告加载失败，出现 AdRequestError。
                         // 强烈建议不要尝试通过 onAdFailedToLoad() 方法加载新广告。
                     }

                     override fun onAdClicked() {
                         // 记录广告点击时调用。
                     }

                     override fun onLeftApplication() {
                         // 当用户由于点击广告而即将离开应用程序（例如转到浏览器）时调用。
                     }

                     override fun onReturnedToApplication() {
                         // 当用户点击后返回应用程序时调用。
                     }

                     override fun onImpression(impressionData: ImpressionData?) {
                         // 记录广告展示次数时调用。
                     }
                 })
                 loadAd(
                     AdRequest.Builder()
                         // 此处可以使用 AdRequest.Builder 类中的方法来指定各个选项设置。
                         .build()
                 )
             }
         }
     }
     ```

   - Java

     ```java
     public class StickyBannerAdActivity extends AppCompatActivity {
         @Nullable
         private BannerAdView mBannerAd = null;
         private ActivityStickyBannerAdBinding mBinding;

         public StickyBannerAdActivity() {
             super(R.layout.activity_sticky_banner_ad);
         }

         @Override
         protected void onCreate(@Nullable Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             mBinding = ActivityStickyBannerAdBinding.inflate(getLayoutInflater());
             setContentView(mBinding.getRoot());

             // 由于我们根据 adContainerView 大小加载横幅，
             // 我们需要等到该视图布局完毕后才能获取宽度
             mBinding.adContainerView.getViewTreeObserver().addOnGlobalLayoutListener(
                     new ViewTreeObserver.OnGlobalLayoutListener() {
                         @Override
                         public void onGlobalLayout() {
                             mBinding.adContainerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                             mBannerAd = loadBannerAd(getAdSize());
                         }
                     }
             );
         }

         @NonNull
         private BannerAdSize getAdSize() {
             final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
             // 计算广告的宽度，同时考虑广告容器中的内边距。
             int adWidthPixels = mBinding.adContainerView.getWidth();
             if (adWidthPixels == 0) {
                 // 如果广告尚未布局，则默认为全屏宽度
                 adWidthPixels = displayMetrics.widthPixels;
             }
            final int adWidth = Math.round(adWidthPixels / displayMetrics.density);

             return BannerAdSize.stickySize(this, adWidth);
         }

         @NonNull
         private BannerAdView loadBannerAd(@NonNull final BannerAdSize adSize) {
             final BannerAdView bannerAd = mBinding.banner;
             bannerAd.setAdSize(adSize);
             bannerAd.setAdUnitId("your-ad-unit-id");
             bannerAd.setBannerAdEventListener(new BannerAdEventListener() {
                 @Override
                 public void onAdLoaded() {
                     // 如果此回调发生在活动被销毁之后，您
                     // 必须调用 destroy 和 return，否则可能会出现内存泄漏。
                     // 注意 `isDestroyed` 是 Activity 上的一个方法。
                     if (isDestroyed() && mBannerAd != null) {
                         mBannerAd.destroy();
                     }
                 }

                 @Override
                 public void onAdFailedToLoad(@NonNull final AdRequestError adRequestError) {
                     // 广告加载失败，出现 AdRequestError。
                     // 强烈建议不要尝试通过 onAdFailedToLoad() 方法加载新广告。
                 }

                 @Override
                 public void onAdClicked() {
                     // 记录广告点击时调用。
                 }

                 @Override
                 public void onLeftApplication() {
                     // 当用户由于点击广告而即将离开应用程序（例如转到浏览器）时调用。
                 }

                 @Override
                 public void onReturnedToApplication() {
                     // 当用户点击后返回应用程序时调用。
                 }

                 @Override
                 public void onImpression(@Nullable ImpressionData impressionData) {
                     // 记录广告展示次数时调用。
                 }
             });
             final AdRequest adRequest = new AdRequest.Builder()
                     // 此处可以使用 AdRequest.Builder 类中的方法来指定各个选项设置。
                     .build();
             bannerAd.loadAd(adRequest);
             return bannerAd;
         }
     }
     ```
{% endlist %}

<!-- source: zh/dev/_includes/ad-attributes.md -->
如果您通过 Adfox 投放广告，则在横幅广告响应后，可以使用 `AdAttributes` 类型的 `adAttributes` 属性从 `BannerAdView` 对象访问 `campaignId`、`bannerId` 和 `placeId` 数据。
<!-- endsource: zh/dev/_includes/ad-attributes.md -->

## 释放资源 {#destroy}

如果回调发生在 Activity 被销毁之后，请为使用的广告对象调用 `destroy()` 函数以释放资源：

{% list tabs %}

   - Kotlin

     ```kotlin
     private fun loadBannerAd(adSize: BannerAdSize): BannerAdView {
         return binding.banner.apply {
             setBannerAdEventListener(object : BannerAdEventListener {
                 override fun onAdLoaded() {
                     // 如果此回调发生在活动被销毁之后，您
                     // 必须调用 destroy 和 return，否则可能会出现内存泄漏。
                     // 注意 `isDestroyed` 是 Activity 上的一个方法。
                     if (isDestroyed) {
                         bannerAd?.destroy()
                         return
                     }
                 }
                 ...
             })
             ...
         }
     }
     ```

   - Java

     ```java
     @NonNull
     private BannerAdView loadBannerAd(@NonNull final BannerAdSize adSize) {
         final BannerAdView bannerAd = mBinding.banner;
         bannerAd.setBannerAdEventListener(new BannerAdEventListener() {
             @Override
             public void onAdLoaded() {
                 // 如果此回调发生在活动被销毁之后，您
                 // 必须调用 destroy 和 return，否则可能会出现内存泄漏。
                 // 注意 `isDestroyed` 是 Activity 上的一个方法。
                 if (isDestroyed() && mBannerAd != null) {
                     mBannerAd.destroy();
                 }
             }
             ...
         });
         ...
         return bannerAd;
     }
     ```
{% endlist %}

## 测试自适应粘性横幅集成 {#test}

<!-- source: zh/dev/_includes/test-android-sticky-banner.md -->
### 使用演示广告单元进行广告测试 {#demo-blocks}

使用测试广告来检查您的自适应固定横幅广告集成和应用本身。为了确保每次广告请求都能返回测试广告，您可以使用一个特殊的演示广告版位 ID。

演示广告单元 ID：`demo-banner-yandex`.

{% note warning %}

在应用商店发布应用前，请务必将演示广告版位 ID 替换为您在 Yandex Advertising Network 接口中获取的真实 ID。

{% endnote %}

有关所有可用演示广告版位 ID 的列表，请参阅[用于测试的演示广告单元](https://ads.yandex.com/helpcenter/zh/dev/android/demo-blocks.md)。

### 测试广告集成 {#test-int}

您可以使用 SDK 的内置分析工具检查自适应固定横幅广告是否已正确集成。日志中将显示包含测试结果的详细报告。

要查看报告，请在 Android 应用调试工具 [Logcat](https://developer.android.com/studio/command-line/logcat) 中搜索关键词“YandexAds”。

```bash
adb logcat -v brief '*:S YandexAds'
```

如果集成成功，将返回以下消息：
```bash
adb logcat -v brief '*:S YandexAds'
mobileads$ adb logcat -v brief '*:S YandexAds'
I/YandexAds(13719): [Integration] Ad type banner was integrated successfully
```

如果存在任何横幅广告集成问题，您将收到详细的问题报告和故障排除建议。
<!-- endsource: zh/dev/_includes/test-android-sticky-banner.md -->

## 其他资源 {#resources}

* <!-- source: zh/dev/_includes/github-pubdev-links.md -->
  [GitHub](https://github.com/yandexmobile/yandex-ads-sdk-android) 链接。
  <!-- endsource: zh/dev/_includes/github-pubdev-links.md -->
