Fix stupid layout, make the details screen scrollable and look better
This commit is contained in:
parent
5bf418db58
commit
5610e46a3f
2 changed files with 144 additions and 92 deletions
|
|
@ -1,23 +1,21 @@
|
||||||
import androidx.compose.foundation.Canvas
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
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.Button
|
||||||
import androidx.compose.material.ButtonColors
|
|
||||||
import androidx.compose.material.ButtonDefaults
|
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.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.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
|
@ -26,13 +24,7 @@ import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
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.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 androidx.compose.ui.unit.dp
|
||||||
import cafe.adriel.voyager.core.screen.Screen
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
|
|
@ -58,9 +50,9 @@ data class DetailScreen(
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
pokemonData = withContext(Dispatchers.IO) {
|
pokemonData = withContext(Dispatchers.IO) {
|
||||||
fetchPokemonDetails();
|
fetchPokemonDetails()
|
||||||
}
|
}
|
||||||
dataLoaded = true;
|
dataLoaded = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dataLoaded) {
|
if (!dataLoaded) {
|
||||||
|
|
@ -69,12 +61,6 @@ data class DetailScreen(
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
Text("Fetching Data from API...")
|
Text("Fetching Data from API...")
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier.background(color = Color.White).fillMaxSize(),
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
//Back Button
|
//Back Button
|
||||||
Button(
|
Button(
|
||||||
onClick = { navigator.popAll(); navigator.push(HomeScreen()) },
|
onClick = { navigator.popAll(); navigator.push(HomeScreen()) },
|
||||||
|
|
@ -85,86 +71,90 @@ data class DetailScreen(
|
||||||
) {
|
) {
|
||||||
Text("Home")
|
Text("Home")
|
||||||
}
|
}
|
||||||
//Details
|
}
|
||||||
Column(
|
} else {
|
||||||
modifier = Modifier.fillMaxSize(),
|
Column(
|
||||||
verticalArrangement = Arrangement.Top,
|
modifier = Modifier.background(color = Color.White).fillMaxSize().padding(16.dp)
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
.verticalScroll(rememberScrollState()),
|
||||||
) {
|
verticalArrangement = Arrangement.Top,
|
||||||
KamelImage(
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
resource = asyncPainterResource(pokemon.imageUrl),
|
) {
|
||||||
modifier = Modifier.size(256.dp),
|
Box(modifier = Modifier.align(Alignment.Start)) {
|
||||||
contentDescription = "",
|
//Back Button
|
||||||
alignment = Alignment.Center
|
Button(
|
||||||
)
|
onClick = { navigator.popAll(); navigator.push(HomeScreen()) },
|
||||||
}
|
modifier = Modifier.align(Alignment.TopStart),
|
||||||
//Details
|
colors = ButtonDefaults.buttonColors(
|
||||||
Box(
|
backgroundColor = orange, contentColor = Color.White
|
||||||
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),
|
|
||||||
)
|
)
|
||||||
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(
|
Text("Home")
|
||||||
"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
|
|
||||||
) {
|
|
||||||
|
|
||||||
|
// 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
|
private suspend fun fetchPokemonDetails(): PokemonData {
|
||||||
suspend fun fetchPokemonDetails(): PokemonData {
|
|
||||||
val apiString = "https://pokeapi.co/api/v2/pokemon/${pokemon.name.lowercase()}"
|
val apiString = "https://pokeapi.co/api/v2/pokemon/${pokemon.name.lowercase()}"
|
||||||
val json = JSONObject(URL(apiString).readText())
|
val json = JSONObject(URL(apiString).readText())
|
||||||
return PokemonData.fromJson(json)
|
return PokemonData.fromJson(json)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
62
composeApp/src/commonMain/kotlin/PokemonStatCard.kt
Normal file
62
composeApp/src/commonMain/kotlin/PokemonStatCard.kt
Normal file
|
|
@ -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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue