スマホを開いた瞬間に、今日1日の予定が時系列で見えるホーム画面ウィジェットです。 カレンダーアプリを開かなくても、「この後何をするのか」を一目で思い出せるようにするための 小さなプロジェクトとして開発しました。
timescheduleWidget は、今日1日の予定だけ に集中したウィジェットです。 0:00〜24:00 のあいだに登録された予定を、開始時刻順に並べて表示します。 予定のタイトル・時間帯・カテゴリカラーなどを表示し、 「いま何をしていて、次に何が来るのか」を常に見える状態にします。
データソースは、内部の Room データベースやスプレッドシート同期アプリと共有する前提で設計しており、
ウィジェット側は AppWidgetProvider と RemoteViewsService を用いて
ListView 形式で 1 日分の予定を描画します。
ホーム画面ウィジェット(AppWidgetProvider)が更新要求を受け取り、 RemoteViewsService 経由で 1 日分の予定リストを取得します。 データは Repository を通して Room や他アプリの DB から読み出す構造にしておき、 後から Google スプレッドシートや LINE WORKS など別ソースに 差し替えられるようにしました。
onUpdate で
RemoteViews を構築し、ListView にアダプタ(RemoteViewsService)を設定。RemoteViewsFactory 内でクエリとソートを実行。
timescheduleWidget は、コレクションウィジェットの定番パターンである
AppWidgetProvider + RemoteViewsService を採用しています。
ListView に対して setRemoteAdapter() を設定し、
1行ずつ RemoteViews を返すことで、軽量なリスト表示を実現しています。
onUpdate() → setRemoteAdapter() →
ScheduleRemoteViewsService.onGetViewFactory() →
RemoteViewsFactory.onCreate() / onDataSetChanged()
予定のクエリは「今日」というコンテキストに特化させています。 ローカルタイムゾーンで 0:00〜24:00 の範囲を求め、 その間に開始する予定だけを取得・ソートして タイムテーブルとして表示します。
// 疑似コード
val start = today.atStartOfDay()
val end = start.plusDays(1)
dao.eventsBetween(start, end).sortedBy { it.startAt }
各予定行には setOnClickFillInIntent を設定し、
予定IDなどを詰めた Intent を Activity 側で受け取れるようにしました。
これにより、「ウィジェットから直接予定を開く」体験を実現できます。
更新タイミングは、
・0時になったとき
・端末起動時(BOOT_COMPLETED)
・アプリ側で予定が変更されたとき
・ウィジェット右上の更新ボタン
の4パターンを想定しています。
必要なときだけ notifyAppWidgetViewDataChanged を呼ぶことで
無駄な更新を避けています。
実際に自分の端末のホーム画面に配置して 1 週間運用してみました。 朝起きた瞬間や授業の合間に次の予定を確認できるため、 カレンダーアプリを開く回数がかなり減りました。
現時点では、 ・「いま進行中の予定」がどれかが分かりづらい ・長い予定タイトルが省略されてしまう ・複数日をまたぐ予定の扱い などに課題があります。 また、縦幅が限られている端末では、予定数が多いときに スクロールしづらい問題もあります。
ウィジェットの追加、予定編集アプリとの連携、 0時を跨いだときの自動更新の様子を撮影したデモ動画です。
timescheduleWidget は、まず 1 日の予定だけに絞っていますが、 将来的には Rootine や EEG 指数、ポイントシステムと連携させて、 ホーム画面に「今日やるべきこと」と「自分の状態」が 一緒に映るダッシュボードにしていきたいと考えています。
表示内容のリッチ化・データソース拡張・他ウィジェットとの統合の 3 ステップで進めていきます。
timescheduleWidget を作る中で、「ホーム画面に何を置くか」が その日の過ごし方をかなり左右することを実感しました。 自分で組んだタイムテーブルが、常に視界の端にいるだけで 行動の迷いが少し減ります。
実装面では、AppWidget の制約や RemoteViews の扱いに慣れる良い練習になりました。 ここで得た知見は、今後作る RootineWidget や EEGWidget など、 他のホーム画面ウィジェットにもそのまま活かしていくつもりです。