Android Day 22 Let's add edit and save functionality to our Contact App

I first seperate the dialog to a seperate composible, so we are not having so much things cramp inside the main activity.

package com.williamjiamin.contactappdemo

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.williamjiamin.contactappdemo.ui.theme.ContactAppDemoTheme

class MainActivity : ComponentActivity() {
    @OptIn(ExperimentalMaterial3Api::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ContactAppDemoTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    var contactPersons by remember { mutableStateOf(listOf<Contact>()) }
                    var selectedContact by remember { mutableStateOf<Contact?>(null) }
                    var showPopUpWindow by remember { mutableStateOf(false) }

                    Column(
                        modifier = Modifier.fillMaxSize(),
                        verticalArrangement = Arrangement.Center
                    ) {
                        LazyColumn(
                            modifier = Modifier
                                .fillMaxWidth()
                                .weight(1f)
                                .padding(16.dp)
                        ) {
                            items(contactPersons) { contact ->
                                // Display each contact here
                                showingEveryContactPerson(
                                    everyContact = contact,
                                    onChangeClick = {
                                        // Logic for changing contact
                                        selectedContact = contact
                                    },
                                    onDeleteClick = {
                                        // Logic for deleting contact
                                        contactPersons = contactPersons.filter { it.id != contact.id }
                                    }
                                )
                            }
                        }

                        Button(
                            onClick = { showPopUpWindow = true },
                            modifier = Modifier
                                .fillMaxWidth()
                        ) {
                            Text("Add Contact")
                        }

                        if (showPopUpWindow) {
                            AddContactDialog(
                                onDismiss = { showPopUpWindow = false },
                                onSave = { newContact ->
                                    contactPersons = contactPersons + newContact
                                    showPopUpWindow = false
                                }
                            )
                        }

                        selectedContact?.let {
                            EditEveryContact(
                                everyContact = it,
                                onDismiss = { selectedContact = null },
                                onSave = { updatedContact ->
                                    contactPersons = contactPersons.map { contact ->
                                        if (contact.id == updatedContact.id) {
                                            updatedContact
                                        } else {
                                            contact
                                        }
                                    }
                                    selectedContact = null
                                }
                            )
                        }
                    }
                }
            }
        }
    }
}

@Composable
fun AddContactDialog(
    onDismiss: () -> Unit,
    onSave: (Contact) -> Unit
) {
    var name by remember { mutableStateOf("") }
    var phone by remember { mutableStateOf("") }
    var email by remember { mutableStateOf("") }
    var address by remember { mutableStateOf("") }

    AlertDialog(
        onDismissRequest = onDismiss,
        title = { Text("Add Contact") },
        text = {
            Column {
                OutlinedTextField(
                    value = name,
                    onValueChange = { name = it },
                    label = { Text("Name") }
                )
                OutlinedTextField(
                    value = phone,
                    onValueChange = { phone = it },
                    label = { Text("Phone") }
                )
                OutlinedTextField(
                    value = email,
                    onValueChange = { email = it },
                    label = { Text("Email") }
                )
                OutlinedTextField(
                    value = address,
                    onValueChange = { address = it },
                    label = { Text("Address") }
                )
            }
        },
        confirmButton = {
            Button(onClick = {
                if (name.isNotEmpty()){
                    onSave(Contact(id = (0..10000).random(), name = name, phone = phone, email = email, address = address))
                }
            }) {
                Text("Save")
            }
        },
        dismissButton = {
            Button(onClick = onDismiss) {
                Text("Cancel")
            }
        }
    )
}

@Composable
fun showingEveryContactPerson(
    everyContact: Contact,
    onChangeClick: () -> Unit,
    onDeleteClick: () -> Unit,
) {
    // Display each contact here

        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(8.dp)
                .border(5.dp, Color.LightGray, MaterialTheme.shapes.medium)
        ){
            Column (
                modifier = Modifier
                    .padding(8.dp)
                    .fillMaxWidth()

            ) {
                Text("Name: ${everyContact.name}")
                Text("Phone: ${everyContact.phone}")
                Text("Email: ${everyContact.email}")
                Text("Address: ${everyContact.address}")
                Spacer(modifier = Modifier.height(8.dp))
                Row (
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.Center
                ){
                    Button(onClick = onChangeClick,
                        modifier = Modifier
                            .padding(8.dp)
                    ) {
                        Text("Change")
                    }
                    Spacer(modifier = Modifier.width(8.dp))
                    Button(
                        onClick = onDeleteClick,
                        modifier = Modifier.padding(8.dp)
                    ) {
                        Text("Delete")
                    }
                }
            }
        }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EditEveryContact(
    everyContact: Contact,
    onDismiss: () -> Unit,
    onSave: (Contact) -> Unit) {

    var editedName by remember { mutableStateOf(everyContact.name) }
    var editedPhone by remember { mutableStateOf(everyContact.phone) }
    var editedEmail by remember { mutableStateOf(everyContact.email) }
    var editedAddress by remember { mutableStateOf(everyContact.address) }

    AlertDialog(
        onDismissRequest = onDismiss,
        title = { Text("Edit Contact") },
        text = {
            Column {
                OutlinedTextField(
                    value = editedName,
                    onValueChange = { editedName = it },
                    label = { Text("Name") }
                )
                OutlinedTextField(
                    value = editedPhone,
                    onValueChange = { editedPhone = it },
                    label = { Text("Phone") }
                )
                OutlinedTextField(
                    value = editedEmail,
                    onValueChange = { editedEmail = it },
                    label = { Text("Email") }
                )
                OutlinedTextField(
                    value = editedAddress,
                    onValueChange = { editedAddress = it },
                    label = { Text("Address") }
                )
            }
        },
        confirmButton = {
            Button(onClick = {
                onSave(
                    Contact(everyContact.id, editedName, editedPhone, editedEmail, editedAddress)
                )
            }) {
                Text("Save")
            }
        },
        dismissButton = {
            Button(onClick = onDismiss) {
                Text("Cancel")
            }
        }
    )
}

data class Contact(
    val id: Int,
    var name: String,
    var phone: String,
    var email: String,
    var address: String,
)

And we finish our demo app. In the future , we are going to learn how to add database the this app.

Stay tuned!

Get New Tutorials by Email

No spam. Just clear, practical breakdowns you can apply right away.

Enjoy this tutorial?

Get new practical tech tutorials in your inbox.