Flutterのクイックアクション:10分でインパクト大

Flutterのクイックアクション:10分でインパクト大

私たちはしばしば「大きな機能」を磨くのに不相応な時間を費やします。 そして、時に片隅に隠れたマイクロアクションが製品において… タイミング > 複雑さ を思い出させてくれます。

今日は Quick Actions について話します:アプリのアイコンを 長押し したときに表示されるメニューです。 Flutter では、パッケージ quick_actions を使えば、それらを素早く組み込み、ルーティング(GoRouter)に接続できます。小さな悪魔的アーキテクチャを作る必要はありません。(Dart packages)

1) なぜ効果的か

Quick Actions には強力な利点があります:すでに負荷のかかった導線にもう一つ画面を追加することなく、"高価値"なアクションを追加できる点です。

最適な使い方:ユーザーが既に意思を持っている瞬間に 摩擦を減らす こと。 典型例:サブスクリプションを管理したい、購入を復元したい、サポートに連絡したい……あるいは「ただ」主要機能にアクセスしたい、など。

2) Quick Action(iOS)/ App Shortcut(Android)とは?

iOS では、Apple は ホームスクリーンのクイックアクション と呼んでいます:ホーム画面からアプリのアクションへのショートカットです。 Android では、同等の概念は App Shortcuts(static / dynamic / pinned)に基づいています。

Flutter 側では、quick_actions が 2 つの要素を提供します:

  • initialize():ショートカット経由でアプリが起動されたときに呼ばれるコールバック。
  • setShortcutItems():アクションのリスト(type、label、icon...)。

3) よく見る例

Apple はユーザー視点でわかりやすい例を示しています:

  • カメラ → セルフィー
  • マップ → 現在地を送信
  • メモ → 新しいメモ

パターンはシンプルです:それらは「機能」ではなく、頻繁に発生する意図です。 そしてそれが自分のアクションを選ぶ助けになります:Quick Action はユーザーの時間を節約するものでなければなりません。

4) Quick Actions のアイデア

良いフィルター:ユーザーがクリックしたとき、それは本当に役に立つか? もしそうなら、ついでに小さなビジネス的施策を入れても構いません。

サブスクリプション / 収益に向けたアイデア

  • "Offre spéciale -30%" → あらかじめ選択されたプロモーション付きでペイウォールを開く。
  • "Passer en Premium" → アップグレード画面を開く(シンプルで明確、ダークパターンは無し)。
  • "Restaurer mes achats" → 端末を変更した iOS/Android ユーザーを救い(サポートチケットを減らす)。

リテンション / 信頼向けのアイデア

  • "Support / Signaler un bug" → 短いフォームを開く(チャットがあればチャットを開く)。
  • "FAQ / Aide" → 上位5つの質問を載せたヘルプページを開く。
  • "Donner mon avis" → 内部のフィードバックスクリーンを開く(その後にストアへ誘導してもよい)。

Android のドキュメントは 抑制 を推奨しています:API は最大15個のショートカット(static + dynamic)をサポートしますが、可読性向上のために 4 個 を公開することを推奨しています。

5) Flutter の実装(GoRouter を使用)

目的:そのまま コピペ で動くこと、そしてきれいなルーティング。 長押しからアクセスできる「サブスクリプションオファー」の例を作ります。

依存関係

dependencies:
  quick_actions: ^1.1.0 # (check la version au moment d'écrire)
  go_router: ^14.0.0

quick_actions はアクションを宣言して監視するためのものです。 go_router は画面へ(必要ならパラメータ付きで)適切にルーティングするためのものです。

ルーター (GoRouter)

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

final GoRouter router = GoRouter(
  routes: <RouteBase>[
    GoRoute(
      path: '/',
      builder: (context, state) => const HomeScreen(),
    ),
    GoRoute(
      path: '/paywall',
      builder: (context, state) {
        final offer = state.uri.queryParameters['offer']; // ex: discount30
        final src = state.uri.queryParameters['src'];     // ex: quick_action
        return PaywallScreen(offer: offer, source: src);
      },
    ),
    GoRoute(
      path: '/support',
      builder: (context, state) => const SupportScreen(),
    ),
  ],
);

GoRouter はルート、クエリパラメータ、ディープリンクなどを管理します。

Quick Actions とナビゲーションの接続

import 'package:flutter/material.dart';
import 'package:quick_actions/quick_actions.dart';

class AppBootstrap extends StatefulWidget {
  const AppBootstrap({super.key});

  @override
  State<AppBootstrap> createState() => _AppBootstrapState();
}

class _AppBootstrapState extends State<AppBootstrap> {
  final QuickActions _quickActions = const QuickActions();

  @override
  void initState() {
    super.initState();

    // 1) Écoute des actions (à init le plus tôt possible)
    _quickActions.initialize((String shortcutType) {
      // Évite de naviguer "au mauvais moment" (app pas encore rendue)
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _handleQuickAction(shortcutType);
      });
    });

    // 2) Déclaration des actions
    _quickActions.setShortcutItems(const <ShortcutItem>[
      ShortcutItem(
        type: 'offer_discount',
        localizedTitle: 'Offre -30%',
        icon: 'ic_discount', // ressource native (iOS xcassets / Android drawable)
      ),
      ShortcutItem(
        type: 'support',
        localizedTitle: 'Support',
        icon: 'ic_support',
      ),
    ]);
  }

  void _handleQuickAction(String type) {
    switch (type) {
      case 'offer_discount':
        router.go('/paywall?offer=discount30&src=quick_action');
        break;
      case 'support':
        router.go('/support?src=quick_action');
        break;
      default:
        // no-op
        break;
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: router,
    );
  }
}

パッケージは早めの初期化を推奨しており、次の点に注意しています:

  • type は一意である必要があります。
  • iconネイティブリソースの名前(iOS の xcassets / Android の drawable)である必要があります。

公式の最小例を見たい場合、パッケージの例はまさにこの initialize()setShortcutItems() の組み合わせを示しています。

6) よくある落とし穴(と一晩費やさない方法)

Android:SDK 16+ でコンパイルはするが…

プラグインは Android SDK 16+ 上で動作しますが、ショートカットは Android 7.1(SDK 25)未満では動作しません(no-op)。 したがって:重要な導線をこれに依存させず、フォールバック(アプリ内のボタン、プロフィールメニューなど)を用意してください。

リリースで消えるアイコン

Android の drawable が Dart 内で「だけ」参照されている場合、shrinker(縮小ツール)がそれらを削除してしまうことがあります。 パッケージの README にもその旨が記載されており、これらのリソースを明示的に保持するための Android のドキュメントへのリンクが示されています。

早すぎるナビゲーション(コールドスタート)

アプリが Quick Action によって起動された場合、コールバックが非常に早く届くことがあります。 例の addPostFrameCallback はルーターが準備できる前にナビゲートしてしまうケースを回避します。

7) インパクトの測定(さもないと単に「良いね」だけになる)

もし Quick Action「Offre -30%」が役立っているか知りたいなら、シンプルに計測してください:

  • quick_action_triggered (type)
  • paywall_viewed (source=quick_action, offer=discount30)
  • purchase_completed (source=quick_action)

その後、比較します:

  • ペイウォールのコンバージョン率(src=quick_action
  • Quick Action の使用率(週ごと)
  • サポートへの影響(ショートカット「Support」を追加した場合)

8) チェックリストと結論

覚えておくべきルールが一つあるとすれば:最大4つのアクション、そして各アクションは一文で正当化できること。 ラベルは短く、アクションは直接「仕事をこなす」ページにつながるべきです。

Checklist :

  • 最大2〜4 個の Quick Actions
  • ネイティブアイコン OK (iOS + Android)
  • ナビゲーションは安全に(post-frame)
  • 最小限のトラッキング(3 イベント)
  • ビジネス目的のアクションは価値がある場合のみ(そうでなければ目立つ)

参考リンク

タグ

  • フラッター

  • ios

  • アンドロイド

  • クイック-アクション

  • go-ルーター

  • flutter-パッケージ

この記事は

コメント

読み込み中...

Flutterのクイックアクション:10分でインパクト大 | DEMILY Clément