Рекламный баннер Admob обрезается при флаттере

Как показано на изображении рекламный баннер admob обрезан или растянут.

Если я использую AdSize.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;
    });

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

2
0
154
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Чтобы сделать его отзывчивым,

Пожалуйста, используйте MethodChannel для вызова любого нативного метода java/kotlin, написанного как часть нативного кода Android, который можно вызвать из вашего .dart файла.

Пример папки ресурсов: Официальный пример Flutter

Пример канала метода: Пример официального канала метода Flutter

Вам необходимо самостоятельно создать указанные ниже папки и файлы внутри папки android/app/src/main/res, установить эти значения самостоятельно и соответствующим образом настроить.

Вариант 1: математически обрабатывать размеры _finalSize и AdWidget на основе значений из файлов ресурсов измерений dimens.xml с использованием имен папок Имен квалификаторов конфигурации

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 ldpi

Определите дробь

<?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>

Получить дробь

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: Прочитайте ограничения в руководстве Понимание ограничений во флаттере

Вариант 3. Поместите SizedBox в другой макет, например линейный, и установите свойства макета так, чтобы центрировать поле, не растягивая его.

Вариант 4: создайте размерные объявления и вызовите AdHelper.bannerAdUnitId из values.xml значения.xml будут помещены в папки с несколькими размерами, например hdpildpi ... и т. д.

Это не применимо к Flutter, ни один из методов не существует.

Patola 30.05.2023 03:10

какой метод? получить ресурсы ()? ты о чем?

Dickens A S 30.05.2023 06:01

да еще и ресурс. XML

Patola 30.05.2023 08:01

Пожалуйста, используйте MethodChanneldocs.flutter.dev/platform-integration/platform-channels для вызова любого нативного метода java/kotlin, написанного как часть нативного кода Android, который можно вызвать из вашего .dart файла.

Dickens A S 30.05.2023 08:20

все эти xml-файлы ресурсов принадлежат собственному коду Android, который находится внутри вашего проекта флаттера с двумя папками androidios, где написан исходный собственный код

Dickens A S 30.05.2023 08:22

Вам нужно создать эти папки и файлы внутри папки android/app/src/main/res самостоятельно, установить эти значения самостоятельно и соответствующим образом настроить.

Dickens A S 30.05.2023 08:24

Замените виджет 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;
        });
    
        // 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();
      }
    }

Я надеюсь, что это сработает для вас.

это все еще отрезать содержание.

Patola 31.05.2023 03:58
Ответ принят как подходящий

Это видимо известная проблема. Отслеживается разработчиками. Еще не решено.

Обходной путь можно найти здесь. Не идеально.

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

Если я использую виджет AdSize.banner не занимает всю ширину, а показывает реклама правильно. Если я использую полный баннер, реклама растягивается.

Это потому что:

  • AdSize.banner Фактический размер 320x50.
  • AdSize.fullBanner Фактический размер 468x60.

Имейте в виду, что эти размеры фиксированы независимо от фактического размера экрана устройства. Чтобы уточнить, кажется, что ширина экрана эмулятора, которую вы используете, меньше 468 и больше 320.

Поэтому вам необходимо указать нестандартный размер в виде AdSize. Вместо объявления size и _finalSize как

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

они могут быть чем-то вроде

// 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;

На данный момент я бы предположил, что нет необходимости оборачивать SizedBox в метод build с помощью Expanded.


Кроме того, вот совет:

Использовать

SizedBox.shrink();

вместо

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

Используйте эту линию

size: AdSize.banner

или

AdSize size = AdSize.banner;

Другие вопросы по теме

Похожие вопросы

.NET MAUI Отменить исчезновение события при обнаружении изменений в представлении
«В запросе указаны недопустимые учетные данные для аутентификации» при использовании cURL для вызова Firebase Cloud Messaging
Force Composable, чтобы занять как можно большую высоту
ОШИБКА: не удалось установить приложение: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED (React-Native-Android-Studio)
PermissionAndroid.request() всегда возвращает never_ask_again без запроса. Реагировать на родной
Как закрыть/закрыть приложение с помощью Android Studio Kotlin при нажатии кнопки «Назад»?
Что такое android.stamp в манифесте Android?
Ошибка установки приложения Flutter Android Physical Device: «Приложение не установлено, так как пакет кажется недействительным»
Как мне сделать так, чтобы это сообщение чата правильно выстраивало свои свойства?
Как получить правильный идентификатор пользователя при создании приложения для создания заметок с поддержкой входа в систему с помощью Jetpack Compose и базы данных Room в Android Studio?