Admob横幅广告在Flutter上被截断。

huangapple go评论74阅读模式
英文:

Admob Banner ad is cut off on flutter

问题

如图所示,Admob横幅广告被切割或拉伸。

如果我使用AdSize.banner小部件,则不会占据整个宽度,但会正确显示广告。如果我使用full-banner,则广告会被拉伸。

我如何使横幅广告适应屏幕的整个宽度并正确显示内容(不切割或拉伸)?

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;
    });

    // 获取当前方向的内联自适应尺寸。
    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}');

          // 广告加载后,获取平台广告尺寸并使用它来更新容器的高度。这是必要的,因为广告加载后高度可能会改变。
          BannerAd bannerAd = (ad as BannerAd);
          _finalSize = await bannerAd.getPlatformAdSize();

          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();
  }
}
英文:

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&lt;AdBanner&gt; {
  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(&#39;Inline adaptive banner loaded: ${ad.responseInfo}&#39;);

          // 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(
          //       &#39;Error: getPlatformAdSize() returned null for $bannerAd&#39;);
          //   return;
          // }

          setState(() {
            _inlineAdaptiveAd = bannerAd;
            _isLoaded = true;
          });
        },
        onAdFailedToLoad: (Ad ad, LoadAdError error) {
          debugPrint(&#39;Inline adaptive banner failedToLoad: $error&#39;);
          ad.dispose();
        },
      ),
    );
    await _inlineAdaptiveAd!.load();
  }

  @override
  Widget build(BuildContext context) {
    return (_inlineAdaptiveAd != null &amp;&amp; _isLoaded &amp;&amp; _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();
  }
}

Admob横幅广告在Flutter上被截断。

答案1

得分: 3

这显然是一个已知问题。由开发人员跟踪。尚未解决。

解决方法可以在这里找到。不是完美的。

https://github.com/googleads/googleads-mobile-flutter/issues/261#issuecomment-1293001373

英文:

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

答案2

得分: 1

为使其响应式,请使用MethodChannel来调用任何作为Android原生代码的一部分编写的本机Java/Kotlin方法,这些方法可以从您的.dart文件中调用。

示例资源文件夹:Flutter官方示例

示例MethodChannel:Flutter官方MethodChannel示例

您需要自己在android/app/src/main/res文件夹中创建以下文件夹和文件,并自行放置这些值并进行相应调整

选项1: 根据维度资源文件dimens.xml中的值,在文件夹名称配置限定符名称下,数学处理_finalSizeAdWidget大小。

values-sw720dp          10.1” 平板 1280x800 mdpi
values-sw600dp          7.0”  平板 1024x600 mdpi
values-sw480dp          5.4”  480x854 mdpi 
values-sw480dp          5.1”  480x800 mdpi 
values-xxhdpi           5.5&quot;  1080x1920 xxhdpi
values-xxxhdpi          5.5&quot; 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 ldpi

定义一个分数

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
 &lt;resources&gt;
     &lt;fraction name=&quot;division_factor_width&quot;&gt;0.31&lt;/fraction&gt;
     &lt;fraction name=&quot;division_factor_height&quot;&gt;0.41&lt;/fraction&gt;
 &lt;/resources&gt;

获取分数

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!,
       )))

选项2: 在flutter中阅读指南Understanding constraints中的约束条件。

选项3: 将SizedBox放在另一个布局内,设置布局属性以使框居中而不拉伸它。

选项4: 创建大小广告并从values.xml中调用AdHelper.bannerAdUnitId,values.xml将放置在多个大小的文件夹中,如hdpildpi等。

英文:

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&quot;  1080x1920 xxhdpi
values-xxxhdpi           5.5&quot; 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 ldpi

Define a fraction

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
 &lt;resources&gt;
     &lt;fraction name=&quot;division_factor_width&quot;&gt;0.31&lt;/fraction&gt;
     &lt;fraction name=&quot;division_factor_height&quot;&gt;0.41&lt;/fraction&gt;
 &lt;/resources&gt;

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

答案3

得分: 0

请将Expanded小部件替换为LayoutBuilder,并根据以下约束计算最大可用宽度(maxWidth)-

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;
    });

    // 获取当前方向的内联自适应尺寸。
    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();
  }
}

我希望这对您有所帮助。

英文:

Replace the Expanded widget with a LayoutBuilder and calculate the maximum available width (maxWidth) based on the constraints as below-

 class _AdBannerState extends State&lt;AdBanner&gt; {
      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(&#39;Inline adaptive banner loaded: ${ad.responseInfo}&#39;);
    
              setState(() {
                _inlineAdaptiveAd = ad as BannerAd;
                _isLoaded = true;
              });
            },
            onAdFailedToLoad: (Ad ad, LoadAdError error) {
              debugPrint(&#39;Inline adaptive banner failedToLoad: $error&#39;);
              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 &amp;&amp; _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.

答案4

得分: 0

如果我使用AdSize.banner小部件,它不会占据整个宽度,但会正确显示广告。如果我使用full-banner,广告会被拉伸。

这是因为:

  • AdSize.banner 的实际大小是 320x50。
  • AdSize.fullBanner 的实际大小是 468x60。

请记住,这些大小是固定的,与实际设备屏幕大小无关。澄清一下,似乎您使用的模拟器屏幕宽度小于 468,大于 320。

因此,您需要提供一个自定义大小作为 AdSize。不要像这样声明 size_finalSize

AdSize size = AdSize.fullBanner;
_finalSize = const AdSize(height: 40, width: 320);

它们可以像这样:

// 直接在BannerAd创建中使用
AdSize size = AdSize(
  width: MediaQuery.of(context).size.width.toInt(),
  height: 40,
);

// ...

// 然后让 _finalSize 保持相同的大小以供以后使用(在build方法中)
_finalSize = size;

在这一点上,我会假设在build方法中不需要用Expanded包装SizedBox

另外,这里有个提示:

使用

SizedBox.shrink();

而不是

const SizedBox(
  width: 0,
  height: 0,
);
英文:

> 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.
<br/><br/>

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,
);

huangapple
  • 本文由 发表于 2023年5月24日 17:40:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76322130.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定