Skip to content

Commit

Permalink
[0.1.20-alpha/AN-UI] 상성 가로 화면 대응 (#178)
Browse files Browse the repository at this point in the history
* ui: type land 버전 xml 생성

* ui: 화면 모드에 따라 상성 spanCount 다르게 설정

* test: ui 테스트
  • Loading branch information
JoYehyun99 authored Aug 8, 2024
1 parent 387f681 commit 28df36a
Show file tree
Hide file tree
Showing 5 changed files with 296 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package poke.rogue.helper.presentation.type

import android.content.pm.ActivityInfo
import androidx.test.espresso.Espresso.onIdle
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Rule
import org.junit.Test
import org.junit.jupiter.api.DisplayName
import org.junit.runner.RunWith
import poke.rogue.helper.R

@RunWith(AndroidJUnit4::class)
class TypeActivityTest {
@get:Rule
val activityRule = ActivityScenarioRule(TypeActivity::class.java)

@Test
@DisplayName("사용자가 아무것도 선택하지 않은 경우에는 선택 안내 이미지가 보인다")
fun test1() {
// then
onView(ViewMatchers.withId(R.id.iv_no_selection))
.check(matches(isDisplayed()))
}

@Test
@DisplayName("화면 회전시에도 사용자가 아무것도 선택하지 않은 경우에는 선택 안내 이미지가 보인다")
fun test2() {
// when
activityRule.scenario.onActivity { activity ->
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
}
onIdle()

// then
onView(ViewMatchers.withId(R.id.iv_no_selection))
.check(matches(isDisplayed()))
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package poke.rogue.helper.presentation.type.selection

import android.content.res.Configuration
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import poke.rogue.helper.databinding.FragmentTypeSelectionBottomSheetBinding
import poke.rogue.helper.presentation.type.TypeEvent
Expand All @@ -31,7 +34,7 @@ class TypeSelectionBottomSheetFragment : BottomSheetDialogFragment() {

private val sharedViewModel by activityViewModels<TypeViewModel>()

private val adapter by lazy {
private val typeSelectionAdapter by lazy {
TypeSelectionAdapter(
sharedViewModel.allTypes,
selectorType,
Expand All @@ -40,6 +43,12 @@ class TypeSelectionBottomSheetFragment : BottomSheetDialogFragment() {
)
}

override fun onStart() {
super.onStart()
val behavior = BottomSheetBehavior.from(requireView().parent as View)
behavior.state = BottomSheetBehavior.STATE_EXPANDED
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
Expand All @@ -59,9 +68,16 @@ class TypeSelectionBottomSheetFragment : BottomSheetDialogFragment() {
}

private fun initAdapter() {
binding.rvTypeSelection.adapter = adapter
val decoration = GridSpacingItemDecoration(spanCount = 4, spacing = 20.dp, includeEdge = false)
binding.rvTypeSelection.addItemDecoration(decoration)
with(binding.rvTypeSelection) {
adapter = typeSelectionAdapter

val spanCount = if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) 6 else 4
val gridLayoutManager = GridLayoutManager(requireContext(), spanCount)
layoutManager = gridLayoutManager

val decoration = GridSpacingItemDecoration(spanCount = spanCount, spacing = 20.dp, includeEdge = false)
addItemDecoration(decoration)
}
}

private fun initObserver() {
Expand Down
230 changes: 230 additions & 0 deletions android/app/src/main/res/layout-land/activity_type.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<data>

<import type="poke.rogue.helper.presentation.type.model.SelectorType" />

<variable
name="typeHandler"
type="poke.rogue.helper.presentation.type.TypeHandler" />

<variable
name="vm"
type="poke.rogue.helper.presentation.type.TypeViewModel" />

<variable
name="myType"
type="poke.rogue.helper.presentation.type.model.TypeUiModel" />

<variable
name="opponent1Type"
type="poke.rogue.helper.presentation.type.model.TypeUiModel" />

<variable
name="opponent2Type"
type="poke.rogue.helper.presentation.type.model.TypeUiModel" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_type"
style="@style/CustomToolbarStyle"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintTop_toTopOf="parent"
app:title="@string/type_title_name" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/gl_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="20dp" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/gl_center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.45" />


<androidx.constraintlayout.widget.Guideline
android:id="@+id/gl_end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="20dp" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/gl_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="?attr/actionBarSize" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/gl_bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_end="12dp" />

<TextView
android:id="@+id/tv_type_opponent_type_title"
style="@style/TextAppearance.Poke.TitleLargeBold"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/type_opponent_type_title"
app:layout_constraintBottom_toTopOf="@id/vw_type_opponent_type_container_1"
app:layout_constraintEnd_toEndOf="@id/gl_center"
app:layout_constraintStart_toStartOf="@id/gl_start"
app:layout_constraintTop_toBottomOf="@id/gl_top" />

<ImageButton
android:id="@+id/btn_refresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_type_choice_container"
android:onClick="@{() -> typeHandler.removeAllSelections()}"
android:padding="2dp"
android:src="@drawable/ic_type_reset"
app:layout_constraintBottom_toBottomOf="@id/tv_type_opponent_type_title"
app:layout_constraintEnd_toEndOf="@id/gl_center"
app:layout_constraintTop_toTopOf="@id/tv_type_opponent_type_title" />

<View
android:id="@+id/vw_type_opponent_type_container_1"
android:layout_width="0dp"
android:layout_height="68dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="4dp"
android:background="@drawable/bg_type_choice_container"
android:onClick="@{() -> typeHandler.startSelection(SelectorType.OPPONENT1)}"
app:layout_constraintBottom_toTopOf="@id/tv_type_my_type_title"
app:layout_constraintEnd_toStartOf="@id/vw_type_opponent_type_container_2"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="@id/gl_start"
app:layout_constraintTop_toBottomOf="@id/tv_type_opponent_type_title" />

<poke.rogue.helper.presentation.type.view.PokeParallelogramLayout
android:id="@+id/parallelogram_type_opponent_type_content_1"
typeSelection="@{opponent1Type}"
typeSelectionListener="@{() -> typeHandler.removeSelection(SelectorType.OPPONENT1)}"
visible="@{vm.typeSelectionStates.isOpponent1Selected}"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="10dp"
app:layout_constraintBottom_toBottomOf="@id/vw_type_opponent_type_container_1"
app:layout_constraintEnd_toEndOf="@id/vw_type_opponent_type_container_1"
app:layout_constraintStart_toStartOf="@id/vw_type_opponent_type_container_1"
app:layout_constraintTop_toTopOf="@id/vw_type_opponent_type_container_1" />

<View
android:id="@+id/vw_type_opponent_type_container_2"
android:layout_width="0dp"
android:layout_height="68dp"
android:layout_marginStart="4dp"
android:background="@drawable/bg_type_choice_container"
android:onClick="@{() -> typeHandler.startSelection(SelectorType.OPPONENT2)}"
app:layout_constraintBottom_toBottomOf="@id/vw_type_opponent_type_container_1"
app:layout_constraintEnd_toEndOf="@id/gl_center"
app:layout_constraintStart_toEndOf="@id/vw_type_opponent_type_container_1"
app:layout_constraintTop_toTopOf="@id/vw_type_opponent_type_container_1" />

<poke.rogue.helper.presentation.type.view.PokeParallelogramLayout
android:id="@+id/parallelogram_type_opponent_type_content_2"
typeSelection="@{opponent2Type}"
typeSelectionListener="@{() -> typeHandler.removeSelection(SelectorType.OPPONENT2)}"
visible="@{vm.typeSelectionStates.isOpponent2Selected}"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="10dp"
app:layout_constraintBottom_toBottomOf="@id/vw_type_opponent_type_container_2"
app:layout_constraintEnd_toEndOf="@id/vw_type_opponent_type_container_2"
app:layout_constraintStart_toStartOf="@id/vw_type_opponent_type_container_2"
app:layout_constraintTop_toTopOf="@id/vw_type_opponent_type_container_2" />

<TextView
android:id="@+id/tv_type_my_type_title"
style="@style/TextAppearance.Poke.TitleLargeBold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/type_my_type_title"
app:layout_constraintBottom_toTopOf="@id/vw_type_my_type_container"
app:layout_constraintStart_toStartOf="@id/gl_start"
app:layout_constraintTop_toBottomOf="@id/vw_type_opponent_type_container_1" />

<View
android:id="@+id/vw_type_my_type_container"
android:layout_width="0dp"
android:layout_height="68dp"
android:layout_marginTop="12dp"
android:layout_marginBottom="8dp"
android:background="@drawable/bg_type_choice_container"
android:onClick="@{() -> typeHandler.startSelection(SelectorType.MINE)}"
app:layout_constraintBottom_toBottomOf="@id/gl_bottom"
app:layout_constraintEnd_toEndOf="@id/gl_center"
app:layout_constraintStart_toStartOf="@id/gl_start"
app:layout_constraintTop_toBottomOf="@id/tv_type_my_type_title" />

<poke.rogue.helper.presentation.type.view.PokeParallelogramLayout
android:id="@+id/parallelogram_type_my_type_content"
typeSelection="@{myType}"
typeSelectionListener="@{() -> typeHandler.removeSelection(SelectorType.MINE)}"
visible="@{vm.typeSelectionStates.isMyTypeSelected}"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="10dp"
app:layout_constraintBottom_toBottomOf="@id/vw_type_my_type_container"
app:layout_constraintEnd_toEndOf="@id/vw_type_my_type_container"
app:layout_constraintStart_toStartOf="@id/vw_type_my_type_container"
app:layout_constraintTop_toTopOf="@id/vw_type_my_type_container" />

<TextView
android:id="@+id/tv_type_result_title"
style="@style/TextAppearance.Poke.TitleLargeBold"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/type_result_title"
app:layout_constraintEnd_toEndOf="@id/gl_end"
app:layout_constraintStart_toStartOf="@id/gl_center"
app:layout_constraintTop_toTopOf="@id/gl_top" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_type_result"
visible="@{!vm.typeSelectionStates.allEmpty}"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="12dp"
android:layout_marginTop="8dp"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="@id/gl_bottom"
app:layout_constraintEnd_toEndOf="@id/gl_end"
app:layout_constraintStart_toStartOf="@id/gl_center"
app:layout_constraintTop_toBottomOf="@id/tv_type_result_title" />

<ImageView
android:id="@+id/iv_no_selection"
visible="@{vm.typeSelectionStates.allEmpty}"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="12dp"
android:layout_marginTop="4dp"
android:src="@drawable/img_type_empty_view_placeholder"
app:layout_constraintBottom_toBottomOf="@id/gl_bottom"
app:layout_constraintEnd_toEndOf="@id/gl_end"
app:layout_constraintStart_toStartOf="@id/gl_center"
app:layout_constraintTop_toBottomOf="@id/tv_type_result_title" />


</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
1 change: 1 addition & 0 deletions android/app/src/main/res/layout/activity_type.xml
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@
app:layout_constraintTop_toBottomOf="@id/tv_type_result_title" />

<ImageView
android:id="@+id/iv_no_selection"
visible="@{vm.typeSelectionStates.allEmpty}"
android:layout_width="0dp"
android:layout_height="wrap_content"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,21 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="24dp"
android:paddingBottom="12dp"
android:orientation="vertical"
tools:context=".presentation.type.selection.TypeSelectionBottomSheetFragment">

<com.google.android.material.bottomsheet.BottomSheetDragHandleView
android:id="@+id/drag_handle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
android:layout_height="wrap_content" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_type_selection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="4"
tools:listitem="@layout/item_type_selection" />
</LinearLayout>
</layout>

0 comments on commit 28df36a

Please sign in to comment.