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!