『Android Jetpackプログラミング』Chapter2 最新バージョン対応(1.0.0-alpha03)

### はじめに

本稿は秀和システムより発売された[Android Jetpackプログラミング](https://www.shuwasystem.co.jp/book/9784798063218.html)に関する内容です。

『Android Jetpackプログラミング』のChapter2ではJetpackのComposeに関して扱っています。

書籍ではComposeのバージョンとして"0.1.0-dev13"が使用されていますが、アルファ版のためか頻繁に更新されているため、現在の最新環境では掲載されているコードのビルドが通らないことがあります。

今回は掲載コードのうち現在の環境でも動作するように必要な変更箇所についてまとめました。

※目的としてはビルドを通し、元コードと同じように動作をさせることとなります。変更後コードの詳細な解説等はありません。

### 実行環境

今回の動作検証に用いた環境です。

Android Studio  4.2 Canary 11

compose_version = '1.0.0-alpha03'



### stateのDeprecated

最新環境ではstate { ... }がDeprecatedとなっており、remember { mutableStateOf(...) }へ置き換える必要があります。

そのため全サンプルコードでstate{ ... }が使用されている箇所を変更する必要があります。※現時点ではDeprecated指定となっていますが、定義はそのままのため変更なしでも動作します。

例えばリスト2-6では以下のようになります。

```kotlin
var state = remember { mutableStateOf(TextFieldValue())}
```

stateでの{}内部の宣言を、mutableStateOf()内部に移動するだけで置き換えが可能です。

https://android-review.googlesource.com/c/platform/frameworks/support/+/1375120



### TextFieldによるテキスト入力

書籍では"androidx.ui.foundation.TextField"を使用していますが、TextFieldはBaseTextFieldに名前変更されています。

ただし、そのままTextFieldをBaseTextFieldに置き換えても、Android Studio上では以下の警告文が発生します。

`This foundation API is experimental and is likely to change or be removed in the future.`



どうやらBaseTextFiledを使用するためには「@ExperimentalFoundationApi」というアノテーションが必要とあるようです。このアノテーションをfuc Greeting()に付与すると、これを呼び出す側にも同じアノテーションを付与する必要があります。



"androidx.ui.foundation.BaseTextField"とは別に"androidx.compose.material.TextField"も存在します。こちらを使用したコードは以下です。

```kotlin:コード2-6
TextField(
        value = state.value,
        onValueChange = { state.value = it },
        label = { Text("TextField") }
)
```

https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#textfield



### Modifier.NoneのDeprecated

Modifierは何度が登場しますが、Modifier.NoneはDeprecatedとなっています。Modifier.Noneは例えばリスト2-7のButtonクラス内部で使用されています。Android studioでの警告どおり('None: Modifier' is deprecated. use the Modifier companion object instead) に置き換えれば問題ありません。

```kotlin:コード2-7
Button(
        modifier = Modifier,
        onClick = {
            val n = state.value.text.toInt()
            var total = 0
            for (n in 1..n) {
                total += n
            }
            message.value = "total: $total"
        }) {
    Text(
            text = "Click",
            style = TextStyle(
                    color = Color.White,
                    fontSize = 20.sp
            )
    )
}
```



### RadioButtonを用いた複数のラジオボタン表示

複数のラジオボタンを表示するRadioGroupが廃止され、使用不可となっています。代替手段としてRadioButtonとRowを用いて実現するようになっています。

書籍と同じ機能を実現するためのコードは以下です。これはAPI referenceのサンプルコードを参考にしています。

```kotlin:コード2-10
Column(){
        val radio = listOf("One", "Two", "Three")
        val (radioSelected, onRadioSelected) = remember { mutableStateOf(radio[0]) }
        Text(
            text = "selected: "  + radioSelected,
            style = TextStyle(
                color = Color.Red,
                fontSize = 28.sp
            )
        )
        radio.forEach { text ->
            Row(Modifier.fillMaxWidth()
                    .selectable(selected = (text == radioSelected),
                                onClick = { onRadioSelected(text)}
                    )
                    .padding(horizontal = 10.dp)
            ){
                RadioButton(
                        selected = (text == radioSelected),
                        onClick = { onRadioSelected(text) }
                )
                Text(
                        text = text,
                )
            }
        }
}
```



### AlertDialogの非表示関数

ダイアログ外の領域やバックボタンを押した際に呼び出されるコールバック関数がonCloseRequest()からonDismissRequest()に変更になりました。それ以外の変更はなさそうなので、onCloseRequest()をonDismissRequest()に置き換えれば問題ありません。

```kotlin:コード2-12
AlertDialog(
        onDismissRequest = {
            dlog.value = false
        },
        title = {
            Text(text = "Alert")
        },
        text = {
            Text("This is sample message!")

        },
        confirmButton = {
            Button(
                    onClick = {
                        dialogMessage.value = "You select \"OK\"!!"
                        dlog.value = false
                    }
            ) {
                Text("OK")
            }
        },
        dismissButton = {
            Button(
                    onClick = {
                        dialogMessage.value = "You canceled..."
                        dlog.value = false
                    }
            ) {
                Text("Cancel")
            }
        },
)
```



### drawRoundRectでの丸み指定

角が丸い四角形を描画するdrawRoundRectですが、角の丸みを指定する引数が変更となっています。

```kotlin:コード2-14
fun drawRoundRect(
    color: Color, 
    topLeft: Offset = Offset.Zero, 
    size: Size = this.size.offsetSize(topLeft), 
    radius: Radius = Radius.Zero, 
    ....
): Unit    
```

丸みは第4引数でandroidx.compose.ui.geomerty.Radiousクラスを用いて指定します。

```kotlin
drawRoundRect(Color.Blue, Offset(100f, 100f), Size(300f, 300f), Radius(25f, 25f))
```

丸みの横、縦幅を個別にFloatで指定するのではなく、Radiusインスタンスとして渡すことで表示できます。



### drawLineでのStroke指定

drawLine()でのStrokeの指定方法が変更となっています。書籍ではStrokeクラスでwidth, miter, StrokeCapを指定し、drawLineの第4引数で渡すことでストロークを設定していました。

最新のdrawLine()ではStrokeクラスでの指定から、直接widthとStrokeCapを引数で指定するように変更されています。

```Kotlin:コード2-16
drawLine(
        Color.Red,
        Offset(s1 * r + center.x, c1 * r + center.y),
        Offset(s2 * r + center.x, c2 * r + center.y),
        20f,
        StrokeCap.Round
)
```



### Offsetクラスのメンバ変数

表示位置を指定する際に使用するOffsetクラスに関してはプロパティ名に変更があります。

x座標のoffsetは "dx -> x"、y座標のoffsetは "dy -> y"となっています。