Glanceであそぼ

# はじめに
こんにちは。どすこいです。
今回は先日リリースされた、Glance 1.0.0-alpha(ComposeでAppWidgetを作れるやつ)で遊んでいきたいと思います。

Glanceの詳細に関してはこちらの記事をご覧ください。

https://blog.kyash.co/entry/2021/11/19/125319

# 環境
Kotlin 1.6
AGP 7.1.0-beta05

# 1.準備
まずはbuild.gradle(app)に依存関係を書いていきます。

https://developer.android.com/jetpack/androidx/releases/glance

```Groovy:build.gradle(app)
dependencies {
    implementation "androidx.glance:glance:1.0.0-alpha01"
   implementation "androidx.glance:glance-appwidget:1.0.0-alpha01"
}

android {
    buildFeatures {
        compose true
    }

    composeOptions {
        kotlinCompilerExtensionVersion = "1.1.0-beta04"
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }
}
```

# 2.作ってみよう
まずGlanceに必要な要素は、

- GlanceAppWidgetReceiver
- GlanceAppWidget

です。上記の各クラスを継承したクラスを作りましょう

```kotlin
class GlanceAppWidgetSample : GlanceAppWidget() {
    @Composable
    override fun Content() {
        
    }

}

class GlanceAppWidgetReceiverSample : GlanceAppWidgetReceiver() {

    override val glanceAppWidget: GlanceAppWidget
        get() = GlanceAppWidgetSample()
}
```

こんな感じ

次にmeta-dataを用意します。これはWidgetの設定などをまとめたファイルです。

```xml:xml/glance_appwidget_sample_meta_data.xml
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:targetCellHeight="2"
    android:targetCellWidth="2"
    android:previewImage="@drawable/ic_launcher_background"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen"
    android:updatePeriodMillis="86400000"
    android:initialLayout="@layout/glance_appwidget_sample" />
```

`targetCellWidth`と`targetCellHeight`はAndroid12以上でしか動かないので注意です。

次にGlanceAppWidgetSampleReceiverと上記のmeta-dataをAndroidManifest.xmlに登録していきます。

```xml:AndroidManifest.xml
<receiver 
    android:name=".GlanceAppWidgetReceiverSample"
    android:exported="false">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/glance_appwidget_sample_meta_data" />
</receiver>
```

これで準備は完了です。

さて先ほどのGlanceAppWidgetSampleクラスに怪しい記述がありましたね。

```kotlin
class GlanceAppWidgetSample : GlanceAppWidget() {
    @Composable
    override fun Content() {

    }
}
```

`@Composable`の記述がありますね。
つまりここにComposeの記述をしていけばいいわけです。

早速作っていきましょう。

最初はとてもシンプルにTextだけ

```kotlin
@Composable
override fun Content() {
    Text(text = "Glance")
}
```

![Screenshot_1640887443.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411927/72269bf1-b5f3-234a-96a0-4b4fef7ff297.png)

なんの背景もなしにGlanceとだけ表示されましたね。

次に背景を設定していきます。

```kotlin
@Composable
override fun Content() {
    Box(
        modifier = GlanceModifier.fillMaxSize().background(Color.White),
        contentAlignment = Alignment.Center
    ) {
        Text(text = "Glance")
    }
}
```
![Screenshot_1640887638.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411927/91c7b794-5a0e-3b64-997c-7a14fec95021.png)

いい感じですね
Composeを経験した方ならオッと思うような記述があることに気づくと思います。

普段は`fillMaxSize`や`background`を設定する際は`Modifier`を使うと思うのですが、今回は`GlanceModifier`を用いています。
中のコードは読んでないのでただの推測ですが、ComposeをRemoteViewに変換する際に普段のModifierではうまくできないのでGlanceModifierを用意しているのかなと思ってます。
また今度ComposeをRemoteViewに変換するところは解説したいですね。

ちなみにimportを見ても

```kotlin
import androidx.glance.background
import androidx.glance.layout.Alignment
import androidx.glance.layout.Box
import androidx.glance.layout.fillMaxSize
import androidx.glance.text.Text
```

androidx.compose.uiに生えているBox等ではなく、androidx.glanceに生えているBoxなので、根本的にものが違うのでしょう。

# 3.遊んでみよう
次にリスト表示をしてみたいと思います。
従来のRemoteViewを使ったAppWidgetでリスト表示をするのはとても大変でした。
気になる方は下のリンクを覗いてみてください。

https://developer.android.com/guide/topics/appwidgets?hl=ja#collections

Composeでリスト表示はLazyColumnやLazyRowですね。
これらでリスト表示をしてみたいと思います。

```kotlin
private val pokemonList = listOf(
    "ピカチュウ",
    "カイリュー",
    "ヤドラン",
    "ピジョン",
    "コダック",
    "コラッタ",
    "ズバット",
    "ギャロップ",
    "サンダース",
    "メノクラゲ",
    "パウワウ",
    "カラカラ",
    "タマタマ",
    "ガラガラ",
    "フシギダネ"
)
@Composable
override fun Content() {
    Box(
        modifier = GlanceModifier.fillMaxSize().background(Color.White),
        contentAlignment = Alignment.Center
    ) {
        LazyColumn {
            items(pokemonList) {
                Text(text = it)
            }
        }
    }
}
```

![glance-lazy-column.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411927/3d064f19-0fdc-f380-0d56-31b8a0b0f175.gif)

とても簡単ですね

次はリストのどれかがタップされたらActivityを開くようにしましょう。
これも従来のやり方だとPendingIntentを発行して、それをViewに紐付けて...的なことをしなければいけませんでした。
少し面倒ですね。
Glanceではどう変わったのでしょうか。

```kotlin
@Composable
override fun Content() {
    Box(
        modifier = GlanceModifier.fillMaxSize().background(Color.White),
        contentAlignment = Alignment.Center
    ) {
        LazyColumn {
            items(pokemonList) {
                Text(
                    modifier = GlanceModifier.clickable(actionStartActivity<MainActivity>()),
                    text = it
                )
            }
        }
    }
}
```

![glance-action.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411927/f0e6cc41-972d-ac28-b021-c68bbbf9fb51.gif)

ちょっとクリックしたところはわかりにくいですが、実際はリストの要素をクリックしています。
これもとても簡単になりましたね。

# 4.まとめ
Glanceがリリースされ、AppWidgetが今までよりも簡単に、そしてより直感的に作ることが可能になりましたね。
皆さんもぜひGlanceで遊んでみてください。