Memo

メモ > 技術 > IDE: AndroidStudio > アプリの作成(Jetpack Compose)

アプリの作成(Jetpack Compose)
■Jetpackについて Android Jetpackとは、アプリを作成するためのコンポーネントやツールなどをひとまとめにしたもの AndroidのOSバージョンアップからは切り離されているので、OSのアップデートを待たずに迅速に対応できるようになっている 一例だが、以下のような機能が提供されている appsearch … ユーザー向けにカスタムのアプリ内検索機能を構築する camera … モバイルカメラアプリを構築する compose … 形状とデータの依存関係を記述するコンポーズ可能な関数を使用して、UIをプログラムで定義する Android Jetpack デベロッパー リソース - Android デベロッパー | Android Developers https://developer.android.com/jetpack?hl=ja Google Developers Japan: Android Jetpack を使用してアプリの開発を加速 https://developers-jp.googleblog.com/2018/05/use-android-jetpack-to-accelerate-your.html Android Jetpackってなにもの? - Qiita https://qiita.com/k_masa777/items/c01c1de6ac763ce5c075 ■Jetpack Composeについて Jetpackで提供されるコンポーネントの一つ Kotlinで宣言的にUIを記述できる(SwiftUIのように簡単にレイアウトできるみたい) 従来のようなXMLではなく、setContentブロック内で「コンポーズ可能な関数」を呼び出してレイアウトを作成する コンポーズ可能な関数は、関数名に「@Composable」アノテーションを追加するだけで作成できる まずは以下の内容を一読するといい UI アプリ開発ツールキット Jetpack Compose - Android デベロッパー | Android Developers https://developer.android.com/jetpack/compose?hl=ja Android Compose のチュートリアル | Android デベロッパー | Android Developers https://developer.android.com/jetpack/compose/tutorial?hl=ja 以下も参考になりそう Jetpack Compose入門 はじめの一歩 https://zenn.dev/ko2ic/articles/0a141f9e5a0d39 Jetpack Composeを使ってみた - Qiita https://qiita.com/kota_2402/items/7bbdd87be8024785e25b Jetpack Compose入門 - 縁側プログラミング https://engawapg.net/programming/jetpack-compose/ ■ハローワールド(Koala Feature Drop時点) src/main/java/net/refirio/helloworld/MainActivity.kt のみ記載する
package net.refirio.helloworld import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import net.refirio.helloworld.ui.theme.HelloWorldTheme class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { HelloWorldTheme { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> Greeting( name = "Android", modifier = Modifier.padding(innerPadding) ) } } } } } @Composable fun Greeting(name: String, modifier: Modifier = Modifier) { Text( text = "Hello $name!", modifier = modifier ) } @Preview(showBackground = true) @Composable fun GreetingPreview() { HelloWorldTheme { Greeting("Android") } }
以前に比べて enableEdgeToEdge() というコードが追加されている edge-to-edgeについては、以下などのページを参照 APIレベルを上げると強制的に適用されるようなので、原則有効であるものと考える方が良さそう アプリの対象 API レベル 35 で初めて edge-to-edge に対処する[Android View編] #Android - Qiita https://qiita.com/seabat-dev/items/b1ee9c71674e80abccc7 Androidのedge-to-edge表示対応の作業メモ(Compose向け) https://zenn.dev/tomoya0x00/articles/f854a6825a1182 ■練習用にテーマを外した場合(Koala Feature Drop時点) - - - - - - - - - - - - - - - - - - - - package net.refirio.helloworld import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> MainScreen(modifier = Modifier.padding(innerPadding)) } } } } @Composable fun MainScreen(modifier: Modifier = Modifier) { Column(modifier = modifier) { Text("Hello Android!!") } } @Preview(showBackground = true) @Composable fun MainScreenPreview() { MainScreen() } - - - - - - - - - - - - - - - - - - - - ■ハローワールド(Flamingo時点) src/main/java/net/refirio/helloworld/MainActivity.kt (Androidビューでは app/java/net.refirio.helloworld/MainActivity.kt にある)
package net.refirio.helloworld import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import net.refirio.helloworld.ui.theme.HelloWorldTheme class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { HelloWorldTheme { // A surface container using the 'background' color from the theme Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { Greeting("Android") } } } } } @Composable fun Greeting(name: String, modifier: Modifier = Modifier) { Text( text = "Hello $name!", modifier = modifier ) } @Preview(showBackground = true) @Composable fun GreetingPreview() { HelloWorldTheme { Greeting("Android") } }
build.gradle.kts
// Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { id("com.android.application") version "8.1.0" apply false id("org.jetbrains.kotlin.android") version "1.8.10" apply false }
app\build.gradle.kts
plugins { id("com.android.application") id("org.jetbrains.kotlin.android") } android { namespace = "com.example.helloworld" compileSdk = 33 defaultConfig { applicationId = "com.example.helloworld" minSdk = 24 targetSdk = 33 versionCode = 1 versionName = "1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary = true } } buildTypes { release { isMinifyEnabled = false proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = "1.8" } buildFeatures { compose = true } composeOptions { kotlinCompilerExtensionVersion = "1.4.3" } packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" } } } dependencies { implementation("androidx.core:core-ktx:1.9.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1") implementation("androidx.activity:activity-compose:1.7.0") implementation(platform("androidx.compose:compose-bom:2023.03.00")) implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.material3:material3") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00")) androidTestImplementation("androidx.compose.ui:ui-test-junit4") debugImplementation("androidx.compose.ui:ui-tooling") debugImplementation("androidx.compose.ui:ui-test-manifest") }
app\src\main\AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.HelloWorld" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="true" android:label="@string/app_name" android:theme="@style/Theme.HelloWorld"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
■練習用にテーマを外した場合(Flamingo時点) src/main/java/net/refirio/helloworld/MainActivity.kt
package com.example.helloworld import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MainScreen() } } } @Composable fun MainScreen() { Text("Hello Android!!") } @Preview(showBackground = true) @Composable fun MainScreenPreview() { MainScreen() }
app\src\main\AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="true" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
■プレビューの表示をリッチにする showSystemUiを有効にすると、プレビューにUIが表示される
@Preview(showBackground = true) ↓ @Preview(showSystemUi = true)
Compose のツール | Jetpack Compose | Android Developers https://developer.android.com/jetpack/compose/tooling?hl=ja ■Jetpack Composeの基本 ※上で作成した MainScreen() の内容だけを以下に記述する
Text("Hello")
文字列の表示
Column { // テキストを表示 Text("Hello") // 色名を指定してテキストを表示 Text("Hello", color = Color.Red) // 色コードを指定してテキストを表示 Text("Hello", color = Color(0xff66ccaa)) // フォントサイズを指定してテキストを表示 Text("Hello", fontSize = 10.sp) Text("Hello", fontSize = 30.sp) }
コンポーネントの装飾
// テキストを装飾 Text( "Hello", modifier = Modifier .size(120.dp, 80.dp) .offset(20.dp, 20.dp) .background(Color(0xff66cdaa), RoundedCornerShape(20.dp)) .border(2.dp, Color(0xff2f4f4f), RoundedCornerShape(20.dp)) .padding(20.dp) )
画像の表示 あらかじめ、res/drawable 内に画像を配置しておく(ここでは「photo01.jpg」としておく)
Image( painter = painterResource(R.drawable.photo01), contentDescription = "画像の表示サンプル" )
Imageを使えない場合、自動で適切ではないクラスが読み込まれている可能性がある この場合、以下のように読み込むクラスを調整する
import androidx.compose.ui.semantics.Role.Companion.Image ↓ import androidx.compose.foundation.Image
【Jetpack Compose】Image()コンポーザブルが使用できない - Qiita https://qiita.com/antk/items/3b10b5f8843bb8896470 縦に並べる
Column { Text("Hello!") Text("Hello!!") Text("Hello!!!") }
横に並べる
Row { Image( painter = painterResource(id = R.drawable.photo01), contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier.size(50.dp) ) Image( painter = painterResource(id = R.drawable.photo02), contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier.size(50.dp) ) Image( painter = painterResource(id = R.drawable.photo03), contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier.size(50.dp) ) }
入れ子にする
Column { Row { Text("[AAA]") Text("[BBB]") Text("[CCC]") } Row { Text("[DDD]") Text("[EEE]") Text("[FFF]") } }
ボタンの表示
Column { Text("これはボタンのテストです。") Button( onClick = { Log.d("Button", "onClick") } ) { Text("ボタン") } }
ボタンをクリックしてUIを更新
Column { // 「by remember」と「mutableStateOf」により、前回の値を記憶している var count by remember { mutableStateOf(0) } Text("ボタンのタップ回数: $count") Button( onClick = { count++ } ) { Text("カウントアップ") } }
値の保持については ・「by remember」で宣言すると、Composable関数で特定の値を保持できる(値がリセットされない) rememberの後の「{ 〜 }」ブロック内は、初回しか実行されない。つまり初期値をセットできる ・「mutableStateOf」は、値の変更を監視することが可能なMutableStateを返す ・「by remember」で宣言された変数(count)は見た目は普通のintだが、ComposeではStateとして扱われる ただし、この変数を別のStateでない変数に代入すると、代入先の変数は普通の変数となり、値の変更も監視されなくなる という仕組みで実現している 「remember」や「mutableStateOf」については、以下なども参考になる Jetpack Compose入門(11) ボタンクリックでUIを更新する - 縁側プログラミング https://engawapg.net/jetpack-compose/1038/update-ui-on-click-button/ もう雰囲気で使わない。rememberを理解するためのポイント - 縁側プログラミング https://engawapg.net/jetpack-compose/2113/remember-tips/ 「by remember」を使う際、
var count by remember { mutableStateOf(0) }
のコードで以下のようなエラーになることがあった この場合、IDEの機能でimportを何度か行うと解消されるみたい
Type 'TypeVariable(T)' has no method 'getValue(Nothing?, KProperty<*>)' and thus it cannot serve as a delegate
Caused by: org.gradle.api.GradleException: Compilation error. See log for more details
UIを専用の関数にまとめる
@Composable fun MainScreen() { Column { SubContents() SubContents() SubContents() } } @Composable fun SubContents() { Row { Text("[AAA]") Text("[BBB]") Text("[CCC]") } }
■Jetpack Composeで画面遷移 Jetpack Compose入門(15) 画面遷移 - 縁側プログラミング https://engawapg.net/jetpack-compose/1393/screen-transition/ 画面遷移には androidx.navigation.compose パッケージが必要なので導入する 以下のページでバージョンを確認する Navigation | Jetpack | Android Developers https://developer.android.com/jetpack/androidx/releases/navigation?hl=ja 現時点での安定板は「2.5.3」となっていた build.gradle の dependencies 内に以下を追加する
implementation "androidx.navigation:navigation-compose:2.5.3"
追加したら「Sync Now」をクリックする Jetpack Composeで画面遷移させる | mokelab tech sheets https://tech.mokelab.com/android/compose/app/navigation/navigate.html 以下のとおり実装する
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MainScreen() } } } @Composable fun MainScreen() { val navController = rememberNavController() NavHost(navController = navController, startDestination = "FirstScreen") { composable("FirstScreen") { FirstScreen(navController = navController) } composable("SecondScreen") { SecondScreen(navController = navController) } } } @Composable fun FirstScreen(navController: NavController) { Column { Text("スクリーンA") Button(onClick = { navController.navigate("SecondScreen") }) { Text("スクリーンBへ") } } } @Composable fun SecondScreen(navController: NavController) { Column { Text("スクリーンB") Button(onClick = { navController.navigateUp() }) { Text("スクリーンAへ") } } } @Preview(showSystemUi = true) @Composable fun MainScreenPreview() { MainScreen() //FirstScreen() //SecondScreen() }
上のように navController を渡すのは明快ではあるが、テストのことを考えると推奨されないらしい 以下のようにすることが推奨されるらしい Compose を使用したナビゲーション | Jetpack Compose | Android Developers https://developer.android.com/jetpack/compose/navigation?hl=ja
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MainScreen() } } } @Composable fun MainScreen() { val navController = rememberNavController() NavHost(navController = navController, startDestination = "FirstScreen") { composable("FirstScreen") { FirstScreen( onNavigateToSecondScreen = { navController.navigate("SecondScreen") }, onNavigateToThirdScreen = { navController.navigate("ThirdScreen") } ) } composable("SecondScreen") { SecondScreen( onNavigateToThirdScreen = { navController.navigate("ThirdScreen") } ) } composable("ThirdScreen") { ThirdScreen() } } } @Composable fun FirstScreen(onNavigateToSecondScreen: () -> Unit, onNavigateToThirdScreen: () -> Unit) { Column { Text("スクリーン1") Button(onClick = onNavigateToSecondScreen) { Text("スクリーン2へ") } Button(onClick = onNavigateToThirdScreen) { Text("スクリーン3へ") } } } @Composable fun SecondScreen(onNavigateToThirdScreen: () -> Unit) { Column { Text("スクリーン2") Button(onClick = onNavigateToThirdScreen) { Text("スクリーン3へ") } } } @Composable fun ThirdScreen() { Column { Text("スクリーン3") } }
Jetpack Compose入門(15) 画面遷移 - 縁側プログラミング https://engawapg.net/jetpack-compose/1393/screen-transition/ 以下のようにすると、画面遷移の際に引数を受け渡しできる
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MainScreen() } } } @Composable fun MainScreen() { val navController = rememberNavController() NavHost(navController = navController, startDestination = "FirstScreen") { composable("FirstScreen") { FirstScreen( onNavigateToSecondScreen = { navController.navigate("SecondScreen") }, onNavigateToThirdScreen = { navController.navigate("ThirdScreen") }, onNavigateToProfileScreen = { userId, message -> navController.navigate("ProfileScreen/$userId/$message") } ) } composable("SecondScreen") { SecondScreen( onNavigateToThirdScreen = { navController.navigate("ThirdScreen") } ) } composable("ThirdScreen") { ThirdScreen() } composable( "ProfileScreen/{userId}/{message}", arguments = listOf( navArgument("userId") { type = NavType.IntType }, navArgument("message") { type = NavType.StringType } ) ) { backStackEntry -> val userId = backStackEntry.arguments?.getInt("userId") ?: 0 val message = backStackEntry.arguments?.getString("message") ?: "" ProfileScreen( userId, message, onNavigateToFirstScreen = { navController.navigate("FirstScreen") } ) } } } @Composable fun FirstScreen( onNavigateToSecondScreen: () -> Unit, onNavigateToThirdScreen: () -> Unit, onNavigateToProfileScreen: (Int, String) -> Unit ) { Column { Text("スクリーン1") Button(onClick = onNavigateToSecondScreen) { Text("スクリーン2へ") } Button(onClick = onNavigateToThirdScreen) { Text("スクリーン3へ") } Text("プロフィール") Button(onClick = { onNavigateToProfileScreen(1, "テスト1") }) { Text("プロフィール1へ") } Button(onClick = { onNavigateToProfileScreen(2, "テスト2") }) { Text("プロフィール2へ") } Button(onClick = { onNavigateToProfileScreen(3, "テスト3") }) { Text("プロフィール3へ") } } } @Composable fun SecondScreen(onNavigateToThirdScreen: () -> Unit) { Column { Text("スクリーン2") Button(onClick = onNavigateToThirdScreen) { Text("スクリーン3へ") } } } @Composable fun ThirdScreen() { Column { Text("スクリーン3") } } @Composable fun ProfileScreen( userId: Int = 0, message: String = "text", onNavigateToFirstScreen: () -> Unit ) { Column { Text("プロフィール $userId $message") Button(onClick = onNavigateToFirstScreen) { Text("スクリーン1へ") } } }
画面遷移については、以下などを参考に引き続き確認したい Jetpack Composeで画面遷移させる | mokelab tech sheets https://tech.mokelab.com/android/compose/app/navigation/navigate.html JetpackComposeでQiitaのクライアントアプリを作ろう|Masato Ishikawa https://note.com/masato1230/n/n743532de2d84 [Jetpack Compose] NavigationBar と Nested Navigation https://zenn.dev/ykrods/articles/580bc1fda58081 JetpackComposeのNavigation Componentを触ったのでまとめる - Qiita https://qiita.com/b4tchkn/items/55b1892ed725297eefe3 Jetpack Composeにおける画面遷移とは? - dely Tech Blog https://tech.dely.jp/entry/2021/12/17/170000 【シンプルサンプル】AndroidStudio 画面遷移 - Qiita https://qiita.com/kiyoZy/items/259699222ae1fec65a8f Jetpack Compose入門(15) 画面遷移 - 縁側プログラミング https://engawapg.net/jetpack-compose/1393/screen-transition/ ■Jetpack Composeでリスト表示 Jetpack Compose入門(17) リスト - 縁側プログラミング https://engawapg.net/jetpack-compose/1442/list/ 簡単なリスト
val fruits = listOf("リンゴ", "オレンジ", "グレープ", "ピーチ", "ストロベリー") LazyColumn { items(fruits) { fruit -> Text(text = "これは $fruit です。") } }
複数セットのデータを扱うリスト
data class Fruits(val english: String, val japanese: String) val fruits = listOf( Fruits("Apple", "リンゴ"), Fruits("Orange", "オレンジ"), Fruits("Grape", "グレープ"), Fruits("Peach", "ピーチ"), Fruits("Strawberry", "ストロベリー"), ) LazyColumn { items(fruits) { fruit -> Text("${fruit.english}は日本語で${fruit.japanese}です。") } }
タップでトーストを表示
val context = LocalContext.current data class Fruits(val english: String, val japanese: String) val fruits = listOf( Fruits("Apple", "リンゴ"), Fruits("Orange", "オレンジ"), Fruits("Grape", "グレープ"), Fruits("Peach", "ピーチ"), Fruits("Strawberry", "ストロベリー"), ) LazyColumn { itemsIndexed(fruits) { index, fruit -> Text( text = "${index}. ${fruit.english}", modifier = Modifier.clickable { Toast.makeText(context, "日本語で${fruit.japanese}です。", Toast.LENGTH_SHORT).show() } ) } }
■テーマの適用 Jetpack Compose入門(18) テーマカラーの適用 - 縁側プログラミング https://engawapg.net/jetpack-compose/1457/theme/ テーマを適用したコードは以下のとおり (AndroidStudioが生成するデフォルトコードを若干調整したもの) src/main/java/net/refirio/helloworld/MainActivity.kt
package net.refirio.helloworld import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import net.refirio.helloworld.ui.theme.HelloWorldTheme class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { HelloWorldTheme { Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { MainScreen() } } } } } @Composable fun MainScreen(modifier: Modifier = Modifier) { Text( text = "Hello!", modifier = modifier ) } @Preview(showSystemUi = true) @Composable fun MainScreenPreview() { HelloWorldTheme { MainScreen() } }
自動的に作成された HelloWorldTheme テーマが適用されている MainScreen定義部分の「fun MainScreen(modifier: Modifier = Modifier) {」でデフォルトのModifierを参照させているが、これは特に修飾が適用されていないもの 例えばMainScreen呼び出し部分で「MainScreen(modifier = Modifier.padding(16.dp))」とすると、Textには16.pdのパディングが設定される app\src\main\AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.HelloWorld" tools:targetApi="31"> <activity android:name=".MainActivity" android:exported="true" android:label="@string/app_name" android:theme="@style/Theme.HelloWorld"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
2箇所ある「android:theme="@style/Theme.HelloWorld"」部分でテーマを適用している app\src\main\java\net\refirio\helloworld\ui\theme\Theme.kt
package net.refirio.helloworld.ui.theme import android.app.Activity import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.MaterialTheme import androidx.compose.material3.darkColorScheme import androidx.compose.material3.dynamicDarkColorScheme import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.runtime.SideEffect import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.core.view.WindowCompat private val DarkColorScheme = darkColorScheme( primary = Purple80, secondary = PurpleGrey80, tertiary = Pink80 ) private val LightColorScheme = lightColorScheme( primary = Purple40, secondary = PurpleGrey40, tertiary = Pink40 /* Other default colors to override background = Color(0xFFFFFBFE), surface = Color(0xFFFFFBFE), onPrimary = Color.White, onSecondary = Color.White, onTertiary = Color.White, onBackground = Color(0xFF1C1B1F), onSurface = Color(0xFF1C1B1F), */ ) @Composable fun HelloWorldTheme( darkTheme: Boolean = isSystemInDarkTheme(), // Dynamic color is available on Android 12+ dynamicColor: Boolean = true, content: @Composable () -> Unit ) { val colorScheme = when { dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { val context = LocalContext.current if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) } darkTheme -> DarkColorScheme else -> LightColorScheme } val view = LocalView.current if (!view.isInEditMode) { SideEffect { val window = (view.context as Activity).window window.statusBarColor = colorScheme.primary.toArgb() WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme } } MaterialTheme( colorScheme = colorScheme, typography = Typography, content = content ) }
テーマファイルも、Kotlinで書かれたプログラムとなっている lightColorSchemeの内容を調整することで、配色を変更できる…が、そのままだと適用されない さらに以下の部分をコメントアウトもしくは削除すると、色の変更が反映される
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { val context = LocalContext.current if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) }
【Jetpack Compose】Material3でテーマカラーを変更する際に陥りがちなミス - Qiita https://qiita.com/Nagumo-7960/items/8699f7670bff4cc7a137 ■画面領域の調整(未解決) 「Jetpack Composeの基本」の内容を試していると、エミュレータ、実機ともに表示が途中で途切れたようになる …が、色々な要素を配置していくと全体が表示された…? 何か専用の指定があるのか、引き続き確認したい

Advertisement