项目作者: takusan23

项目描述 :
Jetpack Compose Icon List App
高级语言: Kotlin
项目地址: git://github.com/takusan23/ComposeIconShop.git
创建时间: 2021-01-14T18:30:57Z
项目社区:https://github.com/takusan23/ComposeIconShop

开源协议:

下载


ComposeIconShop

Jetpack Composeのアイコンを見るアプリ
アウトラインとかツートーンとか






仕組み

マテリアルアイコンのソースコードからアイコン一覧みたいなやつを見つけてきたので
これを使ってアイコン一覧テキストをJSON配列に変換します。これはNode.jsでやってる(download/src/index.js)

生成したJSONファイルをAndroidのassetsに配置します。

あとはJSONファイルを解析し、リフレクションを使ってアイコンを呼び出しています。

実行方法

必要なもの

  • Android アプリ開発環境
    • Android StudioはCanary版を利用してください。
    • Android Studio Arctic Fox | 2020.3.1 Canary 6
  • Node.js
    • アプリの実行には使いませんが、アイコンの名前を取得する際に利用します
    • まあ無くても動く

アイコンデータ取得

download内にNode.jsで実行できるプログラムが入っています。
プログラムを実行すると、Androidのsrc/main/assets/icon.jsonが更新されます。

  1. $ cd download
  2. $ npm run dev

トラブルシューティング

  • Unresolved reference ~
    • あんのに無いって言われる場合
    • Build > Clean Project を実行
    • 名前が悪い?
  • Scanning files to indexが進む気配すらない
    • .ideaフォルダを消して再度起動
  • 'padding(Dp): Modifier' is only available since Kotlin 1.4.30 and cannot be used in Kotlin 1.4
    • エラーに見えるけど実行できる。
    • 設定を開いて、Languages & Frameworksへ進みKotlinを押して、Update ChannelEarly Access Preview 1.4.xにしてInstallを押せばいいらしい。

技術的な話

画面遷移

ViewModelに置いたLiveDataを利用して画面遷移をしています。どうやるのが正解なのかは知らない

とりあえずデータクラスを用意して

  1. /**
  2. * 画面遷移で使うデータクラス
  3. *
  4. * @param screenName 遷移先画面の名前
  5. * */
  6. open class NavigationData(val screenName: String)
  7. /**
  8. * アイコン詳細画面へ切り替える際に利用するデータクラス
  9. *
  10. * @param iconName アイコンの名前。
  11. * @param screenName 遷移先画面の名前
  12. * */
  13. class IconDetailNavigationData(screenName: String, val iconName: String) :
  14. NavigationData(screenName)

あとはデータクラスをLiveDataへ

  1. /**
  2. * GoTo家キャンペーン
  3. *
  4. * [screenLiveData]へ[NavigationNames.HOME]を送信します
  5. * */
  6. fun gotoHome() {
  7. screenLiveData.postValue(NavigationData(NavigationNames.HOME))
  8. }

Jetpack Compose側はこうなってる
画面もFragmentではなくJetpack Composeで作成しています。

  1. override fun onCreate(savedInstanceState: Bundle?) {
  2. super.onCreate(savedInstanceState)
  3. // Jetpack Composeでレイアウト作成
  4. setContent {
  5. // 画面遷移
  6. val screenLiveData = viewModel.screenLiveData.observeAsState()
  7. when (screenLiveData.value?.screenName) {
  8. NavigationNames.HOME -> HomeScreen(viewModel = viewModel,iconSearch = searchWord.value,iconType = iconType.value)
  9. NavigationNames.DETAIL -> DetailScreen(iconName = (screenLiveData.value!! as IconDetailNavigationData).iconName)
  10. }
  11. }
  12. }

アイコン取得のためにリフレクション

アイコン一覧の配列等は(多分)ない。

ちなみに本家はPythonでアイコン一覧を取得している模様。本家README参照( https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/material/material/icons/README.md
ソースコードを見に行けばアイコン一覧が見ようと思えば見れる( https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/material/material/icons/generator/raw-icons/filled/
ただし、Kotlinファイルはライブラリ生成時に生成されるらしく?見てもない。

まず、アイコンを返す関数があるクラスを取得するために、クラスの名前からクラスを取得するClass.forName()を利用します。

  • filledなところはアイコンの種類。アウトラインなアイコンが欲しい場合はoutlinedを代わりに書く
  • AndroidKtはアイコン名。アイコン名+Ktを付ける。
  1. val iconClass = Class.forName("androidx.compose.material.icons.filled.AndroidKt")

その次に、Staticなアイコンを返すメソッドがあるので取得します。
先ほど用意したクラスはインスタンス化しなくていいはずです。Staticなメソッドを呼ぶだけなので

メソッド名は get+アイコン名 だと思います。第二引数は戻り値の型。アウトラインを取得するようにした場合はIcons.Outlined::class.javaになると思う

  1. val getIconFunction = iconClass.getMethod("getAndroid", Icons.Filled::class.java)

最後に取得したメソッドを呼びます。

  1. val icon = getIconFunction.invoke(null, Icons.Filled::class.java) as ImageVector

あとはこれをIconに入れてあげれば完成

  1. Icon(imageVector = icon)

詳しくは各Iconのクラスを見てKotlinをJavaに変換して見てみてください。パスがそのまま書いてある

仕様

  • 一部のアイコンが欠けている
    • Jetpack Composeのアイコン一覧どっかにねえかな
    • JSON生成でミスってんのかわからん