1日の予定リストを表示するホーム画面ウィジェット

timescheduleWidget – ホーム画面に「今日1日」が並ぶタイムテーブルウィジェット

スマホを開いた瞬間に、今日1日の予定が時系列で見えるホーム画面ウィジェットです。 カレンダーアプリを開かなくても、「この後何をするのか」を一目で思い出せるようにするための 小さなプロジェクトとして開発しました。

作品の説明

timescheduleWidget は、今日1日の予定だけ に集中したウィジェットです。 0:00〜24:00 のあいだに登録された予定を、開始時刻順に並べて表示します。 予定のタイトル・時間帯・カテゴリカラーなどを表示し、 「いま何をしていて、次に何が来るのか」を常に見える状態にします。

データソースは、内部の Room データベースやスプレッドシート同期アプリと共有する前提で設計しており、 ウィジェット側は AppWidgetProviderRemoteViewsService を用いて ListView 形式で 1 日分の予定を描画します。

  • ① 今日(ローカル日付)の予定だけをクエリして取得
  • ② 時刻順にソートし、ウィジェット用リストに変換
  • ③ RemoteViewsService から ListView に 1 行ずつバインド
  • ④ タップすると対応するアプリ(詳細画面や編集画面)が起動
  • ⑤ 0時・朝起動・手動更新など、複数のトリガで自動更新

システム概要

timescheduleWidget のアーキテクチャ構成図

ホーム画面ウィジェット(AppWidgetProvider)が更新要求を受け取り、 RemoteViewsService 経由で 1 日分の予定リストを取得します。 データは Repository を通して Room や他アプリの DB から読み出す構造にしておき、 後から Google スプレッドシートや LINE WORKS など別ソースに 差し替えられるようにしました。

技術スタック

  • Android / Widget: AppWidgetProvider, RemoteViews, RemoteViewsService, PendingIntent
  • Data: Room / Repository パターン(予定テーブル)
  • Update: AlarmManager / WorkManager / 手動更新ボタン

主要コンポーネント

  • TimeScheduleWidgetProvider: ウィジェットのエントリポイント。onUpdate で RemoteViews を構築し、ListView にアダプタ(RemoteViewsService)を設定。
  • ScheduleRemoteViewsService: 1日分の予定アイテムを供給するサービス。 RemoteViewsFactory 内でクエリとソートを実行。
  • ScheduleRepository: 日付を受け取り、該当日の予定リストを返す抽象化レイヤ。
  • ScheduleEntity: 開始時刻・終了時刻・タイトル・カテゴリ・メモなどを持つ予定レコード。

技術解説

APPWIDGET

AppWidgetProvider × RemoteViewsService で「1日リスト」を描画

timescheduleWidget は、コレクションウィジェットの定番パターンである AppWidgetProvider + RemoteViewsService を採用しています。 ListView に対して setRemoteAdapter() を設定し、 1行ずつ RemoteViews を返すことで、軽量なリスト表示を実現しています。

非同期での流れイメージ:
onUpdate() → setRemoteAdapter() →
ScheduleRemoteViewsService.onGetViewFactory() →
RemoteViewsFactory.onCreate() / onDataSetChanged()
DAY QUERY

「今日」の 0:00〜24:00 に絞った予定クエリ

予定のクエリは「今日」というコンテキストに特化させています。 ローカルタイムゾーンで 0:00〜24:00 の範囲を求め、 その間に開始する予定だけを取得・ソートして タイムテーブルとして表示します。

例:
// 疑似コード
val start = today.atStartOfDay()
val end = start.plusDays(1)
dao.eventsBetween(start, end).sortedBy { it.startAt }
INTENT

ウィジェットから詳細画面や編集画面へジャンプ

各予定行には setOnClickFillInIntent を設定し、 予定IDなどを詰めた Intent を Activity 側で受け取れるようにしました。 これにより、「ウィジェットから直接予定を開く」体験を実現できます。

UPDATE

0時・手動・スケジュール変更時に自動更新

更新タイミングは、 ・0時になったとき ・端末起動時(BOOT_COMPLETED) ・アプリ側で予定が変更されたとき ・ウィジェット右上の更新ボタン の4パターンを想定しています。 必要なときだけ notifyAppWidgetViewDataChanged を呼ぶことで 無駄な更新を避けています。

実験・結果・課題

ウィジェットを1週間使ってみた所感

実際に自分の端末のホーム画面に配置して 1 週間運用してみました。 朝起きた瞬間や授業の合間に次の予定を確認できるため、 カレンダーアプリを開く回数がかなり減りました。

ホーム画面に配置された timescheduleWidget
(a) ホーム画面に配置した様子
1日の予定リストが並んだウィジェット
(b) 予定リスト部分の拡大

現在の課題

現時点では、 ・「いま進行中の予定」がどれかが分かりづらい ・長い予定タイトルが省略されてしまう ・複数日をまたぐ予定の扱い などに課題があります。 また、縦幅が限られている端末では、予定数が多いときに スクロールしづらい問題もあります。

進行中予定の強調表示は未実装 長文タイトルの表示方法を検討中

動画リンク

ウィジェットの追加、予定編集アプリとの連携、 0時を跨いだときの自動更新の様子を撮影したデモ動画です。

timescheduleWidget で 1 日の予定を確認するデモ

まだできていない部分と今後

「1日タイムテーブル」から「人生のダッシュボード」へ

timescheduleWidget は、まず 1 日の予定だけに絞っていますが、 将来的には Rootine や EEG 指数、ポイントシステムと連携させて、 ホーム画面に「今日やるべきこと」と「自分の状態」が 一緒に映るダッシュボードにしていきたいと考えています。

  • 短期: 進行中の予定のハイライト表示・残り時間の表示。
  • 中期: カテゴリごとの色分け・アイコン表示、 重要度に応じた強調表示。
  • 長期: Rootine ウィジェットや EEG ウィジェットと統合し、 1 画面で「タスク × 健康 × 学習」の状態を把握できるようにする。

これからの改善点と開発計画

表示内容のリッチ化・データソース拡張・他ウィジェットとの統合の 3 ステップで進めていきます。

  • Display: 進行中予定の強調、残り時間のバッジ。
  • Source: Google スプレッドシート / LINE WORKS との連携。
  • Integration: RootineWidget / EEGWidget と連携した マルチウィジェット構成。
17
18
19
20
21
22
23
24
25
26
27
28
29
30
進行中予定のハイライト表示
カテゴリカラー・アイコン付与
他ウィジェットとの統合設計

このプロジェクトを通して

感じていること

timescheduleWidget を作る中で、「ホーム画面に何を置くか」が その日の過ごし方をかなり左右することを実感しました。 自分で組んだタイムテーブルが、常に視界の端にいるだけで 行動の迷いが少し減ります。

実装面では、AppWidget の制約や RemoteViews の扱いに慣れる良い練習になりました。 ここで得た知見は、今後作る RootineWidget や EEGWidget など、 他のホーム画面ウィジェットにもそのまま活かしていくつもりです。

今の自分へのメモ

  • ・情報量を増やしすぎない。「今日1日」に絞る方針を忘れない。
  • ・ウィジェット更新の仕組みは、今後の他プロジェクトでも再利用できるように整理しておく。

リファレンス & リンク

リファレンス

  • Android Developers – App Widgets
  • Android Developers – Collection widgets(RemoteViewsService)

リンク