diff --git a/app/src/main/java/com/example/jetpack_compose_all_in_one/di/AppModules.kt b/app/src/main/java/com/example/jetpack_compose_all_in_one/di/AppModules.kt index fbec0b10..e6686c89 100644 --- a/app/src/main/java/com/example/jetpack_compose_all_in_one/di/AppModules.kt +++ b/app/src/main/java/com/example/jetpack_compose_all_in_one/di/AppModules.kt @@ -1,6 +1,8 @@ package com.example.jetpack_compose_all_in_one.di import android.content.Context +import com.example.jetpack_compose_all_in_one.lessons.lesson_3.PersonRepository +import com.example.jetpack_compose_all_in_one.lessons.lesson_3.PersonRepositoryImpl import com.example.jetpack_compose_all_in_one.utils.Constants import dagger.Module import dagger.Provides @@ -16,4 +18,10 @@ object AppModules { @Singleton fun provideSharedPref(@ApplicationContext context: Context) = context.getSharedPreferences(Constants.SHARED_PREF_NAME, Context.MODE_PRIVATE) + + @Provides + @Singleton + fun providePersonRepository(): PersonRepository { + return PersonRepositoryImpl() + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/Person.kt b/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/Person.kt new file mode 100644 index 00000000..4acedd59 --- /dev/null +++ b/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/Person.kt @@ -0,0 +1,3 @@ +package com.example.jetpack_compose_all_in_one.lessons.lesson_3 + +data class Person(var id: Int, var name: String) \ No newline at end of file diff --git a/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/PersonRepository.kt b/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/PersonRepository.kt new file mode 100644 index 00000000..f7ee63a4 --- /dev/null +++ b/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/PersonRepository.kt @@ -0,0 +1,5 @@ +package com.example.jetpack_compose_all_in_one.lessons.lesson_3 + +interface PersonRepository { + fun getPersonList(): List +} \ No newline at end of file diff --git a/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/PersonRepositoryImpl.kt b/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/PersonRepositoryImpl.kt new file mode 100644 index 00000000..eb895f81 --- /dev/null +++ b/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/PersonRepositoryImpl.kt @@ -0,0 +1,11 @@ +package com.example.jetpack_compose_all_in_one.lessons.lesson_3 + +class PersonRepositoryImpl : PersonRepository { + override fun getPersonList(): List { + val list = mutableListOf() + for (i in 0..50) { + list.add(Person(i, "Person $i")) + } + return list + } +} diff --git a/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/SwipeToDeleteList.kt b/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/SwipeToDeleteList.kt index 1c13892d..43fef3f1 100644 --- a/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/SwipeToDeleteList.kt +++ b/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/SwipeToDeleteList.kt @@ -1,8 +1,118 @@ package com.example.jetpack_compose_all_in_one.lessons.lesson_3 +import android.widget.Toast +import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Delete +import androidx.compose.material3.DismissDirection +import androidx.compose.material3.DismissValue +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.SwipeToDismiss +import androidx.compose.material3.Text +import androidx.compose.material3.rememberDismissState import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.scale +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel +@OptIn(ExperimentalMaterial3Api::class) @Composable -fun SwipeToDeleteScreen() { +fun SwipeToDeleteScreen(viewModel: SwipeToDeleteViewModel = hiltViewModel()) { + val personList = viewModel.personList.collectAsState() + val contextForToast = LocalContext.current.applicationContext + + LaunchedEffect(key1 = true) { + viewModel.getPersonList() + } + LazyColumn( + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues(vertical = 12.dp) + ) { + items( + items = personList.value, + key = { person -> + person.id + } + ) { person -> + val dismissState = rememberDismissState() + + if (dismissState.isDismissed(direction = DismissDirection.EndToStart)) { + viewModel.deletePerson(person) + Toast.makeText(contextForToast, "Deleted ${person.name}", Toast.LENGTH_SHORT).show() + } + SwipeToDismiss( + state = dismissState, + directions = setOf( + DismissDirection.EndToStart + ), + background = { + val backgroundColor by animateColorAsState( + when (dismissState.targetValue) { + DismissValue.DismissedToStart -> Color.Red.copy(alpha = 0.8f) + else -> Color.White + }, label = "Swipe to delete background color" + ) + + val iconImageVector = Icons.Outlined.Delete + + val iconAlignment = Alignment.CenterEnd + + val iconScale by animateFloatAsState( + targetValue = if (dismissState.targetValue == DismissValue.Default) 0.5f else 1.3f, + label = "" + ) + + Box( + Modifier + .fillMaxSize() + .background(color = backgroundColor) + .padding(start = 16.dp, end = 16.dp), + contentAlignment = iconAlignment + ) { + Icon( + modifier = Modifier.scale(iconScale), + imageVector = iconImageVector, + contentDescription = null, + tint = Color.White + ) + } + }, + dismissContent = { + Column( + modifier = Modifier + .fillMaxWidth() + .background(color = Color.White) + ) { + Text( + text = person.name, + fontSize = 20.sp, + modifier = Modifier + .fillMaxSize() + .padding(top = 16.dp, bottom = 16.dp, start = 12.dp) + ) + } + } + ) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/SwipeToDeleteViewModel.kt b/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/SwipeToDeleteViewModel.kt index 1bc518e4..9f382aae 100644 --- a/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/SwipeToDeleteViewModel.kt +++ b/app/src/main/java/com/example/jetpack_compose_all_in_one/lessons/lesson_3/SwipeToDeleteViewModel.kt @@ -1,7 +1,27 @@ package com.example.jetpack_compose_all_in_one.lessons.lesson_3 import androidx.lifecycle.ViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import javax.inject.Inject -class SwipeToDeleteViewModel : ViewModel() { +@HiltViewModel +class SwipeToDeleteViewModel @Inject constructor(private val personRepository: PersonRepository) : + ViewModel() { + + private val _personList = MutableStateFlow>(listOf()) + val personList = _personList.asStateFlow() + + + fun getPersonList() { + _personList.value = personRepository.getPersonList() + } + + fun deletePerson(person: Person) { + val list = _personList.value.toMutableList() + list.remove(person) + _personList.value = list + } } \ No newline at end of file