リバース・エンジニアリング

Flultterとテックブログと時々iOS

22. RSSアプリを色々カスタマイズしてみる

今回はRSSアプリのカスタマイズをしていきます。 デザインの調整がメインになります。

RSSアプリの作成

tamappe.hatenadiary.com

RSSアプリの詳細ページの作成

tamappe.hatenadiary.com

separatorを追加する

まず最初にiOSにあるようなUITableViewのseparatorを作成します。 作り方はListTileListTile.divideTilesにすれば可能です。

ListView(
          padding: EdgeInsets.all(10.0),
          children: ListTile.divideTiles(
              color: Colors.black,
              context: context,
              tiles: _items
          ).toList(),
        ),

separatorの線の色をblack指定しました。

f:id:qed805:20200223154550p:plain
黒色のセパレータ線を追加する

このように線が表示されていたら成功です。

日付のフォーマットを整える

次にRSSで受け取った日付がタイムゾーンを含んだものになっているのでDateを調整して日本時刻に変換します。 実はアプリ開発で扱いが難しいのは日付のデータだったりするのですが、Flutterも例外ではありません。

とりあえずFlutterで日付を操作するパッケージがありますので紹介します。

Intl

pub.dev

パッケージを使うためにpubspec.yamlファイルにIntlを書きます。

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.2
  webfeed: ^0.4.2
  http: ^0.12.0+4
  webview_flutter: ^0.3.19+7
  intl: ^0.15.7 # こちらを追加する

パッケージをアップデートしたらインストール完了です。 まだintlの理解が及んでいませんが、DateTime.parse()タイムゾーンを含んだStringを DateFormatで指定した文字列形式に変換することができました。

例えば、次のようなメソッドを書きます。

Widget convertText(String published) {
    var formatter = DateFormat('yyyy年MM月dd日');
    final date = DateTime.parse(published);
    var formatted = formatter.format(date);
    return Text(formatted);  /// 2020年MM月dd日と表示される
  }

これでStringのpublishedから指定の日付フォーマットに変換されたTextウィジェットを作成することができました。 前回作成したRSSアプリのrss_list_page.dartを次のように修正します。

rss_list_page.dart

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:rss_app/item_detail_page.dart';
import 'package:webfeed/webfeed.dart';
import 'package:http/http.dart';

class RssListPage extends StatefulWidget {
  final String title;
  final String url;

  RssListPage({@required this.title, @required this.url});

  @override
  _RssListPageState createState() => _RssListPageState(title: title, url: url);
}

class _RssListPageState extends State<RssListPage> {
  final String _rssUrl = "https://qiita.com/tamappe/feed.atom";
  final String title;
  final String url;
  List<Widget> _items = [];

  _RssListPageState({@required this.title, @required this.url}) {
    convertItemFromXML();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("RSS リーダー"),
      ),
      body: Center(
        child: ListView(
          padding: EdgeInsets.all(10.0),
          children: ListTile.divideTiles(
              color: Colors.black,
              context: context,
              tiles: _items
          ).toList(),
        ),
      ),
    );
  }

  void convertItemFromXML() async {
    List<Widget> list = [];
    Response res = await get(_rssUrl);
    var atomFeed = new AtomFeed.parse(res.body);
    for (AtomItem item in atomFeed.items) {
      list.add(ListTile(
        contentPadding: EdgeInsets.all(10.0),
        title: Text(
          item.title,
        ),
        subtitle: convertText(item.updated),
        onTap: () {
          Navigator.push(
              context,
              MaterialPageRoute(
                  builder: (_) => ItemDetailPage(
                        item: item,
                      )));
        },
      ));
    }
    setState(() {
      _items = list;
    });
  }

  Widget convertText(String published) {
    var formatter = DateFormat('yyyy年MM月dd日');
    final date = DateTime.parse(published);
    var formatted = formatter.format(date);
    return Text(formatted);
  }
}

これをビルドすると次のように画面が表示されます。

f:id:qed805:20200223160003p:plain
日付を変換

これでよりRSSアプリとして使えるようになりました。 あとはより細かいレイアウト調整だったり、画像を表示させられるといった工夫ができますが ひとまずRSSの基本としてはOKだと思います。

今回は区切り線と日付の扱いについて学びました。