4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

カスタムAppBarを作成して使おうとしたら、型の不一致エラーが発生したので調べてみた:The argument type 'ReUsableAppBar' can't be assigned to the parameter type 'PreferredSizeWidget?'.

Last updated at Posted at 2024-02-25

Flutterを使ってアプリ開発をしていると、UIをカスタマイズしたくなる瞬間が必ずやってきます。
特に、アプリの顔とも言えるAppBarは、デザインにおいて重要な役割を果たします。
そこで、私はReUsableAppBarという名前でカスタムAppBarウィジェットを作成することにしました。これはStatelessWidgetを継承し、再利用しようとしたらエラーが....

コード

カスタムAppBar
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:x_clone/constants/assets_constants.dart';

class ReUsableAppBar extends StatelessWidget {
  const ReUsableAppBar({super.key});

  @override
  Widget build(BuildContext context) {
    return AppBar(
     title: Text("Reusable AppBar"),
    );
  }
}

遭遇した問題

問題のコード
class LoginView extends StatefulWidget {
  const LoginView({super.key});

  @override
  State<LoginView> createState() => _LoginViewState();
}

class _LoginViewState extends State<LoginView> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: ReUsableAppBar(),
    );
  }
}

AppBarカスタムウィジェットをScaffoldに組み込んで実行したところ、予期せぬエラーが発生しました。

The argument type 'ReUsableAppBar' can't be assigned to the parameter type 'PreferredSizeWidget?'.

「PreferredSizeWidget?」って何?と思い、調べてみました。
どうやら、これはウィジェットの高さに関係している重要なインターフェースのようです。

原因の解明

Scaffold内で宣言される際に、AppBarはフレームワークによって自動的に適切な高さが決定されます。これはAppBarPreferredSizeWidgetインターフェースを実装しているためで、このインターフェースを通じてAppBarの高さ情報がFlutterに伝えられます。

しかし、私が作成したReUsableAppBarカスタムウィジェットでは、このPreferredSizeWidgetインターフェースを明示的に実装していませんでした。そのため、Flutterフレームワークはカスタムウィジェットの高さを自動的に判断できず、ScaffoldappBarプロパティに割り当てようとした際に型の不一致エラーが発生してしまったのです。

[解決策1]AppBarウィジェットを返す静的メソッドを持つユーティリティクラス(例: UIConstants)を作成する

解決の鍵は、UIConstantsというユーティリティクラスを作成し、その中でAppBarウィジェットを返す静的メソッドを定義することでした。
このメソッドを通じてAppBarウィジェットを直接取得することで、AppBar自体が既にPreferredSizeWidgetを実装しており、そのpreferredSizeプロパティを通じて高さ情報を提供しているため、型の不一致の問題は解決されます。

class UIConstants {
  static AppBar appBar() {
    return AppBar(
      title: Text("Reusable AppBar"),
    );
  }
}

この方法を用いることで、カスタムAppBarScaffoldappBarプロパティに問題なく割り当てることができました。

上手くいったコード
import 'package:flutter/material.dart';
import 'package:x_clone/constants/ui_constants.dart';

class LoginView extends StatefulWidget {
  const LoginView({super.key});

  @override
  State<LoginView> createState() => _LoginViewState();
}

class _LoginViewState extends State<LoginView> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: UIConstants.appBar(),
    );
  }
}

[解決策2]StatelessWidgetを継承し、PreferredSizeWidgetを実装するカスタムAppBarウィジェットを作成する

この方法では、カスタムウィジェット内でAppBarを使用し、同時にPreferredSizeWidgetインターフェースを実装して、preferredSizeプロパティを提供します。これにより、ウィジェットの高さを明示的にFlutterに伝えることができます。

class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
  const CustomAppBar({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return AppBar(
      title: Text("カスタムAppBar"),
    );
  }

  @override
  Size get preferredSize => Size.fromHeight(kToolbarHeight); // ここでAppBarの高さを指定
}
//preferredSizeプロパティは、AppBarの高さを指定するために使用されます。
//kToolbarHeightはFlutterが提供する標準のアプリバーの高さの定数
  • カスタムAppBarクラスがPreferredSizeWidgetインターフェースを実装するようにします。
    • 実装するためには、クラス宣言の一部としてPreferredSizeWidgetを追加し、必要なpreferredSizeプロパティをオーバーライドします。

まとめ

カスタムAppBarウィジェットをScaffoldで使用する場合、二つの方法を紹介しました。

  1. StatelessWidgetを継承し、PreferredSizeWidgetを実装するカスタムAppBarを作成する方法

  2. AppBarウィジェットを返す静的メソッドを持つユーティリティクラスを定義する方法

どちらの方法も、FlutterのPreferredSizeWidgetの要件を満たし、型の不一致エラーを回避することができます。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?