前回
前回はアプリ作成の準備でした。
ページ遷移させる
せっかくログイン画面がついているので残します。
widgetで選択したライブラリはvoyagerのものだったので使い方を調べると良い記事発見。
https://zenn.dev/turtlekazu/articles/f300809a2c0edb
骨組みを作る
まずは、ログイン画面とリスト画面の二つのファイルだけ作っちゃいます。
ListScreen
package org.company.saikyotodo.List
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.core.screen.Screen
class ListScreen(): Screen {
@Composable
override fun Content() {
val viewModel = rememberScreenModel { ListScreenModel() }
Text("タスク一覧を表示")
}
}
ListScreenModel
package org.company.saikyotodo.List
import cafe.adriel.voyager.core.model.ScreenModel
class ListScreenModel(): ScreenModel {
// 処理
}
LoginScreen
package org.company.saikyotodo.Login
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.core.screen.Screen
class LoginScreen(): Screen {
@Composable
override fun Content() {
val viewModel = rememberScreenModel { LoginScreenModel() }
Text("ログイン画面")
}
}
LoginScreenModel
package org.company.saikyotodo.Login
import cafe.adriel.voyager.core.model.ScreenModel
class LoginScreenModel(): ScreenModel {
}
App.ktをログイン画面に移す
まずはLoginScreen.ktに元のApp.ktを移します。
LoginScreen.kt
package org.company.saikyotodo.Login
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.DarkMode
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.LightMode
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.core.screen.Screen
import org.company.saikyotodo.List.ListScreen
import org.company.saikyotodo.theme.LocalThemeIsDark
class LoginScreen(): Screen {
@Composable
override fun Content() {
val viewModel = rememberScreenModel { LoginScreenModel() }
var email by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var passwordVisibility by remember { mutableStateOf(false) }
Column(modifier = Modifier.fillMaxSize().windowInsetsPadding(WindowInsets.safeDrawing)) {
Row(
horizontalArrangement = Arrangement.Center
) {
Text(
text = "Login",
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(16.dp)
)
Spacer(modifier = Modifier.weight(1.0f))
var isDark by LocalThemeIsDark.current
IconButton(
onClick = { isDark = !isDark }
) {
Icon(
modifier = Modifier.padding(8.dp).size(20.dp),
imageVector = if (isDark) Icons.Default.LightMode else Icons.Default.DarkMode,
contentDescription = null
)
}
}
OutlinedTextField(
value = email,
onValueChange = { email = it },
label = { Text("Email") },
singleLine = true,
modifier = Modifier.fillMaxWidth().padding(16.dp)
)
OutlinedTextField(
value = password,
onValueChange = { password = it },
label = { Text("Password") },
singleLine = true,
visualTransformation = if (passwordVisibility) VisualTransformation.None else PasswordVisualTransformation(),
modifier = Modifier.fillMaxWidth().padding(16.dp),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Password
),
trailingIcon = {
IconButton(onClick = { passwordVisibility = !passwordVisibility }) {
val imageVector = if (passwordVisibility) Icons.Default.Close else Icons.Default.Edit
Icon(imageVector, contentDescription = if (passwordVisibility) "Hide password" else "Show password")
}
}
)
Button(
onClick = { /* Handle login logic here */ },
modifier = Modifier.fillMaxWidth().padding(16.dp)
) {
Text("Login")
}
}
}
}
次にApp.ktの処理を削除して、最初はLoginScreenを表示するように修正
App.kt
package org.company.saikyotodo
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.DarkMode
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.LightMode
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.navigator.Navigator
import org.company.saikyotodo.List.ListScreen
import org.company.saikyotodo.Login.LoginScreen
import org.company.saikyotodo.theme.AppTheme
import org.company.saikyotodo.theme.LocalThemeIsDark
@Composable
internal fun App() = AppTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
val screens = listOf(LoginScreen())
Navigator(screens)
}
}
internal expect fun openUrl(url: String?)
Login画面からList画面への遷移を定義する
LoginScreen.ktの中に画面遷移用のnavigatorを定義
~~~
override fun Content() {
val viewModel = rememberScreenModel { LoginScreenModel() }
var email by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var passwordVisibility by remember { mutableStateOf(false) }
val navigator = LocalNavigator.currentOrThrow
Column(modifier = Modifier.fillMaxSize().windowInsetsPadding(WindowInsets.safeDrawing)) {
~~~
ログインボタンのクリック処理として、List画面への遷移を定義
Button(
onClick = {
navigator.push(ListScreen())
},
modifier = Modifier.fillMaxWidth().padding(16.dp)
) {
Text("Login")
}
以上です。
次
次の記事はアプリの見た目作成です。