Skip to content

Commit

Permalink
[AN/USER] feat: 축제 목록 디자인 수정(#698) (#701)
Browse files Browse the repository at this point in the history
* feat: 뷰페이저 탭의 점 크기 줄이기

* feat: ForegroundPopularFestival 아이템 설명을 뷰페이저 밖으로 이동하고 사이즈 수정

* feat: 아이템 선택 시 해당 아이템에 맞는 정보가 화면에 불러와진다

* feat: 인기 축제 목록 넘기기 범위 확장

* refactor: offset 계산 로직을 함수 분리하여 가독성을 증가시킨다

* feat(FestivalList): 진행중 진행 예정 탭 가로 여백 추가

* chore: lint check
  • Loading branch information
SeongHoonC authored Feb 10, 2024
1 parent 70dabc3 commit deadb0a
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ class FestivalListPopularViewHolder(val binding: ItemFestivalListPopularBinding)
PopularFestivalViewPagerAdapter(
foregroundViewPager = binding.vpPopularFestivalForeground,
backgroundViewPager = binding.vpPopularFestivalBackground,
)
) { item ->
binding.item = item
binding.tvPopularFestivalArtistsName.text =
item.artists.joinToString(ARTIST_NAME_JOIN_SEPARATOR) { it.name }
}

init {
TabLayoutMediator(
Expand All @@ -27,6 +31,8 @@ class FestivalListPopularViewHolder(val binding: ItemFestivalListPopularBinding)
}

companion object {
private const val ARTIST_NAME_JOIN_SEPARATOR = ", "

fun of(parent: ViewGroup): FestivalListPopularViewHolder {
val binding = ItemFestivalListPopularBinding.inflate(
LayoutInflater.from(parent.context),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package com.festago.festago.presentation.ui.home.festivallist.popularfestival

import android.content.res.Resources
import android.view.View
import androidx.viewpager2.widget.ViewPager2
import com.festago.festago.presentation.ui.home.festivallist.popularfestival.background.PopularFestivalBackgroundAdapter
import com.festago.festago.presentation.ui.home.festivallist.popularfestival.foreground.PopularFestivalForegroundAdapter
import com.festago.festago.presentation.ui.home.festivallist.uistate.FestivalItemUiState
import kotlin.math.abs

class PopularFestivalViewPagerAdapter(
foregroundViewPager: ViewPager2,
backgroundViewPager: ViewPager2,
private val onPopularFestivalSelected: (FestivalItemUiState) -> Unit,
) {

private val popularFestivals = mutableListOf<FestivalItemUiState>()
private val foregroundAdapter: PopularFestivalForegroundAdapter =
PopularFestivalForegroundAdapter()
private val backgroundAdapter: PopularFestivalBackgroundAdapter =
Expand All @@ -32,34 +36,67 @@ class PopularFestivalViewPagerAdapter(
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
target.setCurrentItem(position, false)
onPopularFestivalSelected(popularFestivals[position])
}
}
viewpager.registerOnPageChangeCallback(onPageChangeCallback)
}

private fun narrowSpaceViewPager(viewPager: ViewPager2) {
viewPager.setPageTransformer { page, position ->
val offset = position * -(2 * dpToPx(OFFSET_BETWEEN_PAGES))
page.translationX = offset
translateOffsetBetweenPages(position, page)
reduceUnselectedPagesScale(page, position)
}
}

private fun translateOffsetBetweenPages(position: Float, page: View) {
val screenWidth = Resources.getSystem().configuration.screenWidthDp
val offsetBetweenPages = screenWidth - IMAGE_SIZE - INTERVAL_IMAGE
val reducedDifference = IMAGE_SIZE - (IMAGE_SIZE * RATE_SELECT_BY_UNSELECT)
val offset = position * -dpToPx(offsetBetweenPages + reducedDifference * 0.5f)
page.translationX = offset
}

private fun dpToPx(dp: Float): Int {
val density = Resources.getSystem().displayMetrics.density
return (dp * density).toInt()
}

private fun reduceUnselectedPagesScale(page: View, position: Float) {
page.movePivotTo(x = page.pivotX, y = MIDDLE_IMAGE_PIVOT)
if (position <= ALREADY_LOAD_POSITION_CONDITION) {
page.reduceScaleBy(position = position, rate = RATE_SELECT_BY_UNSELECT)
}
}

private fun View.movePivotTo(x: Float, y: Float) {
pivotX = x
pivotY = y
}

private fun View.reduceScaleBy(position: Float, rate: Float) {
val scaleFactor = rate.coerceAtLeast(1 - abs(position))
scaleY = scaleFactor
scaleX = scaleFactor
}

private fun setOffscreenPagesLimit(viewPager: ViewPager2, limit: Int) {
viewPager.offscreenPageLimit = limit
}

fun submitList(popularFestivals: List<FestivalItemUiState>) {
foregroundAdapter.submitList(popularFestivals)
backgroundAdapter.submitList(popularFestivals)
fun submitList(festivals: List<FestivalItemUiState>) {
popularFestivals.clear()
popularFestivals.addAll(festivals)
foregroundAdapter.submitList(festivals)
backgroundAdapter.submitList(festivals)
}

companion object {
private const val PAGE_LIMIT = 3
private const val OFFSET_BETWEEN_PAGES = 63.0f
private const val ALREADY_LOAD_POSITION_CONDITION = 2
private const val RATE_SELECT_BY_UNSELECT = 0.81f
private const val PAGE_LIMIT = 4
private const val IMAGE_SIZE = 220.0f
private const val INTERVAL_IMAGE = 24.0f
private const val MIDDLE_IMAGE_PIVOT = 360.0f
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.festago.festago.presentation.ui.home.festivallist.popularfestival.foreground

import android.content.res.Resources
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
Expand All @@ -14,26 +13,9 @@ class PopularFestivalForegroundViewHolder(

fun bind(item: FestivalItemUiState) {
binding.item = item
binding.ivPopularFestivalImage.outlineProvider
binding.tvPopularFestivalArtistsName.text =
item.artists.joinToString(ARTIST_NAME_JOIN_SEPARATOR) { it.name }
setImageSizeFlexibleToScreenWidth()
}

private fun setImageSizeFlexibleToScreenWidth() {
val imageSize = Resources.getSystem().configuration.screenWidthDp - MINUS_TO_IMAGE_SIZE
val density = Resources.getSystem().displayMetrics.density

binding.ivPopularFestivalImage.layoutParams.apply {
this.width = (imageSize * density + ROUNDUP_CONDITION).toInt()
this.height = (imageSize * density + ROUNDUP_CONDITION).toInt()
}
}

companion object {
private const val MINUS_TO_IMAGE_SIZE = 160
private const val ROUNDUP_CONDITION = 0.5f
private const val ARTIST_NAME_JOIN_SEPARATOR = ", "

fun of(parent: ViewGroup): PopularFestivalForegroundViewHolder {
val binding = ItemPopularFestivalForegroundBinding.inflate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="4dp"
android:thickness="2dp"
android:useLevel="false">
<solid android:color="@color/background_gray_01" />
</shape>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="4dp"
android:thickness="2dp"
android:useLevel="false">
<solid android:color="@color/contents_gray_07" />
</shape>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
<?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">
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>

<import type="java.time.format.DateTimeFormatter" />

<variable
name="item"
type="com.festago.festago.presentation.ui.home.festivallist.uistate.FestivalItemUiState" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
Expand All @@ -25,23 +35,73 @@
android:textColor="@color/background_gray_01"
app:layout_constraintTop_toTopOf="@id/vpPopularFestivalBackground" />

<TextView
android:id="@+id/tvPopularFestivalName"
style="@style/H3Bold18Lh20"
android:layout_width="220dp"
android:layout_height="wrap_content"
android:layout_marginTop="248dp"
android:ellipsize="end"
android:gravity="center"
android:lineSpacingExtra="0dp"
android:maxLines="2"
android:text="@{item.schoolUiState.name+'\n'+ item.name }"
android:textColor="@color/background_gray_01"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/vpPopularFestivalForeground"
tools:text="대학교 \n 축제 이름" />

<TextView
android:id="@+id/tvFestivalSchedule"
style="@style/B2Medium14Lh20"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:ellipsize="end"
android:gravity="center"
android:maxLines="1"
android:text="@{@string/festival_list_tv_date_range_format(item.startDate.format(DateTimeFormatter.ofPattern(@string/festival_list_tv_date_format)),item.endDate.format(DateTimeFormatter.ofPattern(@string/festival_list_tv_date_format)))}"
android:textColor="@color/background_gray_01"
app:layout_constraintEnd_toEndOf="@+id/tvPopularFestivalName"
app:layout_constraintStart_toStartOf="@+id/tvPopularFestivalName"
app:layout_constraintTop_toBottomOf="@id/tvPopularFestivalName"
tools:text="2023.07.03 - 2023.07.09" />

<TextView
android:id="@+id/tvPopularFestivalArtistsName"
style="@style/B2Medium14Lh20"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="center"
android:lineSpacingExtra="0dp"
android:lines="2"
android:textColor="@color/background_gray_01"
app:layout_constraintEnd_toEndOf="@+id/tvFestivalSchedule"
app:layout_constraintStart_toStartOf="@+id/tvFestivalSchedule"
app:layout_constraintTop_toBottomOf="@id/tvFestivalSchedule"
tools:text="르세라핌, 아이브, 뉴진스, \n다이나믹 듀오" />

<androidx.viewpager2.widget.ViewPager2
android:id="@+id/vpPopularFestivalForeground"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="12dp"
app:layout_constraintBottom_toBottomOf="@id/tlDotIndicator"
app:layout_constraintTop_toBottomOf="@id/tvPopularFestivalTitle" />

<com.google.android.material.tabs.TabLayout
android:id="@+id/tlDotIndicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
app:layout_constraintTop_toBottomOf="@id/vpPopularFestivalForeground"
app:layout_constraintTop_toBottomOf="@id/tvPopularFestivalArtistsName"
app:tabBackground="@drawable/selector_tab_page"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
app:tabPaddingEnd="8dp"
app:tabPaddingStart="8dp" />

<androidx.viewpager2.widget.ViewPager2
android:id="@+id/vpPopularFestivalForeground"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/tvPopularFestivalTitle" />

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
android:id="@+id/tlFestivalListTab"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginHorizontal="16dp"
android:background="@android:color/transparent"
app:tabGravity="fill"
app:tabIndicatorColor="@color/contents_gray_07"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,70 +20,19 @@
<ImageView
android:id="@+id/ivPopularFestivalImage"
imageUrl="@{item.imageUrl}"
android:layout_width="200dp"
android:layout_height="200dp"
android:outlineProvider="bounds"
android:layout_marginTop="24dp"
android:layout_width="220dp"
android:layout_height="220dp"
android:layout_marginTop="12dp"
android:elevation="12dp"
android:importantForAccessibility="no"
android:outlineProvider="bounds"
android:scaleType="centerCrop"
android:elevation="10dp"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintDimensionRatio="1:1"
tools:src="@drawable/ic_launcher_background" />


<TextView
android:id="@+id/tvPopularFestivalName"
style="@style/H3Bold18Lh20"
android:textColor="@color/background_gray_01"
android:layout_width="0dp"
android:layout_marginTop="16dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="center"
android:maxLines="2"
android:lineSpacingExtra="0dp"
android:text="@{item.schoolUiState.name+'\n'+ item.name }"
app:layout_constraintTop_toBottomOf="@id/ivPopularFestivalImage"
app:layout_constraintEnd_toEndOf="@+id/ivPopularFestivalImage"
app:layout_constraintStart_toStartOf="@+id/ivPopularFestivalImage"
tools:text="대학교 \n 축제 이름" />


<TextView
android:id="@+id/tvFestivalSchedule"
style="@style/B2Medium14Lh20"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="@color/background_gray_01"
android:ellipsize="end"
android:gravity="center"
android:maxLines="1"
android:layout_marginTop="8dp"
android:text="@{@string/festival_list_tv_date_range_format(item.startDate.format(DateTimeFormatter.ofPattern(@string/festival_list_tv_date_format)),item.endDate.format(DateTimeFormatter.ofPattern(@string/festival_list_tv_date_format)))}"
app:layout_constraintTop_toBottomOf="@id/tvPopularFestivalName"
app:layout_constraintEnd_toEndOf="@+id/ivPopularFestivalImage"
tools:text="2023.07.03 - 2023.07.09"
app:layout_constraintStart_toStartOf="@+id/ivPopularFestivalImage" />

<TextView
android:id="@+id/tvPopularFestivalArtistsName"
style="@style/B2Medium14Lh20"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="@color/background_gray_01"
android:ellipsize="end"
android:gravity="center"
android:lineSpacingExtra="0dp"
android:lines="2"
app:layout_constraintTop_toBottomOf="@id/tvFestivalSchedule"
app:layout_constraintEnd_toEndOf="@+id/ivPopularFestivalImage"
app:layout_constraintStart_toStartOf="@+id/ivPopularFestivalImage"
tools:text="르세라핌, 아이브, 뉴진스, \n다이나믹 듀오" />


</androidx.constraintlayout.widget.ConstraintLayout>

</layout>
</layout>

0 comments on commit deadb0a

Please sign in to comment.