プログラミング

FlutterでTwitterクライアント作成⑤カスタムウィジェットでListTileっぽく

2020-03-31




前回の続き。

FlutterでTwitterクライアント作成④タイムラインをListTileで装飾

前回の続き。 今回はタイムラインの表示をTwitterっぽくします。 目次1 Flutter標準のUIを使用する1.1 tweetをリスト形式で表示する1.1.1 LinkedHashMapの追加1. ...

続きを見る

今回は結構な大改造になりました。
いろいろ手探りでやってるので仕方なし。

カスタムウィジェットを作成する

前回はListTileを使いましたが、これだとタイムラインのUIを満たせないので独自ウィジェットを作成します。

ちなみにmaterial UIのソースはSDKの中に入ってるので、list_tile.dartをコピーすれば拡張できるみたいです。
でもこいつを読み解くのがしんどそうだったので今回は自作します。

最終的な完成図はこんな感じです。
※わかりやすくするために背景に色を付けてます

custom_card.dartを作成する

どうでもいい…くないんですけど、Flutterの構成ってどうしたらいいのかよくわかりませんね。
BLoCとかpackage:providerとか言いますが、これらを理解してからやろうとするとちっとも前に進まないので、今回は超我流パターンで進めています。

ということで、lib/ui/の下にcustom_card.dartを作りました。
他から呼び出されたときにカスタムウィジェットを返します。

実際に叩かれるメソッド

カード用の情報をもらって、特定のカードを返すためのメソッド。
cardIdによって返すカードを変える想定です。

返却されるStatelessWidget

実際に返却されるウィジェット_BaseCard。
将来的にこいつを継承していろいろ作る予定です。

引数を受け取るために、クラス変数を用意しておきます。

RowとColumnを組み合わせてCardを作ってます。
インスペクターで見るとこんな感じ。

Row or Columnの中身を比率で分割するExpanded

ユーザーアイコンとテキスト部分を分けるために、ExpandedでRowの中身を1:5で分割しています。

右側はさらにColumnを入れてます。
こちらは比率指定不要なのでExpandedなし。

ちなみに、中身に合わせて収縮するFlexibleというのもあります。
詳細はこちらの説明を参照。

子要素の並べ方を指定するAxisAlignment

RowやColumnはそのままだと全部中央寄せになってしまいます。
調整するにはmainAxisAlignmentまたはcrossAxisAlignmentを指定します。
AxisAlignmentのわかりやすい説明はこちら

んで、これがcrossAxisAlignmentを指定しなかった場合。

  • ユーザーアイコンを上に寄せたい
  • screenNameを左に寄せたい
  • textを左に寄せたい

ということで、それぞれcrossAxisAlignment.startを指定した結果がこう。

これでとりあえずウィジェットは完成です。

Twitter API接続用のモデルを作成する

home_route.dartの中でごちゃごちゃ処理しすぎるのもよくないので、API接続部分を切り出してtwitter_api_model.dartとしました。
home_route.dartの修正内容は後で書きます。

twitter_api_model.dartを作成する

lib/model/直下に作ります。

中身はこれだけ。
接続先(path)とパラメータ(param)をもらってAPIにGETで接続し、jsonDecodeしてから返します。

カードのリストを返すモデルを作成する

home_route.dartの中でごちゃごちゃ(略)API名を指定したらカードリストを返してくれるモデルを作りました。

twitter_card_model.dartを作成する

MVVMっぽく考えたらmodelでいいはず。
ってことで、lib/model/twitter_card_model.dartを作成します。

作成したファイル2つをインポート

先ほど作成したcustom_card.dartとtwitter_api_model.dartを追加します。

APIを指定して該当のカードリストを返すメソッド

引数で受け取ったapiNameをGetTweetsJsonに渡してAPIでデータを取得します。

さらに、取得したJsonをCustomCard().createCardに渡してカードリストを作成します。
今はカードの種類が1つしかない(text1)ですが、画像付きカードなどが増えたらここに分岐を追加してカードIDを切り替える予定です。

APIに接続してJsonから取得したデータを詰めて返すメソッド

Jsonの取得と必要なデータの収集をこの中で行っています。
対象がタイムラインでもツイートの検索結果でも取得する内容は同じだと思われるので、接続先とパラメータだけ変えるようにしてあります。

home_route.dartを修正する

周囲をいろいろいじったので、home_route.dartも合わせます。
全体はこんな感じ。

importを整理する

いろいろと外に切り出したので、不要なものがいくつか。
以下のように修正します。

_loadでカードリストを取得する

以前は_loadの中でTwitterAPIに接続していましたが、今回はカードリストを受け取るだけ。

カードリストを受け取る変数の用意

TwitterCardModelの戻り値を受け取るための_cardListを用意。
後で代入するのでfinalはつけません。

_tweetsと_timelineDataはもういらないので削除。

initStateにsetStateを追加

以前は_load()の中で実行していたsetStateですが、外に出します。

_load()でCreateCardListを実行

Jsonを取得するためにやっていた処理は全部削除。
CreateCardListを実行するコードを1行だけ追加します。

この処理をsetStateの中でやろうとするとasyncがないとダメだよ!と怒られます。
なのでここでは_cardListの値だけを更新して、setStateは_load()の後で実行してます。

FutureBuilderで取得したカードを非同期で表示する

_cardListの取得は非同期なので、画面を表示した時点ではまだ描画するデータがありません。
FutureBuilderを使ってデータ取得中はローディングアイコンを表示し、取得が終わったらカードリストを描画するようにします。

ローディングアイコンは用意されてるものを呼ぶだけ

Flutterではローディング用ウィジェットが2種類用意されています。

画面の表示待ちはCircularProgressIndicatorかなーと思います。

ついでにheader.dartをuiに移動しておく

せっかくuiフォルダ作ったので、lib直下にあったheader.dartをlib/ui/下に移動しました。
各routesのimport部分を修正しておきます。
本当はroot.dart内のBottomNavigationBarもフッターとして切り出したい…けど、力尽きたのでまた今度。

全部できたらビルドしよう

ここまで出来たらようやく動かせます。
画像などがないのでローディングアイコンは一瞬しか出ません。

背景色を消すとこんな感じ。
なんとなーくそれっぽくなりました。

カスタマイズは続く

今回、ようやくTailListの内容に追いついたくらいですね。
ここからまだまだカスタマイズしないといけません。

長くなったので、ボタン追加したりなんだりは次回で。

FlutterでTwitterクライアント作成⑥タイムラインの各種ボタンを追加する

前回の続き。 コードを読み直してたら、クソ実装というか謎実装してることに気づいたので直しました。 なんでその実装にしようとしたのか全く思い出せない。 過去の自分は別の人。 目次1 CustomCard ...

続きを見る

ここまでのコードはGitHubで。

-プログラミング
-,

© 2024 そんなこと猫でもできる Powered by AFFINGER5