見出し画像

書籍情報保管アプリ #10 『sliverAppBarを用いた書籍一覧ページUI』

前回はアプリのアイコンを作成しました。(アイコンデザインは後で変えたいと思っていますが。)

今回は、書籍一覧ページの見た目をもう少し更新しました。前々回に読書目標の達成率を円上のゲージグラフで表示するところまで作成していました。


sliverAppBarって何?

書籍の一覧で、本の数が増えて下にスクロールした時に、一覧画面上にある円グラフなどの表示が「ぬるっと」消える表示にしたいなー。と思い、調べたところsliverAppBarなるものがあることがわかりました。

こちらの本にも記載があります。なんか今時感(古い?)を期待させてくれます。


sliverAppBarってどうやって実装する?

sliverAppBarを使うにあたり、改修・確認が必要だったのは、

  • 元々設置していたAppBarをどうするか

  • bodyの中に記載していたstreamBuilderどうするか?streamBuilderをsliverAppBarに入れられるか

  • もう一つbodyの中に記載しているstreamBuilderもsliverList/sliverGridにできるか

の3つでした。結論から言えば、いくつかトラブル発生したものの無事思ったことが達成できました。一つずつ説明していきます。

まずAppBarのお引越し

今回の改修にあたり、あらためてコードを確認していくと、Loginの実装のところで、Scaffoldが2階建で入れ子になっていることに気づいてしまいました。。(おそい?)

実際は大きな問題ではなかったのですが、

  • ユーザーのログイン状態をチェックするStatefulWidgetのページにScaffoldがあって、その中でログイン後のページを関数で呼出し

  • 呼び出された関数(StatefulWidget)でもScaffoldが定義されていました。

AppBarは、1つ目のScaffoldで定義(記載)されていたのですが、なんとなく気持ちが悪かったので、2つ目のログイン後のページを記載しているStatefulWidgetのScaffoldの方で記載し直し。(本当は、sliverAppBarと一緒にしようかと思ったのですが、いったんappBar + sliverAppBarの2階建てにしました。)

sliversにstreamBuilder記載できるか?

次は、sliverAppBarの前に、sliversの方にstreamBuilder(本の一覧)を記載していきます。sliversに直接streamBuilderの形で記載できるようです。コードの改修はそれほど多くありません。記載場所を、columnの下から、sliversの下に移動するくらいです。

参考にしたのはこちら。引用したら長くなったのですが、39行目でsliversが記載されていて、40行目のsliverAppBarの後に49行目でstreamBuilderが記載されています。

上に記載の例は、sliverListになっているので、sliverGridにしますが、こちらも大きな変更はないようです。下記を参考にしました。

落とし穴にハマる。。

実は、ここまで記載した内容と後で記載するsliverAppBarの実装までHotReloadしながら「サクサク」進んで、夕食前に「完成!」したのですが、アプリ停止して再コンパイルしたらエラーが発生!!

まったく内容がわからなかったので全部始めからやり直して、要因特定しました。エラーの原因は、sliversの中にcenterやTextなどの「普通の」Widgetがあったことでした。

下に載せたコードのように、エラー用の表示をSliverToBoxAdapter Widgetに入れてあげる必要がありました。

              builder: (context, snapshot) {
                if (snapshot.hasError) {
                  return const Text('Failed to obtain data');
                }
                if (!snapshot.hasData) {
                  return const Center(child: CircularProgressIndicator());
                }
・・・
                          }
            builder: (context, snapshot) {
              if (snapshot.hasError) {
                return const SliverToBoxAdapter(
                    child: Text('Failed to obtain data'));
              }
              if (!snapshot.hasData) {
                return const SliverToBoxAdapter(
                    child: Center(child: CircularProgressIndicator()));
              }
・・・
                        }

さらに落とし穴は、なぜかsliverAppBarの方は、「普通の」WidgetのままでOKというところ。。。詳しい理由はよくわかっていません。

sliverAppBarにstreamBuilderを記載する

sliversに記載できた後は、先ほど記載した落とし穴以外に特殊無事はありません。ぬるっと消えるようにするために、backgroundプロパティにStream Builderを設定します。

          flexibleSpace: FlexibleSpaceBar(
            background: StreamBuilder<QuerySnapshot>(
・・・
                        )
                         )

おまけ:google APIに情報が欠落している場合に対応する

何気なく本の登録をしようとしたところエラーが発生。よくよく調べるとgoogleAPIのJSONに書影の情報が欠落しているにも関わらず、配列を読みにいっていたためnullのエラーが発生しているようでした。

書影情報「thumbnail」がない時には、「imageLinks」もnullになるため、nullチェックの?を["imageLinks"]の後ろにつけるのと、全体的にnullの可能性がある情報にnullの場合に空の文字列’’を代入する処理(?? '')設定しました。

        imagePath = bookInfo["items"][0]["volumeInfo"]["imageLinks"]
                ?["thumbnail"] ??
            '';

        description = bookInfo["items"][0]["volumeInfo"]["description"] ?? '';
        pages = bookInfo["items"][0]["volumeInfo"]["pageCount"] ?? '';
        lang = bookInfo["items"][0]["volumeInfo"]["language"] ?? '';

今の見た感じ

下にスクロールすると円グラフや本の冊数などの表示がぬるっと消えます。


今後やりたいこと

  • ライセンス関係表示

  • ユーザー登録時にプロファイル情報を取得する

  • Appleアプリに公開!

  • 書評保存(まずはタグ付けする)

  • 多言語化する

  • パスワードを忘れた場合に対処する

  • ログイン画面(以下のページ参照)

  • 本一覧表示(以下のページ参照)

  • UI/UXの修正(今回実施しました。大体終了。あとZoomも入れたいかな。)

  • 登録した本の削除(以下のページ参照)

  • コードの整理(Classの再定義など)(以下のページ参照)

  • 本の一覧の検索・並べ替え(以下のページ参照。まだ継続必要)

  • GoogleBookAPIも使えるようにする(以下のページ参照。)

  • 本の情報追加する(以下のページ参照。出版社は別途OpenBDで補完必要。)

  • アイコンの作成(以下のページ参照。)


この記事が気に入ったらサポートをしてみませんか?