🖥️

ゆめみ社のAndroidインターンに参加してきたので学んだことをまとめておく(Compose for Desktop編)

2022/09/07に公開

ゆめみ社の Android インターンに参加しました。
なかなかにありがたい経験をさせてもらえたので、アウトプットします 👍

  • 基本的には課題を進めていく 🚶
  • 課題は AndroidView で開発する前提になっていたが、Jetpack Compose の方が得意という旨を伝えると、Compose を使って UI を作っていくことに。柔軟に対応していただくことができた。感謝 😊

Compose for Desktop

参考:
公式サイト
https://www.jetbrains.com/ja-jp/lp/compose-mpp/
公式の GetStart
https://github.com/JetBrains/compose-jb/tree/master/tutorials/Getting_Started

Compose でデスクトップアプリがつくれる....だと!
社内の勉強会に参加させてもらった時に面白そうだったので実際に触ってみました!

プロジェクトを作る

ドキュメントにもろ載ってるので割愛(書くのがめんどい)

https://github.com/JetBrains/compose-jb/tree/master/tutorials/Getting_Started

コードを見てみる

メインのコード
fun main() = application {
    Window(
        onCloseRequest = ::exitApplication,
        title = "Compose for Desktop",
        state = rememberWindowState(width = 300.dp, height = 300.dp)
    ) {
        val count = remember { mutableStateOf(0) }
        MaterialTheme {
            Column(Modifier.fillMaxSize(), Arrangement.spacedBy(5.dp)) {
                Button(modifier = Modifier.align(Alignment.CenterHorizontally),
                    onClick = {
                        count.value++
                    }) {
                    Text(if (count.value == 0) "Hello World" else "Clicked ${count.value}!")
                }
                Button(modifier = Modifier.align(Alignment.CenterHorizontally),
                    onClick = {
                        count.value = 0
                    }) {
                    Text("Reset")
                }
            }
        }
    }
}

applicationの中に Window があって、それらにデスクトップ特有の設定を書いてく感じ。

Window の中はもういつもの Compose。Compose ファンとしてはわかりやすい事この上なし。

できること

README に載ってました

https://github.com/JetBrains/compose-jb#compose-for-desktop

Getting started // 先述
Image and icon manipulations
Mouse events and hover
Scrolling and scrollbars
Tooltips
Top level windows management // 後述
Menu, tray, notifications // 後述
Keyboard support
Tab focus navigation
Swing interoperability // 後述
Navigation // 後述
Accessibility
Building native distribution
Signing and notarization

ざっと訳すと

  • 入門
  • 画像とアイコン(manipulations ってなんだ?)
  • マウスイベントとホバー
  • スクロールとスクロールバー
  • ツールチップ(マウスホバーすると説明が出るやつ)
  • ⭐️Window の管理
  • ⭐️ メニュートレイと通知
  • キーボードサポート
  • タブナビゲーション
  • ⭐️Swing との統合
  • ⭐️ ナビゲーション(画面遷移)
  • アクセシビリティ
  • ネイティブ ディストリビューションとローカル実行
  • アプリの署名とか諸々

Window の管理

https://github.com/JetBrains/compose-jb/tree/master/tutorials/Window_API_new

ちょっと気になったものをピックアップしていきます。

基本的な引数

Windowの引数
Window(onCloseRequest = ::exitApplication, title = "$fileName - Editor") {
  Button(onClick = { fileName = "note.txt" }) {
    Text("Save")
  }
}

onCloseRequest = ::exitApplicationと書くことでウィンドを閉じることでアプリも終了させるといった動きになります。

ウィンドウとアプリの違い

アプリの中にいくつかウィンドウがあります。例えば Excel を 10 個開くとアプリは 1 つ・ウィンドウは 10 こ開いたことになります。

Window が 1 つしかないアプリ

Window が 1 つしかないアプリのために以下のようなショートハンドが用意されています。

fun main() = singleWindowApplication {
    // Content
}

Window サイズを子要素に合わせる

Window(
  onCloseRequest = ::exitApplication,
  state = rememberWindowState(width = Dp.Unspecified, height = Dp.Unspecified),
  title = "Adaptive",
  resizable = false
) { ... }

ダイアログ

ダイアログも宣言的にかけます。


var isDialogOpen by remember { mutableStateOf(false) }

if (isDialogOpen) {
  Dialog(
    onCloseRequest = { isDialogOpen = false },
    state = rememberDialogState(position = WindowPosition(Alignment.Center))
  ) {
    // Dialog's content
  }
}

// ダイアログを表示したいところ
isDialogOpen = true

// ダイアログを消したいところ
isDialogOpen = true

メニュートレイと通知

https://github.com/JetBrains/compose-jb/tree/master/tutorials/Tray_Notifications_MenuBar_new

トレイとは Mac では以下のように画面右上についている、Windows では右下についているアイコンたちのことです。

トレイ

val trayState = rememberTrayState()

Tray(
  state = trayState,
  icon = TrayIcon,
  menu = {
    Item(
      "メニューアイテム1",
      onClick = {
        // メニューアイテムが押された時にやりたいこと
      }
    )
    Item(
      "メニューアイテム2",
      onClick = {
        // メニューアイテムが押された時にやりたいこと
      }
    )
    // ...
  }
)

通知

val notification = rememberNotification("Notification", "Message from MyApp!")

trayState.sendNotification(notification)

なぜか通知を送るメソッドが trayState についてるけどトレイがないと通知遅れないんかな...

Swing との統合

100 万年ぶりにその名を聞いた Swing。Compose for Desktop は内部で Swing を使っているらしいので、Swing のあれこれが使えます(あれ、JDK 標準ライブラリから外れるとか聞いていたけど...)

Compose for Desktop にない機能は Swing の機能を使って実装するタイミングもしばしば出てくるかもしれないそうです。(せっかく宣言的 UI でかけるのに Swing 使ったら意味ないやん)

調べた感じだと FileChooser がまだ対応していないらしく Swing の JFileChooser 使ってどうにかしてる記事を見つけてそれでいいんか?って思ったりしました。

ナビゲーション(画面遷移)

ナビゲーションに関してはAndroid で使うナビゲーションが今現在使えない模様です。(その実装内に Android 固有の処理が含まれているため)そこでDecomposeを使ったら?と提案されています。

自分もあまりキャッチアップできていないのでもう少し見てみたいところ...

https://github.com/JetBrains/compose-jb/tree/master/tutorials/Navigation

インターンアウトプットシリーズ一覧

Discussion