1 year ago
#371156
OEThe11
Passing a pokemon name to pull out it's information from an API Endpoint in Jetpack Compose Navigation
I have created a Pokemon App with Jetpack Compose. I have two screens. One where the names of the pokemon is being displayed, and a second screen where the details of a selected pokemon will be shown. What I want to achieve is passing the name of the pokemon to a url when it's selected, and getting the information on to the second screen.
const val POKE_DETAILS = "api/v2/pokemon/{name}/"
Network File
interface NetworkingService{
@GET(Endpoints.POKE_LIST)
suspend fun getListResponse(
@Query("limit") limit: String = "151"
): Response<GetPokemonListResponse>
@GET(Endpoints.POKE_DETAILS)
suspend fun getDetailsResponse(
@Path("name") name: String
): GetPokemonDetailResponse
}
object PokemonNetworkObject{
val moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build()
val retroFit: Retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
val networkingServices: NetworkingService by lazy {
retroFit.create(NetworkingService::class.java)
}
val apiClient = ApiClient(networkingServices)
}
Compose Screens
@Preview
@Composable
fun PokemonListPage(pokemonViewModel: PokemonListViewModel = viewModel(), navController: NavController){
val pokeList = pokemonViewModel.pokemonStateData.collectAsState().value
Surface(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(),
) {
Scaffold(topBar =
{
TopAppBar(
backgroundColor = Color.DarkGray,
elevation = 0.dp,
) {
Row(modifier = Modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
){
Text(
text = "POKEDEX",
fontWeight = FontWeight.Bold,
fontSize = 25.sp,
color = Color.Magenta
)
}
}
}, backgroundColor = Color.DarkGray){
PokemonCards(pokemons = pokeList!!, navController = navController))
}
// PokemonCards(pokemons = pokeList!!)
}
}
@Composable
private fun PokemonCards(pokemons: List<PokeListEntity>, navController: NavController) {
LazyColumn{
items(pokemons){ pokemon ->
PokemonCard(pokemon = pokemon, navController = navController)
}
}
}
@Composable
private fun PokemonCard(pokemon: PokeListEntity, navController: NavController) {
Card(
modifier = Modifier
.width(500.dp)
.requiredHeight(100.dp)
.padding(10.dp),
backgroundColor = Color.Cyan,
shape = RoundedCornerShape(corner = CornerSize(10.dp)),
elevation = 5.dp
) {
Row(
modifier = Modifier
.padding(start = 16.dp, end = 16.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = pokemon.name,
fontSize = 25.sp,
fontWeight = FontWeight.Bold
)
Button(
onClick = {
navController.navigate(route = "pokemon_detail_screen/${pokemon.name}")
}) {
Text(text = "INFO")
}
}
}
}
Details Screen
@Preview
@Composable
fun PokemonDetailScreen(
detailViewModel: DetailViewModel = viewModel(),
navController: NavController,
pokemonName: String // This Variable
) {
val details by detailViewModel.detailState.observeAsState()
Surface(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
color = Color.DarkGray
) {
DetailCard(field = details!!)
}
}
@Composable
private fun DetailCard(field: GetPokemonDetailResponse) {
Card(
modifier = Modifier
.requiredHeight(300.dp)
.fillMaxWidth()
.padding(10.dp),
backgroundColor = Color.Cyan,
shape = RoundedCornerShape(corner = CornerSize(15.dp)),
elevation = 10.dp
) {
Column(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth()
.padding(10.dp),
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally
) {
DetailFields("Name:", field = field.name)
Divider(thickness = 4.dp)
DetailFields("Height:", field = "${field.height}.in")
Divider(thickness = 4.dp)
DetailFields("Weight:", field = "${field.weight}.lbs")
}
}
}
@Composable
private fun DetailFields(title: String, field: String) {
Column() {
Text(
title,
fontSize = 20.sp
)
Text(
field,
fontSize = 30.sp,
fontWeight = FontWeight.Bold
)
}
}
MainActivity
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
PokeDexComposeTheme {
Surface(
modifier = Modifier.fillMaxSize()
) {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "pokemon_list_page"
) {
composable("pokemon_list_page") {
PokemonListPage(navController = navController)
}
composable(
"pokemon_detail_screen/{name}",
arguments = listOf(
navArgument("name") {
type = NavType.StringType
}
)
) {
// The navBackStackEntry contains the arguments
val pokemonName = remember {
it.arguments?.getString("name")
}
PokemonDetailScreen(
pokemonName = pokemonName?.lowercase() ?: "",
navController = navController)
}
}
// val pokeListViewModel = viewModel<PokemonListViewModel>()
// PokemonListPage(pokeListViewModel)
}
}
}
}
}
This is still pretty new to me. Any Suggestions are definitely welcomed. Thanks.
Update I have created a Navigation Component, but i don't know where to pass the pokemonName String value in the Details Screen
*Here is a copy of the project, if you want to test some things out. https://drive.google.com/drive/folders/1gLH_Q3jYLhn-6ad0LMBeZHb8HyT8FszC?usp=sharing
android
kotlin
android-jetpack-compose
jetpack-compose-navigation
0 Answers
Your Answer