class StratagemListActivity : ComponentActivity() {
private val viewModel by lazy {
ViewModelProvider(
this, StratagemViewModel.StratagemViewModelFactory()
)[StratagemViewModel::class.java]
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
viewModel.getStratagem()
setContent {
HellDivers2InfoTheme {
Surface(
modifier = Modifier.fillMaxSize()
) {
StratagemListScreen(viewModel)
}
}
}
}
@Composable
fun StratagemListScreen(viewModel: StratagemViewModel) {
val stratagemList by viewModel.stratagem.observeAsState()
when {
stratagemList?.isEmpty() == true -> LoadingScreen()
else -> stratagemList?.get(0)?.data?.let { it -> StratagemList(it.map { it.name }) }
}
}
@Composable
fun StratagemData(viewModel: StratagemViewModel, index: Int = 0) {
val stratagemList by viewModel.stratagem.observeAsState()
when {
stratagemList?.isEmpty() == true -> LoadingScreen()
else -> stratagemList?.get(0)?.data?.get(index).let {
if (it != null) {
StratagemDataListItem(it)
}
}
}
}
@Composable
fun StratagemDataListItem(item: StratagemResponse.Data) {
Spacer(modifier = Modifier.height(8.dp))
Text(text = "호출 시간: " + item.activation.toString())
Spacer(modifier = Modifier.height(4.dp))
Text(text = "쿨타임: " + item.cooldown.toString())
Spacer(modifier = Modifier.height(4.dp))
Row {
Text(text = "호출 키: ")
for (i in item.keys.indices) {
when (item.keys[i]) {
"down" -> {
Icon(
imageVector = Icons.Filled.KeyboardArrowDown,
contentDescription = stringResource(id = R.string.down)
)
}
"up" -> {
Icon(
imageVector = Icons.Filled.KeyboardArrowUp,
contentDescription = stringResource(id = R.string.up)
)
}
"left" -> {
Icon(
imageVector = Icons.AutoMirrored.Filled.KeyboardArrowLeft,
contentDescription = stringResource(id = R.string.left)
)
}
"right" -> {
Icon(
imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight,
contentDescription = stringResource(id = R.string.right)
)
}
}
}
}
}
@Composable
fun StratagemList(names: List<String>) {
LazyColumn(
modifier = Modifier
.padding(vertical = 34.dp, horizontal = 8.dp)
) {
itemsIndexed(names) { index, name ->
StratagemItem(name, index)
Spacer(modifier = Modifier.height(8.dp))
}
}
}
@Composable
private fun StratagemItem(name: String, index: Int = 0) {
var expanded by rememberSaveable { mutableStateOf(false) }
Row(
modifier = Modifier
.background(Color(0xFFFFE4E4))
.padding(12.dp)
.animateContentSize(
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessLow
)
)
) {
Column(
modifier = Modifier
.weight(1f)
.padding(12.dp)
) {
Text(
text = name,
style = MaterialTheme.typography.headlineMedium.copy(
fontWeight = FontWeight.Bold
)
)
if (expanded) {
StratagemData(viewModel, index)
}
}
IconButton(onClick = { expanded = !expanded }) {
Icon(
imageVector = if (expanded) {
Icons.Filled.KeyboardArrowUp
} else Icons.Filled.KeyboardArrowDown,
contentDescription = if (expanded) {
stringResource(id = R.string.show_less)
} else {
stringResource(id = R.string.show_more)
}
)
}
}
}
@Composable
fun LoadingScreen() {}
무료 API를 이용해 간단한 리스트를 만들어 보았다. 이전 Compose 테스트에서는 없었던 클릭 이벤트와 실제 데이터 사용을 추가했다.
@Composable
fun StratagemData(viewModel: StratagemViewModel, index: Int = 0) {
val stratagemList by viewModel.stratagem.observeAsState()
when {
stratagemList?.isEmpty() == true -> LoadingScreen()
else -> stratagemList?.get(0)?.data?.get(index).let {
if (it != null) {
StratagemDataListItem(it)
}
}
}
}
기본적으로 데이터를 불러오는 작업과 UI 구성이 (거의)동시에 일어나기 때문에, 미처 데이터 값을 불러오지 못할 가능성이 있었다. 그래서 리스트의 값을 확인하는 로직과 LoadingScreen() (아직은 빈 화면) 을 추가했다. 이렇게 하면 데이터 로딩과 UI 렌더링이 더 안정적으로 처리될 것이다.
itemsIndexed(names) { index, name ->
StratagemItem(name, index)
Spacer(modifier = Modifier.height(8.dp))
}
itemsIndexed 함수를 사용해 indexOf를 사용할 때보다 더 효율적이고 직관적으로 인덱스를 가져올 수 있다.
'TIL' 카테고리의 다른 글
TIL 74일차 - 최종프로젝트 (0) | 2024.07.04 |
---|---|
TIL 73일차 - 최종프로젝트 (0) | 2024.07.03 |
TIL 71일차 - 최종프로젝트 (0) | 2024.07.01 |
TIL 70일차 - 최종프로젝트 (0) | 2024.06.28 |
TIL 69일차 - 최종프로젝트 (0) | 2024.06.27 |