Android Studio

シンプルなToDoリストを作ってみる

シンプルなToDoリストを作ってみる

実装するために、以下のことを行います。

  • 新しいComposable関数(TodoListScreen など)を作成する。
  • LazyColumn を使って、リスト項目を効率的に表示できるようにする。
  • リストに追加する項目を保持するための状態変数(MutableState<List<String>>)を定義する。
  • 入力欄(TextField)と追加ボタンを配置する。
  • ボタンを押したときに、入力されたテキストをリストに追加し、リストが更新されるようにする。

具体的な手順

既存の MainActivity.kt ファイルに、新しいComposable関数を追加し、NavHost からアクセスできるようにします。

1. 必要なimportを追加

ファイルの先頭あたりに、以下を追加してください。(既にあるものもあるかもしれません)

import androidx.compose.foundation.lazy.LazyColumn // リスト表示用
import androidx.compose.foundation.lazy.items // LazyColumnでリストの要素を処理するため
import androidx.compose.material3.OutlinedTextField // 見た目がきれいな入力欄
import androidx.compose.foundation.BorderStroke // リストアイテムの枠線用
import androidx.compose.foundation.border // リストアイテムの枠線用
import androidx.compose.material3.Card // リストアイテムの見栄えを良くするため
import androidx.compose.ui.graphics.Color // 色指定用
import androidx.compose.ui.unit.sp // 文字サイズ指定用

2. 新しい画面(TodoListScreen)を作成する

MainActivity.kt の中に、SecondScreen の後にでも以下のような新しいComposable関数を追加します。

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TodoListScreen(navController: NavController) {
    // ToDoリストの項目を保持するリストの状態変数
    // rememberSaveableは、画面回転などでも状態を保持するために使う
    var todoItems by rememberSaveable { mutableStateOf(mutableListOf<String>()) }
    // 新しいToDo項目を入力するための状態変数
    var newTodoText by rememberSaveable(stateSaver = TextFieldValue.Saver) {
        mutableStateOf(TextFieldValue(""))
    }

    Column(
        modifier = Modifier.fillMaxSize().padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(
            text = "ToDoリスト",
            fontSize = 24.sp, // 少し大きめのフォント
            modifier = Modifier.padding(bottom = 16.dp)
        )

        // ToDo項目入力欄
        OutlinedTextField( // OutlinedTextFieldで見栄えの良い入力欄
            value = newTodoText,
            onValueChange = { newValue -> newTodoText = newValue },
            label = { Text("新しいToDo") },
            singleLine = true,
            modifier = Modifier
                .fillMaxWidth()
                .padding(bottom = 8.dp)
        )

        // ToDo追加ボタン
        Button(
            onClick = {
                if (newTodoText.text.isNotBlank()) { // 空でなければ追加
                    todoItems = (todoItems + newTodoText.text).toMutableList() // リストに追加
                    newTodoText = TextFieldValue("") // 入力欄をクリア
                }
            },
            modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp)
        ) {
            Text("追加")
        }

        // ToDoリストを表示するLazyColumn
        LazyColumn(
            modifier = Modifier.fillMaxSize()
        ) {
            items(todoItems) { item ->
                Card( // Cardで見栄えの良いリストアイテム
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(vertical = 4.dp),
                    border = BorderStroke(1.dp, Color.LightGray) // 枠線を追加
                ) {
                    Text(
                        text = item,
                        modifier = Modifier.padding(16.dp)
                    )
                }
            }
        }

        // 最初の画面に戻るボタン
        Button(
            onClick = { navController.popBackStack() },
            modifier = Modifier.padding(top = 16.dp)
        ) {
            Text("戻る")
        }
    }
}
  • todoItems by rememberSaveable { mutableStateOf(mutableListOf<String>()) }: ToDo項目を保持するリストです。mutableListOf を使うことで、リストに項目を追加・削除できます。
  • LazyColumn: 多数の項目を効率的に表示するためのコンポーネントです。画面に表示される範囲の項目だけをレンダリングするため、パフォーマンスが良いです。
  • items(todoItems) { item -> … }: LazyColumn の中でリストの各項目をどのように表示するかを定義します。
  • OutlinedTextField: 見た目が少しおしゃれなテキスト入力欄です。
  • Card: 各ToDo項目をカード形式で表示し、視覚的に区切りをつけます。

3. NavHost に新しいルートを追加する

MainActivity の setContent ブロック内の NavHost 定義を修正し、todo_list_screen ルートを追加します。

@OptIn(ExperimentalMaterial3Api::class)
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            YourAppNameTheme {
                val navController = rememberNavController()

                Scaffold(
                    topBar = {
                        TopAppBar(title = { Text("ToDoリストアプリ") })
                    }
                ) { paddingValues ->
                    NavHost(
                        navController = navController,
                        startDestination = "first_screen",
                        modifier = Modifier.padding(paddingValues)
                    ) {
                        composable("first_screen") {
                            FirstScreen(navController = navController)
                        }
                        composable("second_screen/{name}") { backStackEntry ->
                            val name = backStackEntry.arguments?.getString("name")
                            SecondScreen(navController = navController, name = name)
                        }
                        // 新しいToDoリスト画面のルートを追加
                        composable("todo_list_screen") {
                            TodoListScreen(navController = navController)
                        }
                    }
                }
            }
        }
    }
}

4. どこか既存の画面から TodoListScreen へ遷移するボタンを追加する

例えば、FirstScreen か SecondScreen に、TodoListScreen へ遷移するためのボタンを追加しましょう。ここでは、FirstScreen に追加する例を示します。

// FirstScreenのButtonの後にでも追加
// (既存の"2番目の画面へ"ボタンの下あたり)
        Button(onClick = {
            navController.navigate("todo_list_screen")
        }) {
            Text("ToDoリストへ")
        }

これで、アプリを再実行すると、どこかの画面から「ToDoリストへ」のボタンを押して新しい画面に遷移し、そこにテキストを入力してリストに追加できるToDoリストアプリが完成します!

※Google AI Studioによる回答を参考にしました

目次に戻る