Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1.2.0/ AN-UI, AN-FEAT] 배틀 날씨 효과 UI 변경 #487

Merged
merged 11 commits into from
Dec 27, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import poke.rogue.helper.databinding.ActivityBattleBinding
import poke.rogue.helper.presentation.base.toolbar.ToolbarActivity
import poke.rogue.helper.presentation.battle.model.SelectionData
import poke.rogue.helper.presentation.battle.model.WeatherUiModel
import poke.rogue.helper.presentation.battle.model.hasWeatherEffect
import poke.rogue.helper.presentation.battle.selection.BattleSelectionActivity
import poke.rogue.helper.presentation.battle.selection.pokemon.addPokemonTypes
import poke.rogue.helper.presentation.battle.view.itemSelectListener
Expand All @@ -26,7 +27,6 @@ import poke.rogue.helper.presentation.util.serializable
import poke.rogue.helper.presentation.util.view.dp
import poke.rogue.helper.presentation.util.view.setImage
import poke.rogue.helper.presentation.util.view.setOnSingleClickListener
import timber.log.Timber

class BattleActivity : ToolbarActivity<ActivityBattleBinding>(R.layout.activity_battle) {
private val viewModel by viewModel<BattleViewModel> {
Expand Down Expand Up @@ -75,19 +75,39 @@ class BattleActivity : ToolbarActivity<ActivityBattleBinding>(R.layout.activity_
}

private fun initObserver() {
observeWeathers()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

따로 분리하셨군요 굿 👍👍

observeWeatherPosition()
observeWeatherEffect()
observeSelectionState()
observeNavigationEvent()
observeBattleResult()
}

private fun observeWeathers() {
repeatOnStarted {
viewModel.weathers.collect {
weatherAdapter.updateWeathers(it)
}
}
}

private fun observeWeatherPosition() {
repeatOnStarted {
viewModel.weatherPos
.collect {
Timber.tag("weatherPos").d("weatherPos: $it")
binding.spinnerWeather.setSelection(it)
}
viewModel.weatherPos.collect {
binding.spinnerWeather.setSelection(it)
}
}
}

private fun observeWeatherEffect() {
repeatOnStarted {
viewModel.showWeatherEffect.collect {
binding.ivWeatherIcon.isSelected = it
}
}
}

private fun observeSelectionState() {
repeatOnStarted {
viewModel.selectedState.collect {
if (it.minePokemon is BattleSelectionUiState.Selected) {
Expand Down Expand Up @@ -122,11 +142,18 @@ class BattleActivity : ToolbarActivity<ActivityBattleBinding>(R.layout.activity_

if (it.weather is BattleSelectionUiState.Selected) {
val selected = it.weather.content
binding.tvWeatherDescription.text = selected.effect
binding.ivWeatherIcon.setImage(selected.icon.iconResId)

val hasEffect = selected.hasWeatherEffect()
binding.ivWeatherIcon.isEnabled = hasEffect
if (!hasEffect) viewModel.hideWeatherEffect()
binding.tvWeatherEffect.text = selected.effect
}
}
}
}

private fun observeNavigationEvent() {
repeatOnStarted {
viewModel.navigationEvent.collect { event ->
when (event) {
Expand All @@ -135,7 +162,9 @@ class BattleActivity : ToolbarActivity<ActivityBattleBinding>(R.layout.activity_
}
}
}
}

private fun observeBattleResult() {
repeatOnStarted {
viewModel.battleResult.collect {
if (it is BattleResultUiState.Success) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package poke.rogue.helper.presentation.battle

import android.view.View
import androidx.databinding.BindingAdapter

@BindingAdapter("animatedVisibility")
fun View.setAnimatedVisibility(visible: Boolean) {
if (visible) {
animate().alpha(1f).setDuration(200).withStartAction {
visibility = View.VISIBLE
}.start()
} else {
animate().alpha(0f).setDuration(200).withEndAction {
visibility = View.GONE
}.start()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ class BattleViewModel(
battleResult.map { it.isSuccess() }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), false)

private val _showWeatherEffect = MutableStateFlow(false)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weatherEffectIsShown 이 더 나을까요?
이것도 나쁘지 않은데,
이것을 사용하는 클라이언트 코드에서 볼 때 빌더 메서드가 아닌 조정자 메서드 같아 보였어요.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 동감합니다~ 근데 isShownWeatherEffect 이 어떠심? ㅋㅋㅋ

val showWeatherEffect = _showWeatherEffect.asStateFlow()

init {
initWeathers()
handlePokemonSelection(pokemonId, selectionType)
Expand Down Expand Up @@ -249,6 +252,14 @@ class BattleViewModel(
_navigationEvent.emit(NavigateToDetail(pokemonId))
}
}

fun toggleWeatherEffect() {
_showWeatherEffect.value = !_showWeatherEffect.value
}

fun hideWeatherEffect() {
_showWeatherEffect.value = false
}
}

sealed interface BattleNavigationEvent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ enum class WeatherIcon(
TURBULENCE(R.drawable.icon_air),
}

fun WeatherUiModel.hasWeatherEffect(): Boolean = effect.isNotBlank() && effect.isNotEmpty()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

isNotBlank() 만 해도 isNotEmpty 케이스를 커버한다고 알고 있습니다.


fun Weather.toUi(): WeatherUiModel {
val weatherIcon =
when (id) {
Expand Down
5 changes: 5 additions & 0 deletions android/app/src/main/res/drawable/bg_battle_description.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/poke_grey_70" />
<corners android:radius="4dp" />
</shape>
5 changes: 5 additions & 0 deletions android/app/src/main/res/drawable/selector_button_clicked.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_battle_description" android:state_selected="true" />
<item android:drawable="@drawable/bg_battle_default"/>
</selector>
89 changes: 73 additions & 16 deletions android/app/src/main/res/layout-land/activity_battle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,31 +68,35 @@
android:orientation="horizontal"
app:layout_constraintGuide_end="20dp" />

<ImageView
android:id="@+id/iv_weather_icon"
android:layout_width="54dp"
android:layout_height="0dp"
android:layout_marginEnd="12dp"
android:background="@drawable/selector_button_clicked"
android:clickable="true"
android:focusable="true"
android:onClick="@{() -> vm.toggleWeatherEffect()}"
android:paddingHorizontal="12dp"
android:paddingVertical="4dp"
app:layout_constraintBottom_toBottomOf="@id/spinner_weather"
app:layout_constraintEnd_toStartOf="@id/spinner_weather"
app:layout_constraintStart_toStartOf="@id/gl_start"
app:layout_constraintTop_toTopOf="@id/spinner_weather"
tools:src="@drawable/icon_foggy" />

<Spinner
android:id="@+id/spinner_weather"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/bg_spinner"
android:padding="0dp"
android:spinnerMode="dropdown"
app:layout_constraintBottom_toTopOf="@id/tv_weather_description"
app:layout_constraintEnd_toEndOf="@id/gl_end"
app:layout_constraintStart_toStartOf="@id/gl_start"
app:layout_constraintStart_toEndOf="@id/iv_weather_icon"
app:layout_constraintTop_toBottomOf="@id/gl_top"
tools:listitem="@layout/item_spinner_weather" />

<TextView
android:id="@+id/tv_weather_description"
style="@style/TextAppearance.Poke.CaptionLarge"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="end"
android:textStyle="italic"
app:layout_constraintEnd_toEndOf="@id/spinner_weather"
app:layout_constraintStart_toStartOf="@id/spinner_weather"
app:layout_constraintTop_toBottomOf="@id/spinner_weather" />

<TextView
android:id="@+id/tv_opponent_pokemon"
style="@style/TextAppearance.Poke.TitleBold"
Expand Down Expand Up @@ -148,7 +152,60 @@
android:layout_marginTop="16dp"
android:src="@drawable/icon_pokemon_selection_op"
app:layout_constraintEnd_toEndOf="@id/gl_end"
app:layout_constraintTop_toBottomOf="@id/tv_weather_description" />
app:layout_constraintTop_toBottomOf="@id/spinner_weather" />

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/weather_effect_container"
animatedVisibility="@{vm.showWeatherEffect}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:background="@drawable/bg_battle_description"
android:clickable="true"
android:elevation="8dp"
android:focusable="true"
android:orientation="vertical"
android:padding="12dp"
app:layout_constraintEnd_toEndOf="@id/gl_end"
app:layout_constraintStart_toStartOf="@id/gl_start"
app:layout_constraintTop_toBottomOf="@id/spinner_weather"
tools:visibility="visible">

<TextView
android:id="@+id/tv_weather_effect_title"
style="@style/TextAppearance.Poke.CaptionLargeBold"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/battle_weather_effect_title"
app:layout_constraintEnd_toStartOf="@id/btn_weather_description_close"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<ImageView
android:id="@+id/btn_weather_description_close"
android:layout_width="32dp"
android:layout_height="32dp"
android:onClick="@{() -> vm.hideWeatherEffect()}"
android:padding="4dp"
android:src="@drawable/icon_close"
app:layout_constraintBottom_toBottomOf="@id/tv_weather_effect_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tv_weather_effect_title"
app:layout_constraintTop_toTopOf="@id/tv_weather_effect_title" />

<TextView
android:id="@+id/tv_weather_effect"
style="@style/TextAppearance.Poke.CaptionLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_weather_effect_title"
tools:text="날씨 효과 적는 칸" />

</androidx.constraintlayout.widget.ConstraintLayout>

<com.google.android.flexbox.FlexboxLayout
android:id="@+id/flexbox_mine_types"
Expand Down Expand Up @@ -340,8 +397,8 @@
visible="@{vm.isBattleFetchSuccessful}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/battle_accuracy_title"
android:layout_marginVertical="8dp"
android:text="@string/battle_accuracy_title"
app:layout_constraintBottom_toBottomOf="@id/gl_bottom"
app:layout_constraintEnd_toEndOf="@id/tv_calculated_power_content"
app:layout_constraintStart_toStartOf="@id/tv_calculated_power_content"
Expand Down
90 changes: 74 additions & 16 deletions android/app/src/main/res/layout/activity_battle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,31 +64,35 @@
android:orientation="horizontal"
app:layout_constraintGuide_end="20dp" />

<ImageView
android:id="@+id/iv_weather_icon"
android:layout_width="54dp"
android:layout_height="0dp"
android:layout_marginEnd="12dp"
android:background="@drawable/selector_button_clicked"
android:clickable="true"
android:focusable="true"
android:onClick="@{() -> vm.toggleWeatherEffect()}"
android:paddingHorizontal="12dp"
android:paddingVertical="4dp"
app:layout_constraintBottom_toBottomOf="@id/spinner_weather"
app:layout_constraintEnd_toStartOf="@id/spinner_weather"
app:layout_constraintStart_toStartOf="@id/gl_start"
app:layout_constraintTop_toTopOf="@id/spinner_weather"
tools:src="@drawable/icon_foggy" />

<Spinner
android:id="@+id/spinner_weather"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/bg_spinner"
android:padding="0dp"
android:spinnerMode="dropdown"
app:layout_constraintBottom_toTopOf="@id/tv_weather_description"
app:layout_constraintEnd_toEndOf="@id/gl_end"
app:layout_constraintStart_toStartOf="@id/gl_start"
app:layout_constraintStart_toEndOf="@id/iv_weather_icon"
app:layout_constraintTop_toBottomOf="@id/gl_top"
tools:listitem="@layout/item_spinner_weather" />

<TextView
android:id="@+id/tv_weather_description"
style="@style/TextAppearance.Poke.CaptionLarge"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="end"
android:textStyle="italic"
app:layout_constraintEnd_toEndOf="@id/spinner_weather"
app:layout_constraintStart_toStartOf="@id/spinner_weather"
app:layout_constraintTop_toBottomOf="@id/spinner_weather" />

<TextView
android:id="@+id/tv_opponent_pokemon"
style="@style/TextAppearance.Poke.TitleBold"
Expand Down Expand Up @@ -142,10 +146,64 @@
onSingleClick="@{() -> vm.navigateToSelection(SelectionMode.POKEMON_ONLY)}"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginTop="32dp"
android:src="@drawable/icon_pokemon_selection_op"
app:layout_constraintEnd_toEndOf="@id/gl_end"
app:layout_constraintTop_toBottomOf="@id/tv_weather_description" />
app:layout_constraintTop_toBottomOf="@id/spinner_weather" />

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/weather_effect_container"
animatedVisibility="@{vm.showWeatherEffect}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:background="@drawable/bg_battle_description"
android:clickable="true"
android:elevation="8dp"
android:focusable="true"
android:orientation="vertical"
android:padding="12dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="@id/gl_end"
app:layout_constraintStart_toStartOf="@id/gl_start"
app:layout_constraintTop_toBottomOf="@id/spinner_weather"
tools:visibility="visible">

<TextView
android:id="@+id/tv_weather_effect_title"
style="@style/TextAppearance.Poke.CaptionLargeBold"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/battle_weather_effect_title"
app:layout_constraintEnd_toStartOf="@id/btn_weather_description_close"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<ImageView
android:id="@+id/btn_weather_description_close"
android:layout_width="32dp"
android:layout_height="32dp"
android:onClick="@{() -> vm.hideWeatherEffect()}"
android:padding="4dp"
android:src="@drawable/icon_close"
app:layout_constraintBottom_toBottomOf="@id/tv_weather_effect_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tv_weather_effect_title"
app:layout_constraintTop_toTopOf="@id/tv_weather_effect_title" />

<TextView
android:id="@+id/tv_weather_effect"
style="@style/TextAppearance.Poke.CaptionLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_weather_effect_title"
tools:text="날씨 효과 적는 칸" />

</androidx.constraintlayout.widget.ConstraintLayout>

<com.google.android.flexbox.FlexboxLayout
android:id="@+id/flexbox_mine_types"
Expand Down
Loading
Loading