LoginSignup
1
2

More than 1 year has passed since last update.

AndroidのUI開発にJetpack Composeを使ってみる(1)

Posted at

前提条件

  • Android Studio Arctic Fox以降
  • Kotlinの基本的文法

導入

Android Studioを開いてNew Project -> Empty Compose Activityを選択しましょう。
ただし古いバージョンのAndroid Studioを使っている場合は該当部分が存在しません。
スクリーンショット 2021-08-31 20.17.06.png

アプリケーションの情報を決めると以下のようなテンプレートコードが生成されます。(2021/8/31現在)

MainActivity.kt
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeApplicationTheme {
                // A surface container using the 'background' color from the theme
                Surface(color = MaterialTheme.colors.background) {
                    Greeting("Android")
                }
            }
        }
    }
}

@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    ComposeApplicationTheme {
        Greeting("Android")
    }
}

ここで重要なのは、

  • MainActivity -> onCreate -> setContent内にコンポーズ可能な関数から構成されるカタマリを記述する
  • @Composable修飾子をつけた関数はコンポーズ可能であるという
  • @Preview修飾子をつけた関数に配置したコンテンツがAndroid Studio上でプレビューとしてみられる

ここで以下の説明のため一旦setContent内とMainActivity外部の2つの@Composable関数は消去した状態にします。

MainActivity.kt
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {

        }
    }
}

方針

setContent内が複雑になるのを防ぐため、新しくComposable関数MyAppを定義します。UI部品の組み合わせはMyApp内部で行ってsetContentにはMyAppのみを配置するのがオススメです。また、エディタでプレビューを見られるようにするためにPreview関数も作っておきます。

MainActivity.kt
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyApp() // コレ以外書かない
        }
    }
}

@Composable
fun MyApp() {
//    ここにUI部品を並べていく
}

@Preview(showBackground = true)
@Composable
fun Preview() {
    MyApp()
}

このようにすることで、MyApp関数を編集していくだけで自動的にプレビューとエミュレータないし実機でのデバッグ時に、同じUIテストができるようになります。

UI部品の配置

後述するUI部品を、並べて配置する際はRow()Column()が使えます。ここで使うUI部品は後述するので今は流し見してください。

Row

Composable関数を横並びで表示したい場合は、並べたい部品をRow()の内部で与えることで重ならずに表示することができます。

@Composable
fun MyApp() {
//    ここにUI部品を並べていく
    Row() {
        Text(text = "ちくわぶ")
        Text(text = "ちくわ")
    }
}

image.png

Column

UI部品を縦に並べて表示したい時はRow()と同様にColumn()で括ることで実現できます。

@Composable
fun MyApp() {
//    ここにUI部品を並べていく
    Column() {
        Text(text = "ちくわぶ")
        Text(text = "ちくわ")
    }
}

image.png

UI部品

Text

画面上にテキストを配置する際はText()を使います。引数に文字列を指定することで画面に表示することができます。これを使って引数wordsの文字を画面に表示する@Composable PrintText()を定義しましょう。

@Composable
fun MyApp() {
//    ここにUI部品を並べていく
    PrintText(words = "おはようございます")
}

@Composable
fun PrintText(words: String) {
    Text(text = words)
}

今、PrintText()は構成されるComposable部品にText()1つしか持たないので、MyApp()にそのままText(words)を直書きしても構いませんが、後に機能拡張する場合を考慮して別関数にしています。

ここで、画面に表示するためのComposable関数はMyAppに並べるのを忘れないようにしてください。実行すると画面左上に下図のような文字が出力されるはずです。

image.png

よく使うText()のパラメータとして以下のものが存在します。
- color : テキストの色指定
- fontSize : テキストのサイズ変更
- maxLines : テキストの最大表示行数指定

以降でも共通の概念ですが、ここで2つの異なるText()を表示する場合は注意が必要です。

@Composable
fun MyApp() {
//    ここにUI部品を並べていく
    PrintText(words = "おはようございます")
    PrintText(words = "今日はもう寝ます")
}

このようにPrintText()を並べた場合、位置が指定されていないので2つのテキストが被さってしまい次のように表示されてしまいます。

image.png

並べて配置する際は、先述したUI部品の配置にあるRow()Column()を使いましょう。

@Composable
fun MyApp() {
//    ここにUI部品を並べていく
    Column {
        PrintText(words = "おはようございます")
        PrintText(words = "今日はもう寝ます")
    }
}

実行結果は以下のようになります。
image.png

TextField, OutlinedTextField

テキスト入力を行いたい場合はTextField()OutlinedTextField()が使えます。

@Composable
fun MyApp() {
//    ここにUI部品を並べていく
    Column() {
        TextField(value = "ほげほげ", onValueChange = {})
        OutlinedTextField(value = "ほげほげ", onValueChange = {})
    }
}

OutlinedTextField()を使う際には、
- value : 入力エリアの値
- onValueChange : 値が変化した時の処理
- label : 入力エリアの題名のようなもの
を引数で与えましょう。(labelはなくても良い)

また、テキストが変更された際に入力中であることを表すために、画面に表示されるvalueを変更し、その変更に伴ってUIが変更されるようにしたいです。これは再コンポーズと呼ばれ、今回のOutlinedTextField()の場合は以下のように記述するのが良いです。

@Composable
fun PrintTextField() {
    // textが変更されるとPrintTextFieldが再コンポーズ(再描画みたいなもの)される
    var text by remember { mutableStateOf("") } 

    OutlinedTextField(
        onValueChange = { text = it }, // 値が変わったらそれをtextにいれる
        value = text,                  // textの値をvalueに入れる->画面に表示される 
        label = { Text(text = "ここに入力")}
    )
}

remember()内のmutableStateOf()に渡す引数の値は、TextFieldに表示されてる初期値だと思ってもらえれば良いです。

ダウンロード.gif

Image

画像を表示する簡単な方法としてImage()があります。前準備としてapp->res->drawableに貼りたい画像ファイルを置いておきます。

@Composable
fun MyApp() {
//    ここにUI部品を並べていく
    Image(
        painter = painterResource(id = R.drawable.ckwb),
        contentDescription = "プロフィール画像"
    )
}

painterResource()に与えている引数のidR.drawable.(ファイル名)の形です。

細かなレイアウト指示

Modifier

Text()Image()などComposableな関数には引数にmodifierを与えることができることが多いです。ここでは細かいレイアウトの指示を行うことができます。

@Composable
fun MyApp() {
//    ここにUI部品を並べていく
    Row {
        DisplayMyImage()  // 画像表示
        ProfileTextArea() // 名前と本文の表示
    }
}

@Composable
fun DisplayMyImage() {
    Image(
        painter = painterResource(id = R.drawable.ckwb),
        contentDescription = "プロフィール画像",
        modifier = Modifier
            .padding(all = 8.dp)
            .size(50.dp)
            .clip(CircleShape)
    )
}

@Composable 
fun ProfileTextArea() {
    Column() {
        PrintName(name = "ちくわぶ")
        PrintBody(text = "ほげほげとふがふがの間")
    }
}

@Composable
fun PrintName(name: String) {
    Text(
        text = name, 
        color = Color.Green,
        style = MaterialTheme.typography.subtitle1,
        modifier = Modifier.padding(all = 4.dp)
    )
}

@Composable
fun PrintBody(text: String) {
    Text(
        text = text,
        style = MaterialTheme.typography.body2,
        modifier = Modifier.padding(all = 4.dp)
    )
}

実行すると以下のようなプロフィールが出力できます。

image.png

参考

Jetpack Compose Tutorial

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2