英文:
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<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();
}
}
答案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
中的值,在文件夹名称配置限定符名称下,数学处理_finalSize
和AdWidget
大小。
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" 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: 在flutter中阅读指南Understanding constraints中的约束条件。
选项3: 将SizedBox放在另一个布局内,设置布局属性以使框居中而不拉伸它。
选项4: 创建大小广告并从values.xml
中调用AdHelper.bannerAdUnitId
,values.xml将放置在多个大小的文件夹中,如hdpi
,ldpi
等。
英文:
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" 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
Define a fraction
<?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>
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<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();
}
}
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,
);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论