Add Loading Screen for DetailScreen
This commit is contained in:
parent
e58cb76df9
commit
8be471dc84
3 changed files with 178 additions and 97 deletions
|
|
@ -37,6 +37,27 @@ import java.util.Locale
|
|||
|
||||
var pokemap = ArrayList<Pokemon>()
|
||||
val apiString = "https://pokeapi.co/api/v2/pokemon/"
|
||||
@OptIn(ExperimentalResourceApi::class)
|
||||
val pokemonTypeDrawableMap = hashMapOf(
|
||||
"normal" to Res.drawable.normal,
|
||||
"fire" to Res.drawable.fire,
|
||||
"water" to Res.drawable.water,
|
||||
"electric" to Res.drawable.electric,
|
||||
"grass" to Res.drawable.grass,
|
||||
"ice" to Res.drawable.ice,
|
||||
"fighting" to Res.drawable.fighting,
|
||||
"poison" to Res.drawable.poison,
|
||||
"ground" to Res.drawable.ground,
|
||||
"flying" to Res.drawable.flying,
|
||||
"psychic" to Res.drawable.psychic,
|
||||
"bug" to Res.drawable.bug,
|
||||
"rock" to Res.drawable.rock,
|
||||
"ghost" to Res.drawable.ghost,
|
||||
"dragon" to Res.drawable.dragon,
|
||||
"dark" to Res.drawable.dark,
|
||||
"steel" to Res.drawable.steel,
|
||||
"fairy" to Res.drawable.fairy
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalResourceApi::class)
|
||||
@Composable
|
||||
|
|
@ -44,27 +65,6 @@ val apiString = "https://pokeapi.co/api/v2/pokemon/"
|
|||
fun App() {
|
||||
var dataLoaded by remember { mutableStateOf(false) }
|
||||
|
||||
val pokemonTypeDrawableMap = hashMapOf(
|
||||
"normal" to Res.drawable.normal,
|
||||
"fire" to Res.drawable.fire,
|
||||
"water" to Res.drawable.water,
|
||||
"electric" to Res.drawable.electric,
|
||||
"grass" to Res.drawable.grass,
|
||||
"ice" to Res.drawable.ice,
|
||||
"fighting" to Res.drawable.fighting,
|
||||
"poison" to Res.drawable.poison,
|
||||
"ground" to Res.drawable.ground,
|
||||
"flying" to Res.drawable.flying,
|
||||
"psychic" to Res.drawable.psychic,
|
||||
"bug" to Res.drawable.bug,
|
||||
"rock" to Res.drawable.rock,
|
||||
"ghost" to Res.drawable.ghost,
|
||||
"dragon" to Res.drawable.dragon,
|
||||
"dark" to Res.drawable.dark,
|
||||
"steel" to Res.drawable.steel,
|
||||
"fairy" to Res.drawable.fairy
|
||||
)
|
||||
|
||||
MaterialTheme {
|
||||
if (!dataLoaded) {
|
||||
Navigator(screen = LoadingScreen()) {
|
||||
|
|
@ -87,7 +87,7 @@ fun App() {
|
|||
} else {
|
||||
println("Pokemon should show up any second!")
|
||||
//Display Pokemon Grid
|
||||
Navigator(screen = HomeScreen(getPokeMap(), pokemonTypeDrawableMap)) {
|
||||
Navigator(screen = HomeScreen()) {
|
||||
navigator -> SlideTransition(navigator)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,15 +19,17 @@ import androidx.compose.material.icons.Icons
|
|||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.CornerRadius
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.PaintingStyle.Companion.Stroke
|
||||
import androidx.compose.ui.graphics.PathEffect
|
||||
import androidx.compose.ui.graphics.drawscope.DrawStyle
|
||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
|
|
@ -39,7 +41,6 @@ import io.kamel.image.KamelImage
|
|||
import io.kamel.image.asyncPainterResource
|
||||
import org.json.JSONObject
|
||||
import java.net.URL
|
||||
import java.util.Locale
|
||||
|
||||
data class DetailScreen(
|
||||
val pokemon: Pokemon
|
||||
|
|
@ -49,86 +50,118 @@ data class DetailScreen(
|
|||
override fun Content() {
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
val orange = Color(0xFFffa500)
|
||||
val apiString = "https://pokeapi.co/api/v2/pokemon/"
|
||||
val json = JSONObject(URL(apiString + pokemon.name.lowercase()).readText());
|
||||
val type: String =
|
||||
json.getJSONArray("types").optJSONObject(0).optJSONObject("type").optString("name")
|
||||
val name: String = json.optString("name")
|
||||
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
|
||||
val xp: String = json.optString("base_experience")
|
||||
val height: String = json.optString("height")
|
||||
val weight: String = json.optString("weight")
|
||||
Box(
|
||||
modifier = Modifier.background(color = Color.White).fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
//Back Button
|
||||
Button(onClick = { navigator.pop() }, modifier = Modifier.align(Alignment.TopStart), colors = ButtonDefaults.buttonColors(backgroundColor = orange, contentColor = Color.White)) {
|
||||
Text("Back")
|
||||
}
|
||||
//Details
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Top,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
KamelImage(
|
||||
resource = asyncPainterResource(pokemon.imageUrl),
|
||||
modifier = Modifier.size(256.dp),
|
||||
contentDescription = "",
|
||||
alignment = Alignment.Center
|
||||
)
|
||||
var dataLoaded by remember { mutableStateOf(false) }
|
||||
|
||||
var pokemonData by remember { mutableStateOf<PokemonData?>(null) }
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
pokemonData = fetchPokemonDetails();
|
||||
dataLoaded = true;
|
||||
}
|
||||
|
||||
LaunchedEffect(dataLoaded, this) {
|
||||
if (dataLoaded) {
|
||||
navigator.push(this@DetailScreen)
|
||||
}
|
||||
}
|
||||
|
||||
if (!dataLoaded) {
|
||||
navigator.push(LoadingScreen())
|
||||
} else {
|
||||
Box(
|
||||
modifier = Modifier.size(256.dp).padding(5.dp), contentAlignment = Alignment.Center
|
||||
modifier = Modifier.background(color = Color.White).fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Canvas(modifier = Modifier.matchParentSize()) {
|
||||
drawRoundRect(
|
||||
color = Color.White,
|
||||
topLeft = Offset(0f, 0f),
|
||||
size = Size(size.width, size.height),
|
||||
cornerRadius = CornerRadius(20f, 20f),
|
||||
//Back Button
|
||||
Button(
|
||||
onClick = { navigator.popAll(); navigator.push(HomeScreen()) },
|
||||
modifier = Modifier.align(Alignment.TopStart),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
backgroundColor = orange, contentColor = Color.White
|
||||
)
|
||||
drawRoundRect(
|
||||
color = Color.Black,
|
||||
topLeft = Offset(0f, 0f),
|
||||
size = Size(size.width, size.height),
|
||||
cornerRadius = CornerRadius(20f, 20f),
|
||||
style = Stroke(1.dp.toPx())
|
||||
) {
|
||||
Text("Home")
|
||||
}
|
||||
//Details
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Top,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
KamelImage(
|
||||
resource = asyncPainterResource(pokemon.imageUrl),
|
||||
modifier = Modifier.size(256.dp),
|
||||
contentDescription = "",
|
||||
alignment = Alignment.Center
|
||||
)
|
||||
}
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.padding(16.dp)
|
||||
//Details
|
||||
Box(
|
||||
modifier = Modifier.size(256.dp).padding(5.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
"Name: $name",
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Text(
|
||||
"Type: $type",
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Text(
|
||||
"Base XP: $xp",
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Text(
|
||||
"Height: $height",
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Text(
|
||||
"Weight: ${weight}kg",
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Canvas(modifier = Modifier.matchParentSize()) {
|
||||
drawRoundRect(
|
||||
color = Color.White,
|
||||
topLeft = Offset(0f, 0f),
|
||||
size = Size(size.width, size.height),
|
||||
cornerRadius = CornerRadius(20f, 20f),
|
||||
)
|
||||
drawRoundRect(
|
||||
color = Color.Black,
|
||||
topLeft = Offset(0f, 0f),
|
||||
size = Size(size.width, size.height),
|
||||
cornerRadius = CornerRadius(20f, 20f),
|
||||
style = Stroke(1.dp.toPx())
|
||||
)
|
||||
}
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.padding(16.dp)
|
||||
) {
|
||||
Text(
|
||||
"Name: ${pokemonData?.name}",
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Text(
|
||||
"Type: ${pokemonData?.type}",
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Text(
|
||||
"Base XP: ${pokemonData?.baseExperience}",
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Text(
|
||||
"Height: ${pokemonData?.height}",
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Text(
|
||||
"Weight: ${pokemonData?.weight}kg",
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
}
|
||||
}
|
||||
//Stats + Progress Bars
|
||||
Box(
|
||||
modifier = Modifier.size(512.dp).padding(5.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Leave suspend
|
||||
suspend fun fetchPokemonDetails(): PokemonData {
|
||||
val apiString = "https://pokeapi.co/api/v2/pokemon/${pokemon.name.lowercase()}"
|
||||
val json = JSONObject(URL(apiString).readText())
|
||||
return PokemonData.fromJson(json)
|
||||
}
|
||||
}
|
||||
48
composeApp/src/commonMain/kotlin/PokemonData.kt
Normal file
48
composeApp/src/commonMain/kotlin/PokemonData.kt
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import org.json.JSONObject
|
||||
import java.util.Locale
|
||||
|
||||
data class PokemonData(
|
||||
val name: String,
|
||||
val type: String,
|
||||
val baseExperience: Int,
|
||||
val height: Int, // Height in decimetres
|
||||
val weight: Int, // Weight in hectograms
|
||||
val hp: Int,
|
||||
val attack: Int,
|
||||
val defense: Int,
|
||||
val specialAttack: Int,
|
||||
val specialDefense: Int,
|
||||
val speed: Int
|
||||
) {
|
||||
companion object {
|
||||
fun fromJson(json: JSONObject): PokemonData {
|
||||
val name = json.optString("name")
|
||||
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
|
||||
val type = json.getJSONArray("types").optJSONObject(0).optJSONObject("type")
|
||||
.optString("name")
|
||||
val baseExperience = json.optInt("base_experience")
|
||||
val height = json.optInt("height")
|
||||
val weight = json.optInt("weight")
|
||||
val hp = json.getJSONArray("stats").optJSONObject(0).optInt("base_stat")
|
||||
val attack = json.getJSONArray("stats").optJSONObject(1).optInt("base_stat")
|
||||
val defense = json.getJSONArray("stats").optJSONObject(2).optInt("base_stat")
|
||||
val specialAttack = json.getJSONArray("stats").optJSONObject(3).optInt("base_stat")
|
||||
val specialDefense = json.getJSONArray("stats").optJSONObject(4).optInt("base_stat")
|
||||
val speed = json.getJSONArray("stats").optJSONObject(5).optInt("base_stat")
|
||||
|
||||
return PokemonData(
|
||||
name = name,
|
||||
type = type,
|
||||
baseExperience = baseExperience,
|
||||
height = height,
|
||||
weight = weight,
|
||||
hp = hp,
|
||||
attack = attack,
|
||||
defense = defense,
|
||||
specialAttack = specialAttack,
|
||||
specialDefense = specialDefense,
|
||||
speed = speed
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue