Last active
June 14, 2024 08:43
-
-
Save ioannisa/2f674098e20da5f0ef0747b529b129a6 to your computer and use it in GitHub Desktop.
Jetpack Navigation passing Parcelables through backstack's savedState handle (old way)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package eu.anifantakis.composeapp | |
import android.os.Bundle | |
import android.os.Parcelable | |
import androidx.activity.ComponentActivity | |
import androidx.activity.compose.setContent | |
import androidx.compose.foundation.ExperimentalFoundationApi | |
import androidx.compose.foundation.Image | |
import androidx.compose.foundation.background | |
import androidx.compose.foundation.clickable | |
import androidx.compose.foundation.layout.Column | |
import androidx.compose.foundation.layout.Row | |
import androidx.compose.foundation.layout.Spacer | |
import androidx.compose.foundation.layout.fillMaxWidth | |
import androidx.compose.foundation.layout.height | |
import androidx.compose.foundation.layout.padding | |
import androidx.compose.foundation.layout.size | |
import androidx.compose.foundation.layout.width | |
import androidx.compose.foundation.lazy.LazyColumn | |
import androidx.compose.foundation.lazy.items | |
import androidx.compose.material3.Button | |
import androidx.compose.material3.Card | |
import androidx.compose.material3.CardDefaults | |
import androidx.compose.material3.MaterialTheme | |
import androidx.compose.material3.Surface | |
import androidx.compose.material3.Text | |
import androidx.compose.runtime.Composable | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.graphics.Color | |
import androidx.compose.ui.layout.ContentScale | |
import androidx.compose.ui.unit.dp | |
import androidx.navigation.NavController | |
import androidx.navigation.compose.NavHost | |
import androidx.navigation.compose.composable | |
import androidx.navigation.compose.rememberNavController | |
import coil.compose.rememberAsyncImagePainter | |
import eu.anifantakis.composeapp.ui.theme.ComposeAppTheme | |
import kotlinx.parcelize.Parcelize | |
import java.net.URLDecoder | |
import java.net.URLEncoder | |
import java.nio.charset.StandardCharsets | |
// =========================[ NOTE ]========================= | |
// add Coil for Jetpack Compose at your app dependencies | |
// implementation("io.coil-kt:coil-compose:2.6.0") | |
// | |
// Add Parcelize plugin at app module's build.gradle | |
// id("kotlin-parcelize") | |
// ========================================================== | |
// define a simple data class to hold Person information | |
@Parcelize | |
data class Person( | |
val id: Int, | |
val section: Int, | |
val name: String, | |
val imageUrl: String, | |
val landingPage: String | |
): Parcelable | |
class MainActivity : ComponentActivity() { | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
val persons = arrayListOf<Person>() // create an array list of persons | |
var section = 1 | |
for (i in 1..200){ // create 200 Person instances in that list | |
if (i%15 == 0){ | |
section++ | |
} | |
persons.add( | |
Person( | |
id = i, | |
section = section, // all persons are assigned section | |
name = "Ioannis Anifantakis", | |
imageUrl = URLEncoder.encode("https://anifantakis.eu/wp-content/uploads/2021/05/ioannis-anifantakis-firebase-small.jpg", StandardCharsets.UTF_8.toString()), | |
landingPage = URLEncoder.encode("https://anifantakis.eu", StandardCharsets.UTF_8.toString()) | |
) | |
) | |
} | |
setContent { | |
ComposeAppTheme { | |
// A surface container using the 'background' color from the theme | |
Surface(color = MaterialTheme.colorScheme.background) { | |
Navigation(persons) | |
} | |
} | |
} | |
} | |
} | |
@Composable | |
fun Navigation(persons: List<Person>) { | |
val navController = rememberNavController() | |
NavHost(navController = navController, startDestination = "main_screen" ) { | |
composable("main_screen") { MainScreen(persons, navController) } | |
composable("detail_screen") { | |
val person = navController.previousBackStackEntry?.savedStateHandle?.get<Person>("person") | |
person?.let { | |
DetailScreen(navController, it) | |
} | |
} | |
} | |
} | |
@Composable | |
fun ImageLoader(imageUrl: String){ | |
Image( | |
painter = rememberAsyncImagePainter(imageUrl), | |
contentDescription = null, | |
contentScale = ContentScale.Crop, | |
modifier = Modifier.size(120.dp) | |
) | |
} | |
@Composable | |
fun ListItem(person: Person, navController: NavController){ | |
Card( | |
modifier = Modifier | |
.padding(8.dp) | |
.fillMaxWidth() | |
.clickable { | |
navController.currentBackStackEntry?.savedStateHandle?.set("person", person) | |
navController.navigate("detail_screen") | |
}, | |
elevation = CardDefaults.cardElevation(), | |
) { | |
Row{ | |
ImageLoader(URLDecoder.decode(person.imageUrl, StandardCharsets.UTF_8.toString())) | |
Spacer(modifier = Modifier.width(8.dp)) | |
Text( | |
person.name+' '+person.id, | |
style = MaterialTheme.typography.headlineMedium, | |
modifier = Modifier.padding(8.dp) | |
) | |
} | |
} | |
} | |
@Composable | |
fun DetailScreen(navController: NavController, person: Person) { | |
Card ( | |
modifier = Modifier.padding(12.dp), | |
elevation = CardDefaults.cardElevation(), | |
){ | |
Column( | |
modifier = Modifier | |
.padding(16.dp) | |
.fillMaxWidth() | |
) { | |
Text("section ${person.section}", style = MaterialTheme.typography.headlineMedium) | |
Text("${person.name} ${person.id}", style = MaterialTheme.typography.headlineSmall) | |
Spacer(modifier = Modifier.height(8.dp)) | |
ImageLoader(person.imageUrl) | |
Spacer(modifier = Modifier.height(8.dp)) | |
Button(onClick = { navController.popBackStack() }) { | |
Text("Go Back") | |
} | |
} | |
} | |
} | |
@OptIn(ExperimentalFoundationApi::class) | |
@Composable | |
fun MainScreen(persons: List<Person>, navController: NavController){ | |
val grouped = persons.groupBy{it.section} | |
LazyColumn(){ | |
grouped.forEach { (section, sectionPersons) -> | |
stickyHeader { | |
Text( | |
text = "SECTION: $section", | |
color = Color.White, | |
modifier = Modifier | |
.background(color = Color.Black) | |
.padding(8.dp) | |
.fillMaxWidth() | |
) | |
} | |
items( | |
items = sectionPersons, | |
itemContent = { | |
ListItem(it, navController) | |
} | |
) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment