0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Qiita全国学生対抗戦Advent Calendar 2023

Day 12

[compose multiplatform 中級チュートリアル2]ページ遷移のやり方[compose multiplatform]

Last updated at Posted at 2023-12-11

前回

前回はアプリ作成の準備でした。

ページ遷移させる

せっかくログイン画面がついているので残します。
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")
}

以上です。

次の記事はアプリの見た目作成です。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?