【Flutter for Desktop】Mac版で色んなサンプルを試してみた

【Flutter for Desktop】Mac版で色んなサンプルを試してみた_アイキャッチ 技術メモ

以下の機能を実装して遊んでみました。参考になれば幸いです。

紹介するサンプル
  • ファイル選択ダイアログ(file_selector)
  • インターネット上の画像を表示
  • メニューバーを動的に追加

file_selector(ファイル選択ダイアログ)

よくあるやつです。以下の2点さえできていれば簡単です。

  • file_selector_macosもpubspec.yamlに書く
  • entitlementsファイルを編集して、アプリにファイル読み取りの権限を提供
file_selector
ファイル選択ダイアログ

プラグインを追加

以下の2つのプラグインをpubspec.yamlに記述しpub getします。

dependencies:
  file_selector: ^0.8.2
  file_selector_macos: ^0.0.4

ファイルの読み取り権限を与える

macOSビルドでは、デフォルトで、サンドボックス化されるため、明示的に権限を与える必要があります。(参考:https://flutter.dev/desktop#entitlements-and-the-app-sandbox

今回は、ファイルの読み取り権限が必要なので、『DebugProfile.entitlements』と『ReleaseProfile.entitlements』に以下を記述します。

<key>com.apple.security.files.user-selected.read-only</key>
<true/>

※それぞれのファイルは、プロジェクトルート>macoc>Runner配下にあります。

コードを書いていく

※StatefullWidgetで書いています。

アイコンボタンをを押したときに、typeGroupを設定して、openFile()するだけでファイル選択ダイアログを出すことができます。

戻り値はXFile型で受け取れます。

IconButton(
    icon: Icon(Icons.attach_file),
    onPressed: () async {
        final typeGroup = XTypeGroup(label: 'images', extensions: ['jpg', 'png']);
        xFile = await openFile(acceptedTypeGroups: [typeGroup]);
        setState(() {});
    },
),

次に受け取ったXFileから、画像を表示してみます。

xFile == null ? Container() : Container(
    height: 150,
    child: Image.file(
        File(xFile.path),
        fit: BoxFit.fitHeight,
    ),
),

これだけで、ファイル選択ダイアログで選択した画像を表示させることができました。

インターネット上の画像を表示してみる

ネットワーク要求の権限を提供してあげないと、左の画像のようにパーミッションエラーとなってしまいます。

コードを書いていく…だけじゃやっぱりだめ

まず、以下のようにインターネット上の画像を表示するコードを書いて、実行してみます。

class _GetNetworkImageState extends State<GetNetworkImage> {
  final imageSrcPath = 'https://2.bp.blogspot.com/-InDDi4UwPGs/XAY5qpGJnPI/AAAAAAABQdg/q2BHwOIcoOoJHgfHUS41hwvKUZ3vkj7XQCLcBGAs/s800/cat12_moyou_mike.png';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('get_network_image'),
      ),
      body: Center(
        child: Image.network(imageSrcPath),
      ),
    );
  }
}

一見、普通に表示できそうですが、実行してみると、パーミッションエラーとなります。

ネットワーク要求を行う権限を与える

今回は、ネットワーク要求の権限が必要なので、『DebugProfile.entitlements』と『ReleaseProfile.entitlements』に以下を記述します。

<key>com.apple.security.network.client</key>
<true/>

もう一度ビルドしてみると、正しく画像が表示されました。

※Dartのコード以外の部分なので、ホットリロード、ホットリスタートは機能しません。

メニューバーを編集する

メニューバーはモバイルアプリに無い機能ですが、プラグインを使用すれば簡単に実装することができました。

menubarのサンプル
メニューバーのサンプル

プラグインを追加する

記事執筆時点で、pub.devに公開されていなかったので、以下のように記述してプラグインを導入します。

  menubar:
    git:
      url: https://github.com/google/flutter-desktop-embedding.git
      path: plugins/menubar

コードを書いていく

テキストボタンを押下すると、動的にメニューバーに項目を追加するようなものを作っていきます。

メニューバーと言われるとちょっと難しそうに聞こえますが、意外とあっさり書くことができました。

class _MenuBarState extends State<MenuBar> {
  var menuLabel = '';
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('menu_bar'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Text(menuLabel),
            TextButton(
              onPressed: () => addMenuBar(),
                child: Text('メニューバーを追加'),
            )
          ],
        ),
      ),
    );
  }

  Future<void> addMenuBar() async {
    // メニューアイテムを作成(メニューバーをクリックしたときに出てくる中身の項目)
    var menuItems = <MenuItem>[];
    final greetings = ['おはようございます', 'こんにちは', 'こんばんは',];

    for (final greetingString in greetings) {
      menuItems.add(
        MenuItem(
            label: greetingString,
            onClicked: () => {
              setState(() {
                menuLabel = greetingString;
              }),
            }
        ),
      );
    }

    // メニューアイテムをサブメニューとして作成
    final subMenu = Submenu(label: 'あいさつ', children: menuItems);

    // メニューバーにサブメニューをセットする
    await setApplicationMenu([subMenu]);
  }
}

全ソースコードはこちらに格納されています。

コメント

  1. […] […]

タイトルとURLをコピーしました