라이브 상세

- 크리에이터는 예약자(참여자) 표시
This commit is contained in:
klaus 2024-02-13 00:34:34 +09:00
parent a14263bf27
commit a7ef5a8147
5 changed files with 259 additions and 0 deletions

View File

@ -0,0 +1,50 @@
package kr.co.vividnext.sodalive.live.room.detail
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import coil.load
import coil.transform.RoundedCornersTransformation
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.databinding.ItemLiveRoomDetailUserBinding
import kr.co.vividnext.sodalive.extensions.dpToPx
class LiveRoomDetailAdapter(
private val onClick: (GetRoomDetailUser) -> Unit
) : RecyclerView.Adapter<LiveRoomDetailAdapter.ViewHolder>() {
val items = mutableListOf<GetRoomDetailUser>()
inner class ViewHolder(
private val binding: ItemLiveRoomDetailUserBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: GetRoomDetailUser) {
binding.tvNickname.text = item.nickname
binding.ivProfile.load(item.profileImageUrl) {
crossfade(true)
placeholder(R.drawable.ic_place_holder)
transformations(RoundedCornersTransformation(23.4f.dpToPx()))
}
binding.root.setOnClickListener { onClick(item) }
}
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): ViewHolder {
return ViewHolder(
ItemLiveRoomDetailUserBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position])
}
override fun getItemCount() = items.count()
}

View File

@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.live.room.detail
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.graphics.Rect
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
@ -9,9 +10,13 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.webkit.URLUtil import android.webkit.URLUtil
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.Toast import android.widget.Toast
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import coil.load import coil.load
import coil.transform.CircleCropTransformation import coil.transform.CircleCropTransformation
import coil.transform.RoundedCornersTransformation
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.R
@ -19,8 +24,10 @@ import kr.co.vividnext.sodalive.common.Constants
import kr.co.vividnext.sodalive.common.LoadingDialog import kr.co.vividnext.sodalive.common.LoadingDialog
import kr.co.vividnext.sodalive.common.SharedPreferenceManager import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.databinding.FragmentLiveRoomDetailBinding import kr.co.vividnext.sodalive.databinding.FragmentLiveRoomDetailBinding
import kr.co.vividnext.sodalive.databinding.ItemLiveDetailUserSummaryBinding
import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity
import kr.co.vividnext.sodalive.extensions.convertDateFormat import kr.co.vividnext.sodalive.extensions.convertDateFormat
import kr.co.vividnext.sodalive.extensions.dpToPx
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
import java.util.Locale import java.util.Locale
@ -36,7 +43,9 @@ class LiveRoomDetailFragment(
private val viewModel: LiveRoomDetailViewModel by inject() private val viewModel: LiveRoomDetailViewModel by inject()
private lateinit var binding: FragmentLiveRoomDetailBinding private lateinit var binding: FragmentLiveRoomDetailBinding
private var isAllProfileOpen = false
private lateinit var adapter: LiveRoomDetailAdapter
private lateinit var loadingDialog: LoadingDialog private lateinit var loadingDialog: LoadingDialog
private lateinit var roomDetail: GetRoomDetailResponse private lateinit var roomDetail: GetRoomDetailResponse
@ -59,11 +68,33 @@ class LiveRoomDetailFragment(
val behavior = BottomSheetBehavior.from<View>(bottomSheet!!) val behavior = BottomSheetBehavior.from<View>(bottomSheet!!)
behavior.state = BottomSheetBehavior.STATE_EXPANDED behavior.state = BottomSheetBehavior.STATE_EXPANDED
setupAdapter()
bindData() bindData()
binding.ivClose.setOnClickListener { dismiss() } binding.ivClose.setOnClickListener { dismiss() }
viewModel.getDetail(roomId) { dismiss() } viewModel.getDetail(roomId) { dismiss() }
} }
private fun setupAdapter() {
val recyclerView = binding.rvParticipate
adapter = LiveRoomDetailAdapter {}
recyclerView.layoutManager = GridLayoutManager(requireContext(), 5)
recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
super.getItemOffsets(outRect, view, parent, state)
outRect.top = 13.3f.dpToPx().toInt()
outRect.bottom = 13.3f.dpToPx().toInt()
}
})
recyclerView.adapter = adapter
}
private fun bindData() { private fun bindData() {
viewModel.isLoading.observe(viewLifecycleOwner) { viewModel.isLoading.observe(viewLifecycleOwner) {
if (it) { if (it) {
@ -125,6 +156,7 @@ class LiveRoomDetailFragment(
binding.ivShare2.setOnClickListener { shareRoom(response) } binding.ivShare2.setOnClickListener { shareRoom(response) }
if (response.channelName.isNullOrBlank()) { if (response.channelName.isNullOrBlank()) {
binding.tvParticipateExpression.text = "예약자"
when { when {
response.manager.id == SharedPreferenceManager.userId -> { response.manager.id == SharedPreferenceManager.userId -> {
binding.llStartDelete.visibility = View.VISIBLE binding.llStartDelete.visibility = View.VISIBLE
@ -173,6 +205,52 @@ class LiveRoomDetailFragment(
} }
binding.llStartDelete.visibility = View.GONE binding.llStartDelete.visibility = View.GONE
} }
if (response.manager.id == SharedPreferenceManager.userId) {
setParticipantUserSummary(response.participatingUsers)
binding.llParticipateWrapper.visibility = View.VISIBLE
binding.tvParticipate.text = response.numberOfParticipants.toString()
binding.tvTotal.text = "/${response.numberOfParticipantsTotal}"
binding.tvOpenAllProfile.visibility = if (response.numberOfParticipants <= 0) {
View.GONE
} else {
View.VISIBLE
}
binding.tvOpenAllProfile.setOnClickListener {
isAllProfileOpen = !isAllProfileOpen
if (isAllProfileOpen) {
binding.llProfiles.visibility = View.GONE
binding.rvParticipate.visibility = View.VISIBLE
binding.tvParticipateExpression.visibility = View.VISIBLE
binding.tvOpenAllProfile.text = "닫기"
binding.tvOpenAllProfile.setCompoundDrawablesWithIntrinsicBounds(
R.drawable.ic_live_detail_top,
0,
0,
0
)
} else {
binding.llProfiles.visibility = View.VISIBLE
binding.rvParticipate.visibility = View.GONE
binding.tvParticipateExpression.visibility = View.GONE
binding.tvOpenAllProfile.text = "펼쳐보기"
binding.tvOpenAllProfile.setCompoundDrawablesWithIntrinsicBounds(
R.drawable.ic_live_detail_bottom,
0,
0,
0
)
}
}
adapter.items.addAll(response.participatingUsers)
adapter.notifyDataSetChanged()
} else {
binding.llParticipateWrapper.visibility = View.GONE
}
} }
private fun setManagerProfile(manager: GetRoomDetailManager) { private fun setManagerProfile(manager: GetRoomDetailManager) {
@ -244,6 +322,32 @@ class LiveRoomDetailFragment(
} }
} }
private fun setParticipantUserSummary(participatingUsers: List<GetRoomDetailUser>) {
val userCount = if (participatingUsers.size > 10) {
10
} else {
participatingUsers.size
}
for (index in 0 until userCount) {
val user = participatingUsers[index]
val itemView = ItemLiveDetailUserSummaryBinding.inflate(layoutInflater)
itemView.ivProfile.load(user.profileImageUrl) {
crossfade(true)
placeholder(R.drawable.ic_place_holder)
transformations(RoundedCornersTransformation(16.7f.dpToPx()))
}
val lp = LinearLayout.LayoutParams(33.3f.dpToPx().toInt(), 33.3f.dpToPx().toInt())
if (index > 0) {
lp.setMargins(-16.7f.dpToPx().toInt(), 0, 0, 0)
}
itemView.root.layoutParams = lp
binding.llProfiles.addView(itemView.root)
}
}
private fun shareRoom(response: GetRoomDetailResponse) { private fun shareRoom(response: GetRoomDetailResponse) {
viewModel.shareRoomLink( viewModel.shareRoomLink(
response.roomId, response.roomId,

View File

@ -91,6 +91,102 @@
tools:text="300" /> tools:text="300" />
</RelativeLayout> </RelativeLayout>
<LinearLayout
android:id="@+id/ll_participate_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:background="@color/color_88909090" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="13.3dp"
android:layout_marginTop="16.7dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/rl_date_and_can">
<TextView
android:id="@+id/tv_participate_expression"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:fontFamily="@font/gmarket_sans_medium"
android:gravity="center_vertical"
android:text="참여자"
android:textColor="@color/color_eeeeee"
android:textSize="12sp"
android:visibility="gone" />
<LinearLayout
android:id="@+id/ll_profiles"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_marginEnd="23.7dp"
android:layout_toStartOf="@+id/ll_participate"
android:gravity="center_vertical"
android:orientation="horizontal" />
<LinearLayout
android:id="@+id/ll_participate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:gravity="center">
<TextView
android:id="@+id/tv_participate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/gmarket_sans_medium"
android:textColor="@color/color_9970ff"
android:textSize="12sp"
tools:text="14" />
<TextView
android:id="@+id/tv_total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/gmarket_sans_medium"
android:textColor="@color/color_bbbbbb"
android:textSize="12sp"
tools:text="/20" />
</LinearLayout>
</RelativeLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_participate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="13.3dp"
android:layout_marginTop="13.3dp"
android:visibility="gone" />
<TextView
android:id="@+id/tv_open_all_profile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="13.3dp"
android:drawablePadding="6.7dp"
android:fontFamily="@font/gmarket_sans_medium"
android:gravity="center"
android:text="펼쳐보기"
android:textColor="@color/color_bbbbbb"
android:textSize="12sp"
app:drawableStartCompat="@drawable/ic_live_detail_bottom" />
</LinearLayout>
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="1dp" android:layout_height="1dp"

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/iv_profile"
android:layout_width="33.3dp"
android:layout_height="33.3dp"
android:contentDescription="@null"
tools:src="@mipmap/ic_launcher" />

View File

@ -20,6 +20,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ellipsize="end" android:ellipsize="end"
android:fontFamily="@font/gmarket_sans_medium" android:fontFamily="@font/gmarket_sans_medium"
android:layout_marginTop="8dp"
android:lines="1" android:lines="1"
android:textColor="@color/color_bbbbbb" android:textColor="@color/color_bbbbbb"
android:textSize="12sp" android:textSize="12sp"