我用Jetpack Compose创建了一个口袋妖怪应用程序。我有两个屏幕。一个屏幕显示口袋妖怪的名字,另一个屏幕显示选定口袋妖怪的详细信息。我想实现的是,在选定口袋妖怪后,将其名称传递到url,并将信息显示在第二个屏幕上。
const val POKE_DETAILS = "api/v2/pokemon/{name}/"
网络文件
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)
}
合成屏幕
@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")
}
}
}
}
详细信息屏幕
@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
)
}
}
主要活动
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)
}
}
}
}
}
这对我来说还是很新鲜。欢迎提出任何建议。谢谢
使现代化
我已经创建了一个导航组件,但我不知道在详细信息屏幕中在哪里传递Pokemoname字符串值
*如果你想测试一些东西,这里有一份项目副本。
https://drive.google.com/drive/folders/1gLH_Q3jYLhn-6ad0LMBeZHb8HyT8FszC?usp=sharing