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

#8 [ui] Daily Routine - 추가하기 #18

Merged
merged 45 commits into from
Jan 14, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
30917a4
[add] : drawable 및 이미지 에셋 추출
minemi00 Jan 9, 2024
411796f
[feat] 데일리 루틴 테마 리사이클러뷰 item
minemi00 Jan 9, 2024
9272708
[add] 인디케이터 selector 만들기
minemi00 Jan 9, 2024
13db25d
[ui] 데일리 루틴 추가하기 1차 구현
minemi00 Jan 9, 2024
d3b843a
[add] 데일리루틴 뷰페이저 어댑터 생성
minemi00 Jan 9, 2024
c5c057f
[feat] 데일리루틴 추가 viewpager, indicator 로직
minemi00 Jan 9, 2024
022f0a8
[feat] 데일리루틴 추가 viewpager, indicator 로직
minemi00 Jan 9, 2024
b81bf10
[chore] indicator 수정
minemi00 Jan 9, 2024
041f285
[feat] 리사이클러뷰 연결
minemi00 Jan 9, 2024
fdecc78
[chore] 이미지 로드 이슈 해결
minemi00 Jan 9, 2024
a859f4e
[chore] 뷰페이저 가운데 정렬 완
minemi00 Jan 9, 2024
6ec660e
[chore] 뷰페이저 가운데 정렬 완
minemi00 Jan 9, 2024
db96226
[add] manifest에 데일리루틴추가하기 뷰 추가
minemi00 Jan 10, 2024
bf52dfe
[chore] 글자 행간 수정
minemi00 Jan 10, 2024
47d5fdf
[chore] 리사이클러뷰 클릭이벤트 수정
minemi00 Jan 10, 2024
5527708
Merge branch 'develop' of https://github.com/Team-Sopetit/Sopetit-And…
minemi00 Jan 11, 2024
b6ca29f
[chore] 네이밍 및 폴더링 변경
minemi00 Jan 11, 2024
66e7e17
[chore] mocklist, 데이터클래스 변경
minemi00 Jan 11, 2024
82afb19
Merge branch 'develop' of https://github.com/Team-Sopetit/Sopetit-And…
minemi00 Jan 11, 2024
ccb3045
#8 [chore] 뷰모델 가짜데이터, 데이터 클래스 수정
minemi00 Jan 11, 2024
3b8a9f9
#8 [chore] 뷰페이저 양옆 보이게 수정
minemi00 Jan 11, 2024
249f79d
Merge branch 'develop' of https://github.com/Team-Sopetit/Sopetit-And…
minemi00 Jan 11, 2024
9f2ea54
#8 [chore] 이미지 로드 이슈 해결
minemi00 Jan 12, 2024
63d2a52
#8 [feat] 리사이클러뷰 클릭 이벤트 적용
minemi00 Jan 12, 2024
14c3e99
#8 [feat] : 리사이클러뷰 클릭이벤트 색깔 바뀌게
minemi00 Jan 12, 2024
2d71560
#8 [chore] : 이미지 로드 문제 해결
minemi00 Jan 12, 2024
7b7fd6d
#8 [chore] : 이미지 로드 비율 맞추기
minemi00 Jan 12, 2024
7432bc5
Merge branch 'develop' of https://github.com/Team-Sopetit/Sopetit-And…
minemi00 Jan 12, 2024
4a4db0f
#8 [chore] : 이미지 로드 비율 수정
minemi00 Jan 12, 2024
d51808e
#8 [chore] : ci 오류 수정
minemi00 Jan 12, 2024
85e1ad0
#8 [chore] : ci 오류 재수정
minemi00 Jan 12, 2024
ce2ab8b
#8 [chore] : ci 오류 재수정
minemi00 Jan 12, 2024
f3f751c
#8 [chore] : ci 오류 재수정
minemi00 Jan 12, 2024
c490a1a
#8 [chore] : 테마 리스트 변수명 변경
minemi00 Jan 12, 2024
f0d7e14
#8 [refact] : 코드리뷰 반영
minemi00 Jan 14, 2024
fe5d383
#8 [add] : 데일리추가하기 데이터 클래스 생성
minemi00 Jan 14, 2024
0182c04
#8 [refact] : 데일리 루틴 리스트 불러오기
minemi00 Jan 14, 2024
f608e2d
Merge branch 'develop' of https://github.com/Team-Sopetit/Sopetit-And…
minemi00 Jan 14, 2024
914c300
#8 [chore] : ci 오류 수정
minemi00 Jan 14, 2024
7d53ab7
#8 [add] : 액티비티 종료
minemi00 Jan 14, 2024
1ce1e29
#8 [add] : 액티비티 종료
minemi00 Jan 14, 2024
8e73d6c
Merge branch 'develop' of https://github.com/Team-Sopetit/Sopetit-And…
minemi00 Jan 14, 2024
2ba41c2
#8 [chore] : 중복 indicator 삭제
minemi00 Jan 14, 2024
a3713b0
#8 [chore] : 코드리뷰 반영
minemi00 Jan 14, 2024
dea9844
#8 [add] : 데일리루틴뷰, 추가뷰 연결
minemi00 Jan 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ dependencies {
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")

//indicator
Copy link
Collaborator

Choose a reason for hiding this comment

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

인디케이터 잘 쓰겠습니다^^

Copy link
Member Author

Choose a reason for hiding this comment

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

^^ 오빠가 기쁘니 좋다

implementation("com.tbuonomo:dotsindicator:5.0")
}

fun getApiKey(propertyKey: String): String {
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
android:exported="false"
android:screenOrientation="portrait" />

<activity
android:name=".ui.daily.DailyAddActivity"
android:exported="false"
android:screenOrientation="portrait" />

<activity
android:name=".ui.storytelling.StoryTellingActivity"
android:exported="true"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.sopetit.softie.domain.entity

import androidx.annotation.DrawableRes

data class DailyCard(
@DrawableRes val card: Int,
val routine: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.sopetit.softie.domain.entity

data class DailyTheme(
val routineId: Int,
val iconImageUrl: String,
val content: String
)
133 changes: 133 additions & 0 deletions app/src/main/java/com/sopetit/softie/ui/daily/DailyAddActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package com.sopetit.softie.ui.daily

import android.graphics.Rect
import android.os.Bundle
import android.view.View
import androidx.activity.viewModels
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.CompositePageTransformer
import androidx.viewpager2.widget.MarginPageTransformer
import androidx.viewpager2.widget.ViewPager2
import com.sopetit.softie.R
import com.sopetit.softie.databinding.ActivityDailyAddBinding
import com.sopetit.softie.util.binding.BindingActivity

class DailyAddActivity : BindingActivity<ActivityDailyAddBinding>(R.layout.activity_daily_add) {
private lateinit var viewPager: ViewPager2
private lateinit var dailyPagerAdapter: DailyPagerAdapter
private lateinit var dailyThemeAdapter: DailyThemeAdapter

private val dailyAddViewModel by viewModels<DailyAddViewModel>()
private val dailyThemeViewModel by viewModels<DailyThemeViewModel>()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
dailyPagerAdapter = DailyPagerAdapter()
dailyThemeAdapter = DailyThemeAdapter()

viewPager = binding.vpDailyCard

setupAdapter()
//marginPage()
initViewPager()
setIndicator()
setDiv()
initPagerDiv(19, 20)
}

private fun setupAdapter() {
with(binding) {
vpDailyCard.adapter = dailyPagerAdapter
rvThemeDaily.adapter = dailyThemeAdapter
}
dailyPagerAdapter.submitList(dailyAddViewModel.mockDailyList)
dailyThemeAdapter.submitList(dailyThemeViewModel.mockDailyThemeList.value)
}

private fun marginPage() {
val pageMarginPx = resources.getDimensionPixelOffset(R.dimen.viewpager_margin)
val pagerWidth = resources.getDimensionPixelOffset(R.dimen.viewpager_margin)
val screenWidth = resources.displayMetrics.widthPixels
val offsetPx = screenWidth - pageMarginPx - pagerWidth

binding.vpDailyCard.setPageTransformer { page, position ->
page.translationX = position * -offsetPx
}
}

private fun initViewPager() {

viewPager.adapter = dailyPagerAdapter

viewPager.apply {
clipChildren = false
clipToPadding = false
offscreenPageLimit = 1
}

val compositePageTransformer = CompositePageTransformer()
compositePageTransformer.addTransformer(
MarginPageTransformer(
resources.getDimensionPixelOffset(
R.dimen.viewpager_margin
)
)
)
viewPager.setPageTransformer(compositePageTransformer)
}

private fun setIndicator() {
binding.diDailyIndicator.attachTo(binding.vpDailyCard)
}

private fun initPagerDiv(previewWidth: Int, itemMargin: Int) {
val decoMargin = previewWidth + itemMargin
val pageTransX = decoMargin + previewWidth
val decoration = PageDecoration(decoMargin)

binding.vpDailyCard.also {
it.offscreenPageLimit = 1
it.addItemDecoration(decoration)
it.setPageTransformer { page, position ->
page.translationX = position * -pageTransX
}
}
}

private class PageDecoration(private val margin: Int) : RecyclerView.ItemDecoration() {

override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
outRect.left = margin
outRect.right = margin
}
}

class HorizontalItemDecorator(private val divHeight: Int) : RecyclerView.ItemDecoration() {
@Override
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
super.getItemOffsets(outRect, view, parent, state)
outRect.left = divHeight
Copy link
Collaborator

Choose a reason for hiding this comment

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

position == 0일 경우와 아닌 경우 나눠서 divHeight을 두면 첫 margin만 구분을 줄 수 있습니다!

Copy link
Member Author

Choose a reason for hiding this comment

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

아하 ! 꼼꼼한 리뷰 감사합니다

outRect.right = divHeight
}
}

private fun selectTheme() {
dailyThemeAdapter.setOnThemeClickListener {

}
}

private fun setDiv() {
binding.rvThemeDaily.addItemDecoration(HorizontalItemDecorator(16))
}
}
30 changes: 30 additions & 0 deletions app/src/main/java/com/sopetit/softie/ui/daily/DailyAddViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.sopetit.softie.ui.daily

import androidx.lifecycle.ViewModel
import com.sopetit.softie.R
import com.sopetit.softie.domain.entity.DailyCard

class DailyAddViewModel : ViewModel() {
val mockDailyList = listOf<DailyCard>(
DailyCard(
card = R.drawable.shape_gray_fill_20_rect,
routine = "가짜 데이터"
),
DailyCard(
card = R.drawable.shape_gray_fill_20_rect,
routine = "진짜 데이터"
),
DailyCard(
card = R.drawable.shape_gray_fill_20_rect,
routine = "가짜 데이터"
),
DailyCard(
card = R.drawable.shape_gray_fill_20_rect,
routine = "가짜 데이터"
),
DailyCard(
card = R.drawable.shape_gray_fill_20_rect,
routine = "가짜 데이터"
)
)
}
36 changes: 36 additions & 0 deletions app/src/main/java/com/sopetit/softie/ui/daily/DailyPagerAdapter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.sopetit.softie.ui.daily

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.sopetit.softie.R
import com.sopetit.softie.databinding.ItemDailyCardBinding
import com.sopetit.softie.domain.entity.DailyCard
import com.sopetit.softie.util.ItemDiffCallback

class DailyPagerAdapter : ListAdapter<DailyCard, DailyPagerAdapter.DailyPagerViewHolder>(
ItemDiffCallback<DailyCard>(
onItemsTheSame = { oldItem, newItem -> oldItem == newItem },
onContentsTheSame = { oldItem, newItem -> oldItem == newItem }
)
) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DailyPagerViewHolder {
val binding = ItemDailyCardBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
return DailyPagerViewHolder(binding)
}

override fun onBindViewHolder(holder: DailyPagerViewHolder, position: Int) {
holder.onBind(currentList[position])
}

class DailyPagerViewHolder(private val binding: ItemDailyCardBinding) :
RecyclerView.ViewHolder(binding.root) {
fun onBind(data: DailyCard) {
binding.clDailyCard.loadLayoutDescription(R.layout.item_daily_card)
binding.tvDailyCard.text = data.routine
}
}
}
95 changes: 95 additions & 0 deletions app/src/main/java/com/sopetit/softie/ui/daily/DailyThemeAdapter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.sopetit.softie.ui.daily

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.sopetit.softie.R
import com.sopetit.softie.databinding.ItemDailyThemeBinding
import com.sopetit.softie.domain.entity.DailyTheme
import com.sopetit.softie.util.ItemDiffCallback

class DailyThemeAdapter : ListAdapter<DailyTheme, DailyThemeAdapter.DailyThemeViewHolder>(
ItemDiffCallback<DailyTheme>(
onItemsTheSame = { oldItem, newItem -> oldItem == newItem },
onContentsTheSame = { oldItem, newItem -> oldItem == newItem }
)
) {
var selectedThemeArray = mutableListOf<Int>()

inner class DailyThemeViewHolder(private val binding: ItemDailyThemeBinding) :
RecyclerView.ViewHolder(binding.root) {

init {
toggleThemeSelection(getItem(0).routineId)
}

fun onBind(data: DailyTheme) {
binding.data = data
binding.root.setOnClickListener {
val position = bindingAdapterPosition
if (position != RecyclerView.NO_POSITION) {
val isSelected = toggleThemeSelection(data.routineId)
onItemClickListener?.invoke(data)
notifyItemChanged(bindingAdapterPosition)
changeThemeBackground(binding, selectedThemeArray.contains(data.routineId))
}
}
}
}

//클릭이벤트 만들어 주기
private var onItemClickListener: ((DailyTheme) -> Unit)? = null
fun setOnThemeClickListener(listener: (DailyTheme) -> Unit) {
onItemClickListener = listener
}

private fun toggleThemeSelection(routineId: Int): Boolean {
val isSelected = selectedThemeArray.contains(routineId)
if (isSelected) {
selectedThemeArray.remove(routineId) // 선택 해제
} else {
selectedThemeArray.add(routineId) // 선택
}
return !isSelected // 선택 상태 반전
}

private fun changeThemeBackground(
binding: ItemDailyThemeBinding,
selected: Boolean
) {
when (selected) {
true -> {
binding.ivDailyThemeBackground.setBackgroundResource(R.drawable.ic_daily_theme_background_click)
binding.tvThemeDaily.setTextColor(
ContextCompat.getColor(
binding.root.context,
R.color.gray700
)
)
}

false -> {
binding.ivDailyThemeBackground.setBackgroundResource(R.drawable.ic_daily_theme_background)
binding.tvThemeDaily.setTextColor(
ContextCompat.getColor(
binding.root.context,
R.color.gray400
)
)
}
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DailyThemeViewHolder {
val binding = ItemDailyThemeBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
return DailyThemeViewHolder(binding)
}

override fun onBindViewHolder(holder: DailyThemeViewHolder, position: Int) {
holder.onBind(getItem(position))
}
}
Loading
Loading