はじめに
JetpackComposeチュートリアルを学んだ内容を記載してます
(一応第0回の続き)
レッスン1 コンポーズ可能な関数
コンポーズ可能な関数とは
- @Composableアノテーションを付けることで宣言可能
- UIの外観とデータの依存関係を指定することによってアプリのUIをプログラムで定義できる関数
- 要素の初期化や親のViewへのアタッチなどを気にしなくて済む
テキスト追加
- setContentブロックでコンポーズ可能な関数が呼び出されるアクティビティのレイアウトを定義
- Textは画面上にテキストラベルを表示
setContent {
Text("Hello world!")
}
コンポーズ可能な関数を定義
@Composable
アノテーションを追加することで関数をコンポーズ可能にできる
@Composable
fun MessageCard(name: String) {
Text(text = "Hello $name!")
}
AndroidStudioでプレビュー
- @Previewアノテーションを付けることでAndroidデバイスやエミュレータにインストールせずに確認できる
- @Previewアノテーションはパラメータを受け取らないコンポーズ可能な関数にのみ使用することができる
@Preview
@Composable
fun PreviewMessageCard() {
MessageCard("Android")
}
レッスン2 レイアウト
- Composeで定義していくUIは階層状
- コンポーズ可能な関数からコンポーズ可能な関数を呼び出していくことで様々なUIを表現可能
複数テキストの定義
data class Message(val author: String, val body: String)
@Composable
fun MessageCard(msg: Message) {
Text(text = msg.author)
Text(text = msg.body)
}
列を使用する
- Column関数で要素を垂直方向に揃えることができる
- Row関数は水平方向
- Box関数で要素を積み重ねられる
@Composable
fun MessageCard(msg: Message) {
Column {
Text(text = msg.author)
Text(text = msg.body)
}
}
画像要素を追加
- Image関数で画像リソースを追加
- contentDescriptionも設定可能
Image(
painter = painterResource(R.drawable.profile_picture),
contentDescription = "Contact profile picture",
)
レイアウトを構成
-
Modifier
関数- コンポーザブルのサイズ、レイアウト、外観の変更
- padding,widh,height
- clip,borderなど
- クリック可能などのインタラクションを追加
- clickableなど
- コンポーザブルのサイズ、レイアウト、外観の変更
Row(modifier = Modifier.padding(all = 8.dp)) {
Image(
painter = painterResource(R.drawable.profile_picture),
contentDescription = "Contact profile picture",
modifier = Modifier
// 画像サイズ設定
.size(40.dp)
// 丸で型取り
.clip(CircleShape)
)
// 要素同士横方向のスペース設定
Spacer(modifier = Modifier.width(8.dp))
Column {
Text(text = msg.author)
// テキスト縦方向のスペース設定
Spacer(modifier = Modifier.height(4.dp))
Text(text = msg.body)
}
}
レッスン3 マテリアルデザイン
Composeはマテリアルデザインの原則をサポート
UI要素の多くは最初からマテリアルデザインを実装
マテリアルデザインの使用
- プロジェクトの名前+Theme(例:ComposeTutorialTheme)とSurface関数でをコンポーズ可能な関数をラップ
- マテリアルデザインは
Color
,Typography
,Shape
を中心に構成
setContent {
ComposeTutorialTheme {
Surface(modifier = Modifier.fillMaxSize()) {
MessageCard(Message("Android", "Jetpack Compose"))
}
}
}
Color
-
MaterialTheme.Colors
を使用 - 必要な場合どこでもテーマの値を使用可能
modifier = Modifier
.size(40.dp)
.clip(CircleShape)
// 枠線を描画し、カラー適用
.border(1.5.dp, MaterialTheme.colors.secondary, CircleShape)
Typography
-
MaterialTheme.typography
をTextに使用 - 活字の設定可能
Text(
text = msg.body,
// Textに対してbody2を適用
style = MaterialTheme.typography.body2
)
Shape
- Surface関数でコンポーズ可能な関数をラップ
- Surface関数に
MaterialTheme.shapes
を使って設定可能
// shapes.mediumを適用
Surface(shape = MaterialTheme.shapes.medium, elevation = 1.dp) {
Text(
text = msg.body,
modifier = Modifier.padding(all = 4.dp),
style = MaterialTheme.typography.body2
)
}
ダークテーマを有効
- マテリアルデザインのサポートでダークテーマを処理可能
- ダークモード有効で自動的に調整
- Preview内でも設定する事で確認可能
// 通常モードのプレビュー
@Preview(name = "Light Mode")
// ダークモードのプレビュー
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true,
name = "Dark Mode"
)
レッスン4 リストとアニメーション
アプリ内のあらゆる場所で使われるリストとアニメーションを、Composeを使って簡潔に実装
メッセージのリストを作成
- LazyColumn, LazyRowで複数要素を扱う
- items()でパラメータでListを受け取れる
- 画面上で表示される要素のみレンダリング
@Composable
fun Conversation(messages: List<Message>) {
LazyColumn {
// 扱うListを受け取る
items(messages) { message ->
// 1つごとの要素に対してComposable関数を適用
MessageCard(message)
}
}
}
展開時のアニメーション
展開されているというUI状態を保存をするためにremember
関数とmutableStateOf
関数を使ってトラッキングを行う
- remember:ローカル状態をメモリに格納
- mutableStateOf:ここに渡された値をトラッキングに用いる
rememberやmutableStateOfなどの状態を扱う関数を使うことで、状態の変更によるUIの自動更新が可能
→これを再コンポーズという
// rememberで展開状態を保持
var isExpanded by remember { mutableStateOf(false) }
// 展開状態によって色をアニメーション状に変える変数
val surfaceColor by animateColorAsState(
if (isExpanded) MaterialTheme.colors.primary else MaterialTheme.colors.surface,
)
// タップによる展開状態を反映
Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {
Text(
text = msg.author,
color = MaterialTheme.colors.secondaryVariant,
style = MaterialTheme.typography.subtitle2
)
Spacer(modifier = Modifier.height(4.dp))
Surface(
shape = MaterialTheme.shapes.medium,
elevation = 1.dp,
// 展開状態でアニメーション状に色が変わる値を代入
color = surfaceColor,
// 1dpずつ展開が拡大していくよう設定
modifier = Modifier.animateContentSize().padding(1.dp)
) {
Text(
text = msg.body,
modifier = Modifier.padding(all = 4.dp),
// メッセージが展開されている時は全体表示
maxLines = if (isExpanded) Int.MAX_VALUE else 1,
style = MaterialTheme.typography.body2
)
}
}
成果物
チュートリアルを最後まで実施して出来上がる成果物がこちら
アニメーション展開可能な、アイコン, 名前, メッセージが要素のメッセージリストが出来上がる
まとめ
コンポーズ可能な関数とは
- @Composableをつける事で宣言可能な関数
- アプリのUIをプログラムで定義可能
コンポーズ可能な関数の種類
- setContent:レイアウトを定義
- Text:テキスト
- Column:縦に要素を並べる
- Row:横に要素を並べる
- Box:要素を積み重ねる
- Image:画像を扱う
- Modifier:要素の様々な設定
- コンポーザブルのサイズ、レイアウト、外観の変更
- padding,widh,height
- clip,borderなど
- クリック可能などのインタラクションを追加
- clickable
- アニメーションに関する設定
- animateContentSize
- コンポーザブルのサイズ、レイアウト、外観の変更
- プロジェクト名+Theme:マテリアルデザインの適用
- Color:色
- Typography:活字
- Shape:形状
- LazyColumn,LazyRow:リストを表示、itemsで要素を扱う
- remember,mutableStateOf:状態をローカルに保持して再コンポーズに使用
- animateColorAsState:状態によって表示を変える
プレビュー
-
@PreviewアノテーションでAndroidStudio状で表示の確認可能
- ダークモードも確認可能
感想
今回Composeにおける多くの要素を学んだが、まだ慣れておらずxmlの方がどの要素に何があるかを理解しやすいなと思った。(慣れれば変わると期待)
LazyColumnやLazyRowを使ってこれまでRecyclerViewでやっていた事を置き換えるとなった時に、どの程度の複雑さになるかが気になった。
次回はCompose思想を学ぶ予定