Skip to content

Commit

Permalink
feat 댓글방 접히는 공지 뷰 구현 (#72)
Browse files Browse the repository at this point in the history
* chore: manifest에 CommentDetailActivity 추가

* feat: BindingAdatper을 사용하여 접힐 때 애니메이션 적용 및 픽셀 변환

* feat: viewmodel 구현 및 click 마다 접히고 펴지는 로직 구현

* style: ktlint 적용

* refactor: binding adpater을 사용하여 가시성 변경
  • Loading branch information
chaehyuns authored Jul 24, 2024
1 parent b61934c commit 2b8195d
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 43 deletions.
15 changes: 12 additions & 3 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,27 @@
android:theme="@style/Theme.Chongdae"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".presentation.view.detail.OfferingDetailActivity"
android:exported="false" />

<activity
android:name=".presentation.view.MainActivity"
android:exported="true">

<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

</activity>

<activity
android:name=".presentation.view.detail.OfferingDetailActivity"
android:exported="false" />

<activity
android:name=".presentation.view.commentdetail.CommentDetailActivity"
android:exported="false" />

</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.zzang.chongdae.presentation.util

import android.animation.ValueAnimator
import android.content.Context
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.databinding.BindingAdapter
Expand Down Expand Up @@ -62,3 +65,32 @@ private fun OfferingCondition.toComment(
totalCount,
)
}

@BindingAdapter("layout_heightWithAnimation")
fun setLayoutHeightWithAnimation(
view: View,
heightDp: Int,
) {
val params: ViewGroup.LayoutParams = view.layoutParams
val startHeight = params.height

val heightPx = heightDp.toPx(view.context)

val animator =
ValueAnimator.ofInt(startHeight, heightPx).apply {
duration = 300
addUpdateListener { animation ->
params.height = animation.animatedValue as Int
view.layoutParams = params
}
}
animator.start()
}

private fun Int.toPx(context: Context): Int {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
this.toFloat(),
context.resources.displayMetrics,
).toInt()
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,61 @@
package com.zzang.chongdae.presentation.view.commentdetail

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.databinding.DataBindingUtil
import com.zzang.chongdae.R
import com.zzang.chongdae.databinding.ActivityCommentDetailBinding

class CommentDetailActivity : AppCompatActivity() {
private var _binding: ActivityCommentDetailBinding? = null
private val binding get() = _binding!!
private lateinit var navHostFragment: NavHostFragment
private lateinit var navController: NavController

private val offeringId by lazy {
intent.getLongExtra(
EXTRA_OFFERING_ID_KEY,
EXTRA_DEFAULT_VALUE,
)
}

private val offeringTitle by lazy {
intent.getStringExtra(EXTRA_OFFERING_TITLE_KEY) ?: ""
}

private val viewModel: CommentDetailViewModel by viewModels { CommentDetailViewModel.getFactory(offeringId, offeringTitle) }

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

initBinding()
}

override fun onDestroy() {
super.onDestroy()
_binding = null
}

private fun initBinding() {
_binding = ActivityCommentDetailBinding.inflate(layoutInflater)
setContentView(binding.root)
_binding = DataBindingUtil.setContentView(this, R.layout.activity_comment_detail)
binding.vm = viewModel
binding.lifecycleOwner = this
}

companion object {
private const val EXTRA_DEFAULT_VALUE = -1L
private const val EXTRA_OFFERING_ID_KEY = "offering_id_key"
private const val EXTRA_OFFERING_TITLE_KEY = "offering_title_key"

fun startActivity(
context: Context,
offeringId: Long,
offeringTitle: String,
) = Intent(context, CommentDetailActivity::class.java).run {
putExtra(EXTRA_OFFERING_ID_KEY, offeringId)
putExtra(EXTRA_OFFERING_TITLE_KEY, offeringTitle)
context.startActivity(this)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.zzang.chongdae.presentation.view.commentdetail

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.CreationExtras

class CommentDetailViewModel(
private val offeringId: Long,
private val offeringTitle: String,
) : ViewModel() {
private val _isCollapsibleViewVisible = MutableLiveData<Boolean>(false)
val isCollapsibleViewVisible: LiveData<Boolean> get() = _isCollapsibleViewVisible

fun toggleCollapsibleView() {
_isCollapsibleViewVisible.value = _isCollapsibleViewVisible.value?.not()
Log.d("CommentDetailViewModel", "toggleCollapsibleView: ${_isCollapsibleViewVisible.value}")
}

companion object {
@Suppress("UNCHECKED_CAST")
fun getFactory(
offeringId: Long,
offeringTitle: String,
) = object : ViewModelProvider.Factory {
override fun <T : ViewModel> create(
modelClass: Class<T>,
extras: CreationExtras,
): T = CommentDetailViewModel(offeringId, offeringTitle) as T
}
}
}
98 changes: 64 additions & 34 deletions android/app/src/main/res/layout/activity_comment_detail.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

<data>

<variable
name="vm"
type="com.zzang.chongdae.presentation.view.commentdetail.CommentDetailViewModel" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
Expand All @@ -15,15 +18,16 @@
<View
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="@dimen/size_150"
android:layout_height="@dimen/size_120"
android:background="@color/main_color"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<ImageView
android:id="@+id/iv_back"
android:layout_width="@dimen/icon_size_24"
android:layout_height="@dimen/icon_size_24"
android:layout_width="@dimen/icon_size_20"
android:layout_height="@dimen/icon_size_20"
android:layout_marginStart="@dimen/margin_20"
android:layout_marginTop="@dimen/margin_30"
android:contentDescription="@string/comment_detail"
Expand All @@ -41,10 +45,10 @@
android:maxLines="1"
android:textColor="@color/white"
android:textSize="@dimen/size_20"
app:layout_constraintBottom_toBottomOf="@+id/iv_back"
app:layout_constraintBottom_toBottomOf="@id/iv_back"
app:layout_constraintEnd_toStartOf="@id/iv_more"
app:layout_constraintStart_toEndOf="@+id/iv_back"
app:layout_constraintTop_toTopOf="@+id/iv_back"
app:layout_constraintStart_toEndOf="@id/iv_back"
app:layout_constraintTop_toTopOf="@id/iv_back"
tools:text="엄청나게 긴 제목이 들어가는 것을 표현하는 중 입니다" />

<ImageView
Expand All @@ -54,73 +58,99 @@
android:layout_marginEnd="@dimen/margin_20"
android:contentDescription="@string/comment_detail"
android:src="@drawable/btn_more"
app:layout_constraintBottom_toBottomOf="@+id/tv_title_text"
app:layout_constraintBottom_toBottomOf="@id/tv_title_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/tv_title_text" />
app:layout_constraintTop_toTopOf="@id/tv_title_text" />

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_offering_condition"
<View
android:id="@+id/white_round_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="@dimen/size_120"
android:layout_marginTop="@dimen/margin_30"
android:background="@drawable/bg_white_radius_16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title_text" />

<ImageView
android:id="@+id/iv_offering_status"
android:layout_width="wrap_content"
android:layout_height="80dp"
android:layout_marginTop="@dimen/margin_20"
android:background="@drawable/bg_white_radius_16dp"
app:layout_constraintTop_toBottomOf="@+id/tv_title_text">
android:contentDescription="@string/comment_detail"
android:scaleType="fitXY"
android:src="@drawable/ic_recruiting"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/white_round_view" />

<ImageView
android:id="@+id/ic_offering_status"
android:layout_width="wrap_content"
android:layout_height="80dp"
android:layout_marginTop="@dimen/margin_20"
android:contentDescription="@string/comment_detail"
android:src="@drawable/ic_recruiting"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_offering_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_white_radius_16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/white_round_view">

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btn_edit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_20"
android:background="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/btn_confirm"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ic_offering_status"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.5"
tools:text="수정" />

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btn_confirm"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_20"
android:background="@color/main_color"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/btn_edit"
app:layout_constraintTop_toBottomOf="@id/ic_offering_status"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.5"
tools:text="인원확정" />

</androidx.constraintlayout.widget.ConstraintLayout>

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/foldable_view"
android:id="@+id/cl_foldable_view"
android:layout_width="match_parent"
android:layout_height="@dimen/size_36"
android:background="@color/gray_100"
android:onClick="@{() -> vm.toggleCollapsibleView()}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_offering_condition">
app:layout_constraintTop_toBottomOf="@id/cl_offering_button"
app:layout_heightWithAnimation="@{vm.isCollapsibleViewVisible ? 80 : 36}">

<ImageView
android:id="@+id/iv_foldable_open"
android:layout_width="@dimen/icon_size_15"
android:layout_height="@dimen/icon_size_15"
android:layout_marginTop="@dimen/size_10"
android:layout_marginEnd="@dimen/margin_20"
android:src="@drawable/btn_under_vector"
app:layout_constraintBottom_toBottomOf="parent"
app:isVisible="@{vm.isCollapsibleViewVisible}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<ImageView
android:id="@+id/iv_foldable_close"
android:layout_width="@dimen/icon_size_15"
android:layout_height="@dimen/icon_size_15"
android:layout_marginTop="@dimen/size_10"
android:layout_marginEnd="@dimen/margin_20"
android:src="@drawable/btn_up_vector"
app:isVisible="@{!vm.isCollapsibleViewVisible}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />

Expand Down Expand Up @@ -154,10 +184,10 @@
android:layout_width="@dimen/icon_size_15"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_20"
android:layout_marginTop="@dimen/margin_10"
android:layout_marginTop="@dimen/margin_20"
android:contentDescription="@string/comment_detail"
android:src="@drawable/ic_comment_detail_calendar"
android:visibility="gone"
app:isVisible="@{vm.isCollapsibleViewVisible}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_location" />

Expand All @@ -168,13 +198,13 @@
android:layout_marginStart="@dimen/margin_10"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/comment_detail_place_time_title"
android:textColor="@color/gray_font"
android:textSize="@dimen/size_11"
android:visibility="gone"
app:isVisible="@{vm.isCollapsibleViewVisible}"
app:layout_constraintBottom_toBottomOf="@id/iv_calendar"
app:layout_constraintStart_toEndOf="@id/iv_calendar"
app:layout_constraintTop_toTopOf="@id/iv_calendar" />
app:layout_constraintTop_toTopOf="@id/iv_calendar"
tools:text="@string/comment_detail_place_time_title" />

</androidx.constraintlayout.widget.ConstraintLayout>

Expand Down

0 comments on commit 2b8195d

Please sign in to comment.