Skip to content

Commit

Permalink
[MERGE] #60 -> develop
Browse files Browse the repository at this point in the history
[UI/#60] OurTodo 추가, 조회 뷰 / UI 구현
  • Loading branch information
Marchbreeze authored Jan 10, 2024
2 parents 3fc73dd + c5bf37f commit 1dd5f1c
Show file tree
Hide file tree
Showing 22 changed files with 1,153 additions and 12 deletions.
10 changes: 10 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@
android:exported="false"
android:screenOrientation="portrait" />

<activity
android:name="com.going.presentation.todo.ourtodo.create.OurTodoCreateActivity"
android:exported="false"
android:screenOrientation="portrait" />

<activity
android:name="com.going.presentation.todo.ourtodo.detail.OurTodoDetailActivity"
android:exported="false"
android:screenOrientation="portrait" />

<activity
android:name="com.going.presentation.starttrip.finishtrip.FinishTripActivity"
android:exported="false"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.going.presentation.todo.ourtodo

import android.content.Intent
import android.os.Bundle
import android.text.SpannableStringBuilder
import android.text.Spanned
Expand All @@ -9,8 +10,10 @@ import androidx.core.content.ContextCompat
import androidx.fragment.app.activityViewModels
import com.going.presentation.R
import com.going.presentation.databinding.FragmentOurTodoBinding
import com.going.presentation.todo.ourtodo.create.OurTodoCreateActivity
import com.going.presentation.todo.ourtodo.todolist.OurTodoViewPagerAdapter
import com.going.ui.base.BaseFragment
import com.going.ui.extension.setOnSingleClickListener
import com.google.android.material.tabs.TabLayoutMediator
import dagger.hilt.android.AndroidEntryPoint

Expand All @@ -29,6 +32,7 @@ class OurTodoFragment() : BaseFragment<FragmentOurTodoBinding>(R.layout.fragment
super.onViewCreated(view, savedInstanceState)

initAdapter()
initAddTodoBtnListener()
setDateTextColor()
setProgressBarStatus()
setTabLayout()
Expand All @@ -41,6 +45,14 @@ class OurTodoFragment() : BaseFragment<FragmentOurTodoBinding>(R.layout.fragment
adapter.submitList(viewModel.mockParticipantsList)
}

private fun initAddTodoBtnListener() {
binding.btnOurTodoAddTodo.setOnSingleClickListener {
Intent(activity, OurTodoCreateActivity::class.java).apply {
startActivity(this)
}
}
}

private fun setDateTextColor() {
binding.tvOurTodoTitleDown.apply {
text = SpannableStringBuilder(text).apply {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package com.going.presentation.todo.ourtodo.create

import android.graphics.drawable.Drawable
import android.os.Bundle
import android.widget.TextView
import androidx.activity.viewModels
import androidx.core.content.res.ResourcesCompat
import com.going.presentation.R
import com.going.presentation.databinding.ActivityOurTodoCreateBinding
import com.going.ui.base.BaseActivity
import com.going.ui.extension.setOnSingleClickListener

class OurTodoCreateActivity :
BaseActivity<ActivityOurTodoCreateBinding>(R.layout.activity_our_todo_create) {

private val viewModel by viewModels<OurTodoCreateViewModel>()

private var _adapter: TodoCreateNameAdapter? = null
private val adapter
get() = requireNotNull(_adapter) { getString(R.string.adapter_not_initialized_error_msg) }

private var ourTodoCreateBottomSheet: OurTodoCreateBottomSheet? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

initViewModel()
initNameListAdapter()
initTodoFocusListener()
initMemoFocusListener()
initDateClickListener()
initFinishBtnListener()
initBackBtnListener()
observeTextLength()
observeMemoLength()
observeDateEmpty()
}

private fun initViewModel() {
binding.vm = viewModel
}

private fun initNameListAdapter() {
// 아워투두 뷰에서 intent로 친구목록 받아와서 적용할 예정
_adapter = TodoCreateNameAdapter(false)
binding.rvOurTodoCreatePerson.adapter = adapter
adapter.submitList(listOf("김상호", "박동민", "조세연", "이유빈"))
}

private fun initTodoFocusListener() {
binding.etOurTodoCreateTodo.setOnFocusChangeListener { _, hasFocus ->
setColors(
hasFocus,
viewModel.nowTodoLength.value ?: 0,
binding.tvOurTodoTodoCounter,
) { background ->
binding.etOurTodoCreateTodo.background = setBackgroundColor(background)
}
}
}

private fun initMemoFocusListener() {
binding.etOurTodoCreateMemo.setOnFocusChangeListener { _, hasFocus ->
setColors(
hasFocus,
viewModel.nowMemoLength.value ?: 0,
binding.tvOurTodoMemoCounter,
) { background ->
binding.etOurTodoCreateMemo.background = setBackgroundColor(background)
}
}
}

private fun initDateClickListener() {
binding.etOurTodoCreateDate.setOnSingleClickListener {
ourTodoCreateBottomSheet = OurTodoCreateBottomSheet()
ourTodoCreateBottomSheet?.show(supportFragmentManager, DATE_BOTTOM_SHEET)
}
}

private fun initFinishBtnListener() {
binding.btnOurTodoMemoFinish.setOnSingleClickListener {
// 서버통신 진행
finish()
}
}

private fun initBackBtnListener() {
binding.btnOurTodoCreateBack.setOnSingleClickListener {
finish()
}
}

private fun observeTextLength() {
viewModel.nowTodoLength.observe(this) { length ->
val maxTodoLen = viewModel.getMaxTodoLen()

if (length > maxTodoLen) {
binding.etOurTodoCreateTodo.apply {
setText(text?.subSequence(0, maxTodoLen))
setSelection(maxTodoLen)
}
}
setColors(
false,
viewModel.nowTodoLength.value ?: 0,
binding.tvOurTodoTodoCounter,
) { background ->
binding.etOurTodoCreateTodo.background = setBackgroundColor(background)
}
}
}

private fun observeMemoLength() {
viewModel.nowMemoLength.observe(this) { length ->
val maxMemoLen = viewModel.getMaxMemoLen()
if (length > maxMemoLen) {
binding.etOurTodoCreateTodo.apply {
setText(text?.subSequence(0, maxMemoLen))
setSelection(maxMemoLen)
}
}
setColors(
false,
viewModel.nowMemoLength.value ?: 0,
binding.tvOurTodoMemoCounter,
) { background ->
binding.etOurTodoCreateMemo.background = setBackgroundColor(background)
}
}
}

private fun observeDateEmpty() {
viewModel.endDate.observe(this) { text ->
if (text.isEmpty()) {
binding.etOurTodoCreateDate.setBackgroundResource(R.drawable.shape_rect_4_gray200_line)
} else {
binding.etOurTodoCreateDate.setBackgroundResource(R.drawable.shape_rect_4_gray700_line)
}
}
}

private fun setColors(
hasFocus: Boolean,
length: Int,
counter: TextView,
setBackground: (Int) -> Unit,
) {
val (color, background) = when {
hasFocus || viewModel.nowTodoLength.value != 0 -> R.color.gray_700 to R.drawable.shape_rect_4_gray700_line
length == 0 -> R.color.gray_200 to R.drawable.shape_rect_4_gray200_line
else -> R.color.gray_700 to R.drawable.shape_rect_4_gray700_line
}
setCounterColor(counter, color)
setBackground(background)
}

private fun setCounterColor(counter: TextView, color: Int) {
counter.setTextColor(getColor(color))
}

private fun setBackgroundColor(background: Int): Drawable? {
return ResourcesCompat.getDrawable(
this.resources,
background,
theme,
)
}

override fun onDestroy() {
super.onDestroy()
_adapter = null
if (ourTodoCreateBottomSheet?.isAdded == true) ourTodoCreateBottomSheet?.dismiss()
}

companion object {
private const val DATE_BOTTOM_SHEET = "DATE_BOTTOM_SHEET"
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.going.presentation.todo.ourtodo.create

import android.os.Bundle
import android.view.View
import androidx.fragment.app.activityViewModels
import com.going.presentation.R
import com.going.presentation.databinding.FragmentMyTodoCreateBottomSheetBinding
import com.going.presentation.todo.mytodo.create.MyTodoCreateViewModel
import com.going.ui.base.BaseBottomSheet
import com.going.ui.extension.setOnSingleClickListener

class OurTodoCreateBottomSheet() :
BaseBottomSheet<FragmentMyTodoCreateBottomSheetBinding>(R.layout.fragment_my_todo_create_bottom_sheet) {

private val viewModel by activityViewModels<MyTodoCreateViewModel>()

override fun onStart() {
super.onStart()
dialog?.window?.setBackgroundDrawableResource(R.color.transparent)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

initFinishBtnClickListener()
}

private fun initFinishBtnClickListener() {
binding.btnCreateTripFinish.setOnSingleClickListener {
viewModel.endDate.value =
binding.dpCreateTripDate.year.toString() + "." + (binding.dpCreateTripDate.month + 1).toString() + "." + binding.dpCreateTripDate.dayOfMonth.toString()
viewModel.checkIsFinishAvailable()
dismiss()
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.going.presentation.todo.ourtodo.create

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import java.text.BreakIterator

class OurTodoCreateViewModel : ViewModel() {

val todo = MutableLiveData("")
val nowTodoLength = MutableLiveData(0)

val endDate = MutableLiveData("")

val memo = MutableLiveData("")
val nowMemoLength = MutableLiveData(0)

val isFinishAvailable = MutableLiveData(false)

fun getMaxTodoLen() = MAX_TODO_LEN

fun getMaxMemoLen() = MAX_MEMO_LEN

fun checkIsFinishAvailable() {
nowTodoLength.value = getGraphemeLength(todo.value)
nowMemoLength.value = getGraphemeLength(memo.value)
isFinishAvailable.value =
todo.value?.isNotEmpty() == true && memo.value?.isNotEmpty() == true && endDate.value?.isNotEmpty() == true
}

// 이모지 포함 글자 수 세는 함수
private fun getGraphemeLength(value: String?): Int {
BREAK_ITERATOR.setText(value)
var count = 0
while (BREAK_ITERATOR.next() != BreakIterator.DONE) {
count++
}
return count
}

companion object {
val BREAK_ITERATOR: BreakIterator = BreakIterator.getCharacterInstance()

const val MAX_TODO_LEN = 15
const val MAX_MEMO_LEN = 1000
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.going.presentation.todo.ourtodo.create

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter
import com.going.presentation.databinding.ItemTodoCreateNameBinding
import com.going.ui.extension.ItemDiffCallback

class TodoCreateNameAdapter(
private val isFixed: Boolean
) : ListAdapter<String, TodoCreateNameViewHolder>(diffUtil) {

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

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

companion object {
private val diffUtil = ItemDiffCallback<String>(
onItemsTheSame = { old, new -> old.length == new.length },
onContentsTheSame = { old, new -> old == new },
)
}
}
Loading

0 comments on commit 1dd5f1c

Please sign in to comment.