半農半エンジニアの記録

関西在住エンジニア。個人で勉強・開発したこと、その他趣味のことを書いてます。農業してます。

Flutter で作ったアプリに広告表示する(firebase_admob)

Flutter で作ったアプリで広告収入を得るために、admob ツールを使った。 firebase_admob という公式チームが作成しているライブラリがあるので、そちらを利用する。

pub.dev

気になったこと

アプリに広告を表示するまでの手順は、こちらのブログに書かれている手順に沿って設定できた。

[Flutter] AdMob を使ってバナー広告を表示する方法 │ Web備忘録

バナー広告でやってみて設定・表示するだけだと問題なくできたが、ちょっと工夫・考慮が必要な部分があった。
以下、画面下バナー広告を表示した場合の話

縦・横表示対応に向いていない

横向き(landscape)だと必然的に高さが小さく、広告でそれがさらに小さくなる。UI・UX 的に難ありなので縦(portrait)固定にした。

void main() {
  FirebaseAdMob.instance.initialize(appId: appId);
  // バナー広告を表示する
  myBanner
    ..load()
    ..show(
      // ボトムからのオフセットで表示位置を決定
      anchorOffset: 0.0,
      anchorType: AnchorType.bottom,
    );

  // 縦固定
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);

  runApp(MyApp());
}

位置調整が必要

ライブラリにより表示される広告は、Flutter の世界からは切り離されている。つまり Widget ではない。なので普通に画面いっぱい表示させると Widget の上に広告が表示される。

例えば Floating action button はデフォルトで右下(bottomEnd)に表示されるが、広告がその上に表示されるので、ボタンは完全に隠れてしまう。

なので Padding を追加して広告を避けさせる必要がある。 *1

Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        ...
      ),
      body: Container(
        ...
      ),
      floatingActionButton: Padding(
        padding: const EdgeInsets.only(bottom: 90.0),
        child: FloatingActionButton(
          ...
        ),
      ),
    );
  }

キーボード出現時の位置調整

上記の位置調整をしたとき、更に問題が出てくるパターンがある。それは入力がある画面の場合だ。

キーボードが出てきたときに、Flutter のオブジェクトはキーボードが出てきた分を認識して下端がキーボードの上端になる。しかし広告は上記の通り Flutter とは切り離されており、かつキーボードを認識しない。そのため広告はキーボードによって隠されてしまう。

これで何が問題かというと、位置調整で Padding したぶんがそのまま適用されてしまっており、広告がないのに広告の分だけ Padding されたままになってしまうのである。
なのでこれを解決するには、キーボードが開いているかどうかを判定し、 Padding を動的に設定する必要がある。

ただし Flutter ではそのようなプロパティは用意されていないようなので、下記のpackage を使って対応することにした。*2

pub.dev

 @override
  void initState() {
    super.initState();
    KeyboardVisibilityNotification().addNewListener(
      onShow: () {
        _padding = EdgeInsets.all(0.0);
      },
      onHide: () {
        _padding = EdgeInsets.only(bottom: 90.0);
      },
    );
  }

という感じで違和感なく広告が表示できるようになったんじゃないかと思う。

*1:Scaffold の floatginActionButton は、FloatingActionButton を設定する必要はないので Padding でラップが可能

*2:MediaQuery.of(context).viewInsets.bottom の値で判定する方法を取っている人もいるようだが、Android でのみ動作し iOS では正常に動作しないらしい