From 5610e46a3fb5a78f96e80108b356b0d9d89630e5 Mon Sep 17 00:00:00 2001 From: FirephoenixX02 Date: Fri, 12 Apr 2024 13:08:05 +0200 Subject: [PATCH] Fix stupid layout, make the details screen scrollable and look better --- .../src/commonMain/kotlin/DetailScreen.kt | 174 +++++++++--------- .../src/commonMain/kotlin/PokemonStatCard.kt | 62 +++++++ 2 files changed, 144 insertions(+), 92 deletions(-) create mode 100644 composeApp/src/commonMain/kotlin/PokemonStatCard.kt diff --git a/composeApp/src/commonMain/kotlin/DetailScreen.kt b/composeApp/src/commonMain/kotlin/DetailScreen.kt index 9b0afff..43bf8a3 100644 --- a/composeApp/src/commonMain/kotlin/DetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/DetailScreen.kt @@ -1,23 +1,21 @@ -import androidx.compose.foundation.Canvas import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize +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.shape.RoundedCornerShape +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material.Button -import androidx.compose.material.ButtonColors import androidx.compose.material.ButtonDefaults -import androidx.compose.material.Icon +import androidx.compose.material.Card +import androidx.compose.material.MaterialTheme import androidx.compose.material.Text -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 @@ -26,13 +24,7 @@ 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.drawscope.Stroke -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.navigator.LocalNavigator @@ -58,9 +50,9 @@ data class DetailScreen( LaunchedEffect(Unit) { pokemonData = withContext(Dispatchers.IO) { - fetchPokemonDetails(); + fetchPokemonDetails() } - dataLoaded = true; + dataLoaded = true } if (!dataLoaded) { @@ -69,12 +61,6 @@ data class DetailScreen( contentAlignment = Alignment.Center ) { Text("Fetching Data from API...") - } - } else { - Box( - modifier = Modifier.background(color = Color.White).fillMaxSize(), - contentAlignment = Alignment.Center - ) { //Back Button Button( onClick = { navigator.popAll(); navigator.push(HomeScreen()) }, @@ -85,86 +71,90 @@ data class DetailScreen( ) { 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 - ) - } - //Details - Box( - modifier = Modifier.size(256.dp).padding(5.dp), - 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), + } + } else { + Column( + modifier = Modifier.background(color = Color.White).fillMaxSize().padding(16.dp) + .verticalScroll(rememberScrollState()), + verticalArrangement = Arrangement.Top, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Box(modifier = Modifier.align(Alignment.Start)) { + //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()) - ) - } - 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 - ) + Text("Home") } } - //Stats + Progress Bars - Box( - modifier = Modifier.size(512.dp).padding(5.dp), - contentAlignment = Alignment.Center - ) { + // Image + KamelImage( + resource = asyncPainterResource(pokemon.imageUrl), + modifier = Modifier.size(256.dp), + contentDescription = "", + alignment = Alignment.Center + ) + + Spacer(modifier = Modifier.height(16.dp)) + + // Details card + Card( + modifier = Modifier.background(color = Color.White).fillMaxWidth() + ) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + detailRow("Name:", pokemonData?.name ?: "") + detailRow("Type:", pokemonData?.type?.capitalize() ?: "") + detailRow("Base XP:", pokemonData?.baseExperience.toString()) + detailRow("Height:", pokemonData?.height.toString()) + detailRow("Weight:", pokemonData?.weight.toString()) + } } + + Spacer(modifier = Modifier.height(16.dp)) + + // Stat card + PokemonStatCard( + hp = pokemonData?.hp ?: 0, + attack = pokemonData?.attack ?: 0, + defense = pokemonData?.defense ?: 0, + specialAttack = pokemonData?.specialAttack ?: 0, + specialDefense = pokemonData?.specialDefense ?: 0, + speed = pokemonData?.speed ?: 0 + ) } } } - //Leave suspend - suspend fun fetchPokemonDetails(): PokemonData { + private 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) + return PokemonData.fromJson(json) } -} \ No newline at end of file +} + +@Composable +private fun detailRow(statName: String, value: String) { + Row( + verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth() + ) { + Text( + text = statName, + modifier = Modifier.weight(1f), + style = MaterialTheme.typography.body1 // Adjust text style as needed + ) + Text( + text = value, + modifier = Modifier.weight(1f), + style = MaterialTheme.typography.body1 // Adjust text style as needed + ) + } +} diff --git a/composeApp/src/commonMain/kotlin/PokemonStatCard.kt b/composeApp/src/commonMain/kotlin/PokemonStatCard.kt new file mode 100644 index 0000000..3a4d42e --- /dev/null +++ b/composeApp/src/commonMain/kotlin/PokemonStatCard.kt @@ -0,0 +1,62 @@ + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +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.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.LinearProgressIndicator +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp + +@Composable +fun PokemonStatCard( + hp: Int, + attack: Int, + defense: Int, + specialAttack: Int, + specialDefense: Int, + speed: Int +) { + Column( + modifier = Modifier + .background(color = Color.White, shape = RoundedCornerShape(8.dp)) + .padding(16.dp), + verticalArrangement = Arrangement.Bottom, + ) { + StatRow("HP", hp, Color.Green) + StatRow("Attack", attack, Color.Red) + StatRow("Defense", defense, Color.Gray) + StatRow("Special Attack", specialAttack, Color.Yellow) + StatRow("Special Defense", specialDefense, Color.LightGray) + StatRow("Speed", speed, Color.Cyan) + } +} + +@Composable +private fun StatRow(statName: String, progress: Int, color: Color) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + Text( + text = "$statName: $progress", + modifier = Modifier.weight(1f), + style = MaterialTheme.typography.body1 + ) + Spacer(modifier = Modifier.width(16.dp)) + LinearProgressIndicator( + progress = progress / 200f, + modifier = Modifier.weight(2f), + color = color, + ) + } +}