라이브 메인 - UI, Api 적용
|
@ -98,7 +98,7 @@ dependencies {
|
|||
}
|
||||
|
||||
// Gson
|
||||
implementation "com.google.code.gson:gson:2.9.0"
|
||||
implementation "com.google.code.gson:gson:2.9.1"
|
||||
|
||||
// Network
|
||||
implementation "com.squareup.retrofit2:retrofit:2.9.0"
|
||||
|
@ -115,6 +115,7 @@ dependencies {
|
|||
implementation "io.github.ParkSangGwon:tedpermission-normal:3.3.0"
|
||||
|
||||
implementation 'com.github.dhaval2404:imagepicker:2.1'
|
||||
implementation 'com.github.zhpanvip:bannerviewpager:3.5.7'
|
||||
|
||||
implementation 'com.google.android.gms:play-services-oss-licenses:17.0.1'
|
||||
|
||||
|
|
|
@ -10,11 +10,12 @@ object Constants {
|
|||
const val PREF_USER_ROLE = "pref_user_role"
|
||||
const val PREF_PUSH_TOKEN = "pref_push_token"
|
||||
const val PREF_PROFILE_IMAGE = "pref_profile_image"
|
||||
const val PREF_IS_FOLLOWED_CREATOR_LIVE = "pref_is_followed_creator_live"
|
||||
|
||||
const val EXTRA_DATA = "extra_data"
|
||||
const val EXTRA_TERMS = "extra_terms"
|
||||
const val EXTRA_USER_ID = "extra_user_id"
|
||||
const val EXTRA_ROOM_ID = "extra_room_id"
|
||||
const val EXTRA_USER_ID = "extra_user_id"
|
||||
const val EXTRA_MESSAGE_ID = "extra_message_id"
|
||||
|
||||
const val EXTRA_CONTENT_ID = "extra_content_id"
|
||||
|
|
|
@ -98,4 +98,10 @@ object SharedPreferenceManager {
|
|||
set(value) {
|
||||
sharedPreferences[Constants.PREF_PUSH_TOKEN] = value
|
||||
}
|
||||
|
||||
var isFollowedCreatorLive: Boolean
|
||||
get() = sharedPreferences[Constants.PREF_IS_FOLLOWED_CREATOR_LIVE, false]
|
||||
set(value) {
|
||||
sharedPreferences[Constants.PREF_IS_FOLLOWED_CREATOR_LIVE] = value
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,15 @@ import android.content.Context
|
|||
import com.google.gson.GsonBuilder
|
||||
import kr.co.vividnext.sodalive.BuildConfig
|
||||
import kr.co.vividnext.sodalive.common.ApiBuilder
|
||||
import kr.co.vividnext.sodalive.live.LiveApi
|
||||
import kr.co.vividnext.sodalive.live.LiveRepository
|
||||
import kr.co.vividnext.sodalive.live.LiveViewModel
|
||||
import kr.co.vividnext.sodalive.live.recommend.LiveRecommendApi
|
||||
import kr.co.vividnext.sodalive.live.recommend.LiveRecommendRepository
|
||||
import kr.co.vividnext.sodalive.main.MainViewModel
|
||||
import kr.co.vividnext.sodalive.network.TokenAuthenticator
|
||||
import kr.co.vividnext.sodalive.settings.event.EventApi
|
||||
import kr.co.vividnext.sodalive.settings.event.EventRepository
|
||||
import kr.co.vividnext.sodalive.settings.terms.TermsApi
|
||||
import kr.co.vividnext.sodalive.settings.terms.TermsRepository
|
||||
import kr.co.vividnext.sodalive.settings.terms.TermsViewModel
|
||||
|
@ -58,6 +65,9 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
|
|||
|
||||
single { ApiBuilder().build(get(), UserApi::class.java) }
|
||||
single { ApiBuilder().build(get(), TermsApi::class.java) }
|
||||
single { ApiBuilder().build(get(), LiveApi::class.java) }
|
||||
single { ApiBuilder().build(get(), EventApi::class.java) }
|
||||
single { ApiBuilder().build(get(), LiveRecommendApi::class.java) }
|
||||
}
|
||||
|
||||
private val viewModelModule = module {
|
||||
|
@ -66,11 +76,15 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
|
|||
viewModel { TermsViewModel(get()) }
|
||||
viewModel { FindPasswordViewModel(get()) }
|
||||
viewModel { MainViewModel(get()) }
|
||||
viewModel { LiveViewModel(get(), get(), get()) }
|
||||
}
|
||||
|
||||
private val repositoryModule = module {
|
||||
factory { UserRepository(get()) }
|
||||
factory { TermsRepository(get()) }
|
||||
factory { LiveRepository(get()) }
|
||||
factory { EventRepository(get()) }
|
||||
factory { LiveRecommendRepository(get()) }
|
||||
}
|
||||
|
||||
private val moduleList = listOf(
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package kr.co.vividnext.sodalive.live
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class GetRoomListResponse(
|
||||
@SerializedName("roomId") val roomId: Long,
|
||||
@SerializedName("title") val title: String,
|
||||
@SerializedName("content") val content: String,
|
||||
@SerializedName("beginDateTime") val beginDateTime: String,
|
||||
@SerializedName("numberOfParticipate") val numberOfParticipate: Int,
|
||||
@SerializedName("numberOfPeople") val numberOfPeople: Int,
|
||||
@SerializedName("coverImageUrl") val coverImageUrl: String,
|
||||
@SerializedName("isAdult") val isAdult: Boolean,
|
||||
@SerializedName("price") val price: Int,
|
||||
@SerializedName("tags") val tags: List<String>,
|
||||
@SerializedName("channelName") val channelName: String?,
|
||||
@SerializedName("managerNickname") val managerNickname: String,
|
||||
@SerializedName("managerId") val managerId: Long,
|
||||
@SerializedName("isReservation") val isReservation: Boolean,
|
||||
@SerializedName("isPrivateRoom") val isPrivateRoom: Boolean
|
||||
)
|
|
@ -0,0 +1,20 @@
|
|||
package kr.co.vividnext.sodalive.live
|
||||
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoomStatus
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
import retrofit2.http.Query
|
||||
|
||||
interface LiveApi {
|
||||
@GET("/live/room")
|
||||
fun roomList(
|
||||
@Query("timezone") timezone: String,
|
||||
@Query("dateString") dateString: String?,
|
||||
@Query("status") status: LiveRoomStatus,
|
||||
@Query("page") page: Int,
|
||||
@Query("size") size: Int,
|
||||
@Header("Authorization") authHeader: String
|
||||
): Flowable<ApiResponse<List<GetRoomListResponse>>>
|
||||
}
|
|
@ -1,7 +1,403 @@
|
|||
package kr.co.vividnext.sodalive.live
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.graphics.Rect
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.webkit.URLUtil
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.zhpan.bannerview.BaseBannerAdapter
|
||||
import com.zhpan.indicator.enums.IndicatorSlideMode
|
||||
import com.zhpan.indicator.enums.IndicatorStyle
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.base.BaseFragment
|
||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||
import kr.co.vividnext.sodalive.databinding.FragmentLiveBinding
|
||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||
import kr.co.vividnext.sodalive.live.event_banner.EventBannerAdapter
|
||||
import kr.co.vividnext.sodalive.live.now.LiveNowAdapter
|
||||
import kr.co.vividnext.sodalive.live.recommend.RecommendLiveAdapter
|
||||
import kr.co.vividnext.sodalive.live.recommend_channel.LiveRecommendChannelAdapter
|
||||
import kr.co.vividnext.sodalive.live.reservation.LiveReservationAdapter
|
||||
import kr.co.vividnext.sodalive.settings.notification.MemberRole
|
||||
import org.koin.android.ext.android.inject
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class LiveFragment : BaseFragment<FragmentLiveBinding>(FragmentLiveBinding::inflate) {
|
||||
private val viewModel: LiveViewModel by inject()
|
||||
|
||||
private lateinit var liveNowAdapter: LiveNowAdapter
|
||||
private lateinit var liveReservationAdapter: LiveReservationAdapter
|
||||
private lateinit var liveRecommendChannelAdapter: LiveRecommendChannelAdapter
|
||||
|
||||
private lateinit var loadingDialog: LoadingDialog
|
||||
|
||||
private var message = ""
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
setupView()
|
||||
setupRecommendLive()
|
||||
setupRecommendChannel()
|
||||
setupLiveNow()
|
||||
setupLiveReservation()
|
||||
setupEvent()
|
||||
|
||||
message = "라이브를 불러오고 있습니다."
|
||||
viewModel.getSummary()
|
||||
}
|
||||
|
||||
private fun setupView() {
|
||||
loadingDialog = LoadingDialog(requireActivity(), layoutInflater)
|
||||
|
||||
viewModel.toastLiveData.observe(viewLifecycleOwner) {
|
||||
it?.let { Toast.makeText(requireActivity(), it, Toast.LENGTH_LONG).show() }
|
||||
}
|
||||
|
||||
viewModel.isLoading.observe(viewLifecycleOwner) {
|
||||
if (it) {
|
||||
loadingDialog.show(screenWidth, message)
|
||||
} else {
|
||||
loadingDialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
binding.ivMakeRoom.visibility =
|
||||
if (SharedPreferenceManager.role == MemberRole.CREATOR.name) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
binding.ivMakeRoom.setOnClickListener {}
|
||||
|
||||
binding.swipeRefreshLayout.setOnRefreshListener { refreshSummary() }
|
||||
|
||||
val ivHowToUseLp = binding.ivHowToUse.layoutParams as LinearLayout.LayoutParams
|
||||
ivHowToUseLp.width = screenWidth
|
||||
ivHowToUseLp.height = (200 * screenWidth) / 1080
|
||||
binding.ivHowToUse.layoutParams = ivHowToUseLp
|
||||
binding.ivHowToUse.setOnClickListener {
|
||||
val url = "https://blog.naver.com/yozmlive"
|
||||
if (URLUtil.isValidUrl(url)) {
|
||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun refreshSummary() {
|
||||
liveNowAdapter.clear()
|
||||
liveRecommendChannelAdapter.clear()
|
||||
liveReservationAdapter.clear()
|
||||
|
||||
message = "라이브를 불러오고 있습니다."
|
||||
viewModel.getSummary()
|
||||
|
||||
binding.swipeRefreshLayout.isRefreshing = false
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun setupRecommendLive() {
|
||||
val layoutParams = binding
|
||||
.layoutRecommendLive
|
||||
.pager
|
||||
.layoutParams as LinearLayout.LayoutParams
|
||||
|
||||
val pagerWidth = screenWidth.toDouble() - 26.7f.dpToPx()
|
||||
val pagerHeight = (pagerWidth * 0.53).roundToInt()
|
||||
layoutParams.width = pagerWidth.roundToInt()
|
||||
layoutParams.height = pagerHeight
|
||||
|
||||
binding
|
||||
.layoutRecommendLive
|
||||
.pager
|
||||
.layoutParams = layoutParams
|
||||
|
||||
binding.layoutRecommendLive.pager.apply {
|
||||
adapter = RecommendLiveAdapter(pagerWidth.roundToInt(), pagerHeight) {
|
||||
} as BaseBannerAdapter<Any>
|
||||
|
||||
setLifecycleRegistry(lifecycle)
|
||||
setScrollDuration(1000)
|
||||
setInterval(4 * 1000)
|
||||
}.create()
|
||||
|
||||
binding
|
||||
.layoutRecommendLive
|
||||
.pager
|
||||
.setIndicatorView(binding.layoutRecommendLive.indicator2)
|
||||
.setIndicatorStyle(IndicatorStyle.ROUND_RECT)
|
||||
.setIndicatorSlideMode(IndicatorSlideMode.SMOOTH)
|
||||
.setIndicatorVisibility(View.GONE)
|
||||
.setIndicatorSliderColor(
|
||||
ContextCompat.getColor(requireContext(), R.color.color_909090),
|
||||
ContextCompat.getColor(requireContext(), R.color.color_9970ff)
|
||||
)
|
||||
.setIndicatorSliderWidth(4f.dpToPx().toInt(), 10f.dpToPx().toInt())
|
||||
.setIndicatorHeight(4f.dpToPx().toInt())
|
||||
|
||||
viewModel.recommendLiveData.observe(viewLifecycleOwner) {
|
||||
if (it.isNotEmpty()) {
|
||||
binding.layoutRecommendLive.root.visibility = View.VISIBLE
|
||||
binding.layoutRecommendLive.pager.refreshData(it)
|
||||
} else {
|
||||
binding.layoutRecommendLive.root.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupRecommendChannel() {
|
||||
liveRecommendChannelAdapter = LiveRecommendChannelAdapter(
|
||||
onClick = {},
|
||||
onClickMore = {}
|
||||
)
|
||||
|
||||
binding.layoutRecommendChannel.rvRecommendChannel.layoutManager = LinearLayoutManager(
|
||||
requireContext(),
|
||||
LinearLayoutManager.HORIZONTAL,
|
||||
false
|
||||
)
|
||||
|
||||
binding
|
||||
.layoutRecommendChannel
|
||||
.rvRecommendChannel
|
||||
.addItemDecoration(object : RecyclerView.ItemDecoration() {
|
||||
override fun getItemOffsets(
|
||||
outRect: Rect,
|
||||
view: View,
|
||||
parent: RecyclerView,
|
||||
state: RecyclerView.State
|
||||
) {
|
||||
super.getItemOffsets(outRect, view, parent, state)
|
||||
|
||||
when (parent.getChildAdapterPosition(view)) {
|
||||
0 -> {
|
||||
outRect.left = 0.dpToPx().toInt()
|
||||
outRect.right = 8.3f.dpToPx().toInt()
|
||||
}
|
||||
|
||||
liveRecommendChannelAdapter.itemCount - 1 -> {
|
||||
outRect.left = 8.3f.dpToPx().toInt()
|
||||
outRect.right = 0.dpToPx().toInt()
|
||||
}
|
||||
|
||||
else -> {
|
||||
outRect.left = 8.3f.dpToPx().toInt()
|
||||
outRect.right = 8.3f.dpToPx().toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
binding.layoutRecommendChannel.rvRecommendChannel.adapter = liveRecommendChannelAdapter
|
||||
binding.layoutRecommendChannel.ivSwitch.setOnClickListener {
|
||||
viewModel.toggleIsFollowedCreatorLive()
|
||||
}
|
||||
|
||||
viewModel.recommendChannelLiveData.observe(viewLifecycleOwner) {
|
||||
binding.layoutRecommendChannel.root.visibility = View.VISIBLE
|
||||
liveRecommendChannelAdapter.addItems(it)
|
||||
binding.layoutRecommendChannel.rvRecommendChannel.requestLayout()
|
||||
binding.layoutRecommendChannel.root.requestLayout()
|
||||
}
|
||||
|
||||
viewModel.isFollowedCreatorLive.observe(viewLifecycleOwner) {
|
||||
liveRecommendChannelAdapter.isFollowedCreatorLive = it
|
||||
liveRecommendChannelAdapter.clear()
|
||||
|
||||
if (it) {
|
||||
binding.layoutRecommendChannel.ivSwitch.setImageResource(R.drawable.btn_toggle_on_big)
|
||||
binding.layoutRecommendChannel.llTitle2.visibility = View.VISIBLE
|
||||
binding.layoutRecommendChannel.llTitle1.visibility = View.GONE
|
||||
} else {
|
||||
binding.layoutRecommendChannel.ivSwitch.setImageResource(R.drawable.btn_toggle_off_big)
|
||||
binding.layoutRecommendChannel.llTitle1.visibility = View.VISIBLE
|
||||
binding.layoutRecommendChannel.llTitle2.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun setupLiveNow() {
|
||||
binding
|
||||
.layoutLiveNow
|
||||
.tvAllView
|
||||
.setOnClickListener {}
|
||||
|
||||
val recyclerView = binding
|
||||
.layoutLiveNow
|
||||
.rvSudaNow
|
||||
|
||||
liveNowAdapter = LiveNowAdapter {}
|
||||
|
||||
recyclerView.layoutManager = LinearLayoutManager(
|
||||
requireContext(),
|
||||
LinearLayoutManager.HORIZONTAL,
|
||||
false
|
||||
)
|
||||
|
||||
recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() {
|
||||
override fun getItemOffsets(
|
||||
outRect: Rect,
|
||||
view: View,
|
||||
parent: RecyclerView,
|
||||
state: RecyclerView.State
|
||||
) {
|
||||
super.getItemOffsets(outRect, view, parent, state)
|
||||
|
||||
when (parent.getChildAdapterPosition(view)) {
|
||||
0 -> {
|
||||
outRect.left = 13.3f.dpToPx().toInt()
|
||||
outRect.right = 5.dpToPx().toInt()
|
||||
}
|
||||
|
||||
liveNowAdapter.itemCount - 1 -> {
|
||||
outRect.left = 5.dpToPx().toInt()
|
||||
outRect.right = 13.3f.dpToPx().toInt()
|
||||
}
|
||||
|
||||
else -> {
|
||||
outRect.left = 5.dpToPx().toInt()
|
||||
outRect.right = 5.dpToPx().toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
recyclerView.adapter = liveNowAdapter
|
||||
|
||||
viewModel.liveNowLiveData.observe(viewLifecycleOwner) {
|
||||
if (liveNowAdapter.items.isEmpty() && it.isEmpty()) {
|
||||
recyclerView.visibility = View.GONE
|
||||
binding.layoutLiveNow.tvAllView.visibility = View.GONE
|
||||
binding.layoutLiveNow.llNoItems.visibility = View.VISIBLE
|
||||
binding.layoutLiveNow.tvMakeRoom.setOnClickListener {}
|
||||
|
||||
recyclerView.requestLayout()
|
||||
binding.layoutLiveNow.llNoItems.requestLayout()
|
||||
} else {
|
||||
binding.layoutLiveNow.tvAllView.visibility = View.VISIBLE
|
||||
binding.layoutLiveNow.llNoItems.visibility = View.GONE
|
||||
liveNowAdapter.items.addAll(it)
|
||||
liveNowAdapter.notifyDataSetChanged()
|
||||
recyclerView.visibility = View.VISIBLE
|
||||
recyclerView.requestLayout()
|
||||
}
|
||||
|
||||
binding.layoutLiveNow.root.requestLayout()
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun setupLiveReservation() {
|
||||
val recyclerView = binding
|
||||
.layoutLiveReservation
|
||||
.rvSudaReservation
|
||||
|
||||
liveReservationAdapter = LiveReservationAdapter(isMain = true) {}
|
||||
|
||||
recyclerView.layoutManager = LinearLayoutManager(
|
||||
requireContext(),
|
||||
LinearLayoutManager.VERTICAL,
|
||||
false
|
||||
)
|
||||
|
||||
recyclerView.addItemDecoration(object : RecyclerView.ItemDecoration() {
|
||||
override fun getItemOffsets(
|
||||
outRect: Rect,
|
||||
view: View,
|
||||
parent: RecyclerView,
|
||||
state: RecyclerView.State
|
||||
) {
|
||||
super.getItemOffsets(outRect, view, parent, state)
|
||||
|
||||
outRect.left = 13.3f.dpToPx().toInt()
|
||||
outRect.right = 13.3f.dpToPx().toInt()
|
||||
|
||||
when (parent.getChildAdapterPosition(view)) {
|
||||
0 -> {
|
||||
outRect.top = 0f.dpToPx().toInt()
|
||||
outRect.bottom = 6.7f.dpToPx().toInt()
|
||||
}
|
||||
|
||||
liveReservationAdapter.itemCount - 1 -> {
|
||||
outRect.top = 6.7f.dpToPx().toInt()
|
||||
outRect.bottom = 13.3f.dpToPx().toInt()
|
||||
}
|
||||
|
||||
else -> {
|
||||
outRect.top = 6.7f.dpToPx().toInt()
|
||||
outRect.bottom = 6.7f.dpToPx().toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
recyclerView.adapter = liveReservationAdapter
|
||||
|
||||
viewModel.liveReservationLiveData.observe(viewLifecycleOwner) {
|
||||
if (liveReservationAdapter.items.isEmpty() && it.isEmpty()) {
|
||||
recyclerView.visibility = View.GONE
|
||||
binding.layoutLiveReservation.tvAllView.visibility = View.GONE
|
||||
binding.layoutLiveReservation.llNoItems.visibility = View.VISIBLE
|
||||
binding.layoutLiveReservation.tvMakeRoom.setOnClickListener {}
|
||||
|
||||
recyclerView.requestLayout()
|
||||
binding.layoutLiveReservation.llNoItems.requestLayout()
|
||||
} else {
|
||||
binding.layoutLiveReservation.tvAllView.visibility = View.VISIBLE
|
||||
binding.layoutLiveReservation.llNoItems.visibility = View.GONE
|
||||
liveReservationAdapter.items.addAll(it)
|
||||
liveReservationAdapter.notifyDataSetChanged()
|
||||
|
||||
recyclerView.visibility = View.VISIBLE
|
||||
recyclerView.requestLayout()
|
||||
}
|
||||
|
||||
binding.layoutLiveReservation.root.requestLayout()
|
||||
}
|
||||
|
||||
binding.layoutLiveReservation.tvAllView.setOnClickListener {}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun setupEvent() {
|
||||
val imageSliderLp = binding.eventBannerSlider.layoutParams
|
||||
imageSliderLp.width = screenWidth
|
||||
imageSliderLp.height = (screenWidth * 300) / 1000
|
||||
binding.eventBannerSlider.layoutParams = imageSliderLp
|
||||
|
||||
binding.eventBannerSlider.apply {
|
||||
adapter = EventBannerAdapter(requireContext()) {} as BaseBannerAdapter<Any>
|
||||
setLifecycleRegistry(lifecycle)
|
||||
setScrollDuration(800)
|
||||
}.create()
|
||||
|
||||
binding.eventBannerSlider
|
||||
.setIndicatorView(binding.indicator)
|
||||
.setIndicatorStyle(IndicatorStyle.ROUND_RECT)
|
||||
.setIndicatorSlideMode(IndicatorSlideMode.SMOOTH)
|
||||
.setIndicatorVisibility(View.GONE)
|
||||
.setIndicatorSliderColor(
|
||||
ContextCompat.getColor(requireContext(), R.color.color_909090),
|
||||
ContextCompat.getColor(requireContext(), R.color.color_9970ff)
|
||||
)
|
||||
.setIndicatorSliderWidth(4f.dpToPx().toInt(), 10f.dpToPx().toInt())
|
||||
.setIndicatorHeight(4f.dpToPx().toInt())
|
||||
|
||||
viewModel.eventLiveData.observe(viewLifecycleOwner) {
|
||||
if (it.isNotEmpty()) {
|
||||
binding.eventBannerSlider.visibility = View.VISIBLE
|
||||
binding.eventBannerSlider.refreshData(it)
|
||||
} else {
|
||||
binding.eventBannerSlider.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package kr.co.vividnext.sodalive.live
|
||||
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoomStatus
|
||||
import java.util.TimeZone
|
||||
|
||||
class LiveRepository(private val api: LiveApi) {
|
||||
fun roomList(
|
||||
dateString: String? = null,
|
||||
status: LiveRoomStatus,
|
||||
page: Int,
|
||||
size: Int,
|
||||
token: String
|
||||
): Flowable<ApiResponse<List<GetRoomListResponse>>> {
|
||||
return api.roomList(
|
||||
timezone = TimeZone.getDefault().id,
|
||||
dateString = dateString,
|
||||
status = status,
|
||||
page = page - 1,
|
||||
size = size,
|
||||
authHeader = token
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package kr.co.vividnext.sodalive.live
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import kr.co.vividnext.sodalive.live.recommend.GetRecommendLiveResponse
|
||||
import kr.co.vividnext.sodalive.settings.event.GetEventResponse
|
||||
|
||||
data class LiveSummary(
|
||||
@SerializedName("liveNow") val liveNow: ApiResponse<List<GetRoomListResponse>>,
|
||||
@SerializedName("liveReservation") val liveReservation: ApiResponse<List<GetRoomListResponse>>,
|
||||
@SerializedName("event") val event: ApiResponse<GetEventResponse>,
|
||||
@SerializedName("recommendLive") val recommendLive: ApiResponse<List<GetRecommendLiveResponse>>,
|
||||
)
|
|
@ -0,0 +1,241 @@
|
|||
package kr.co.vividnext.sodalive.live
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.orhanobut.logger.Logger
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||
import kr.co.vividnext.sodalive.live.recommend.GetRecommendLiveResponse
|
||||
import kr.co.vividnext.sodalive.live.recommend.LiveRecommendRepository
|
||||
import kr.co.vividnext.sodalive.live.recommend_channel.GetRecommendChannelResponse
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoomStatus
|
||||
import kr.co.vividnext.sodalive.settings.event.EventItem
|
||||
import kr.co.vividnext.sodalive.settings.event.EventRepository
|
||||
|
||||
class LiveViewModel(
|
||||
private val repository: LiveRepository,
|
||||
private val eventRepository: EventRepository,
|
||||
private val liveRecommendRepository: LiveRecommendRepository
|
||||
) : BaseViewModel() {
|
||||
private var _isLoading = MutableLiveData(false)
|
||||
val isLoading: LiveData<Boolean>
|
||||
get() = _isLoading
|
||||
|
||||
private val _toastLiveData = MutableLiveData<String?>()
|
||||
val toastLiveData: LiveData<String?>
|
||||
get() = _toastLiveData
|
||||
|
||||
private val _recommendLiveData = MutableLiveData<List<GetRecommendLiveResponse>>()
|
||||
val recommendLiveData: LiveData<List<GetRecommendLiveResponse>>
|
||||
get() = _recommendLiveData
|
||||
|
||||
private val _isFollowedCreatorLive = MutableLiveData(
|
||||
SharedPreferenceManager.isFollowedCreatorLive
|
||||
)
|
||||
val isFollowedCreatorLive: LiveData<Boolean>
|
||||
get() = _isFollowedCreatorLive
|
||||
|
||||
private val _recommendChannelLiveData = MutableLiveData<List<GetRecommendChannelResponse>>()
|
||||
val recommendChannelLiveData: LiveData<List<GetRecommendChannelResponse>>
|
||||
get() = _recommendChannelLiveData
|
||||
|
||||
private val _liveNowLiveData = MutableLiveData<List<GetRoomListResponse>>()
|
||||
val liveNowLiveData: LiveData<List<GetRoomListResponse>>
|
||||
get() = _liveNowLiveData
|
||||
|
||||
private val _liveReservationLiveData = MutableLiveData<List<GetRoomListResponse>>()
|
||||
val liveReservationLiveData: LiveData<List<GetRoomListResponse>>
|
||||
get() = _liveReservationLiveData
|
||||
|
||||
private val _eventLiveData = MutableLiveData<List<EventItem>>()
|
||||
val eventLiveData: LiveData<List<EventItem>>
|
||||
get() = _eventLiveData
|
||||
|
||||
var page = 1
|
||||
var isLast = false
|
||||
private val pageSize = 10
|
||||
|
||||
fun toggleIsFollowedCreatorLive() {
|
||||
val isOn = !_isFollowedCreatorLive.value!!
|
||||
SharedPreferenceManager.isFollowedCreatorLive = isOn
|
||||
_isFollowedCreatorLive.value = isOn
|
||||
if (_isFollowedCreatorLive.value!!) {
|
||||
getFollowedChannelList()
|
||||
} else {
|
||||
getRecommendChannelList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFollowedChannelList() {
|
||||
compositeDisposable.add(
|
||||
liveRecommendRepository.getFollowingChannelList(
|
||||
token = "Bearer ${SharedPreferenceManager.token}"
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{
|
||||
if (it.success && it.data != null) {
|
||||
_recommendChannelLiveData.postValue(it.data!!)
|
||||
} else {
|
||||
if (it.message != null) {
|
||||
_toastLiveData.postValue(it.message)
|
||||
} else {
|
||||
_toastLiveData.postValue(
|
||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
_isLoading.value = false
|
||||
it.message?.let { message -> Logger.e(message) }
|
||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun getRecommendChannelList() {
|
||||
compositeDisposable.add(
|
||||
liveRecommendRepository.getRecommendChannelList(
|
||||
token = "Bearer ${SharedPreferenceManager.token}"
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{
|
||||
if (it.success && it.data != null) {
|
||||
_recommendChannelLiveData.postValue(it.data!!)
|
||||
} else {
|
||||
if (it.message != null) {
|
||||
_toastLiveData.postValue(it.message)
|
||||
} else {
|
||||
_toastLiveData.postValue(
|
||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
_isLoading.value = false
|
||||
it.message?.let { message -> Logger.e(message) }
|
||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun getSummary() {
|
||||
if (!_isLoading.value!!) {
|
||||
if (_isFollowedCreatorLive.value!!) {
|
||||
getFollowedChannelList()
|
||||
} else {
|
||||
getRecommendChannelList()
|
||||
}
|
||||
|
||||
val liveNow = repository.roomList(
|
||||
status = LiveRoomStatus.NOW,
|
||||
page = 1,
|
||||
size = pageSize,
|
||||
token = "Bearer ${SharedPreferenceManager.token}"
|
||||
)
|
||||
|
||||
val liveReservation = repository.roomList(
|
||||
status = LiveRoomStatus.RESERVATION,
|
||||
page = 1,
|
||||
size = pageSize,
|
||||
token = "Bearer ${SharedPreferenceManager.token}"
|
||||
)
|
||||
|
||||
val event = eventRepository.getEvents(
|
||||
0,
|
||||
5,
|
||||
token = "Bearer ${SharedPreferenceManager.token}"
|
||||
)
|
||||
|
||||
val recommendLive = liveRecommendRepository.getRecommendLive(
|
||||
token = "Bearer ${SharedPreferenceManager.token}"
|
||||
)
|
||||
|
||||
_isLoading.postValue(true)
|
||||
|
||||
compositeDisposable.add(
|
||||
Flowable.combineLatest(
|
||||
liveNow,
|
||||
liveReservation,
|
||||
event,
|
||||
recommendLive,
|
||||
) { t1, t2, t3, t4 -> LiveSummary(t1, t2, t3, t4) }
|
||||
.subscribe(
|
||||
{
|
||||
val now = it.liveNow
|
||||
if (now.success && now.data != null) {
|
||||
_liveNowLiveData.postValue(now.data!!)
|
||||
if (now.data.isNotEmpty()) {
|
||||
page += 1
|
||||
} else {
|
||||
isLast = true
|
||||
}
|
||||
} else {
|
||||
if (now.message != null) {
|
||||
_toastLiveData.postValue(now.message)
|
||||
} else {
|
||||
_toastLiveData.postValue(
|
||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val reservation = it.liveReservation
|
||||
if (reservation.success && reservation.data != null) {
|
||||
_liveReservationLiveData.postValue(reservation.data!!)
|
||||
if (reservation.data.isNotEmpty()) {
|
||||
page += 1
|
||||
} else {
|
||||
isLast = true
|
||||
}
|
||||
} else {
|
||||
if (reservation.message != null) {
|
||||
_toastLiveData.postValue(reservation.message)
|
||||
} else {
|
||||
_toastLiveData.postValue(
|
||||
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val eventResponse = it.event
|
||||
if (eventResponse.success && eventResponse.data != null) {
|
||||
val data = eventResponse.data
|
||||
_eventLiveData.postValue(data.eventList)
|
||||
} else {
|
||||
_eventLiveData.postValue(emptyList())
|
||||
}
|
||||
|
||||
val recommendLiveResponse = it.recommendLive
|
||||
if (
|
||||
recommendLiveResponse.success &&
|
||||
recommendLiveResponse.data != null
|
||||
) {
|
||||
val data = recommendLiveResponse.data
|
||||
_recommendLiveData.postValue(data!!)
|
||||
} else {
|
||||
_recommendLiveData.postValue(emptyList())
|
||||
}
|
||||
|
||||
_isLoading.postValue(false)
|
||||
},
|
||||
{
|
||||
_isLoading.postValue(false)
|
||||
it.message?.let { message -> Logger.e(message) }
|
||||
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package kr.co.vividnext.sodalive.live.event_banner
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.ImageView
|
||||
import coil.load
|
||||
import com.zhpan.bannerview.BaseBannerAdapter
|
||||
import com.zhpan.bannerview.BaseViewHolder
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.settings.event.EventItem
|
||||
|
||||
class EventBannerAdapter(
|
||||
private val context: Context,
|
||||
private val itemClick: (EventItem) -> Unit
|
||||
) : BaseBannerAdapter<EventItem>() {
|
||||
|
||||
override fun bindData(
|
||||
holder: BaseViewHolder<EventItem>,
|
||||
data: EventItem,
|
||||
position: Int,
|
||||
pageSize: Int
|
||||
) {
|
||||
val ivThumbnail = holder.findViewById<ImageView>(R.id.iv_thumbnail)
|
||||
ivThumbnail.load(data.thumbnailImageUrl) {
|
||||
crossfade(true)
|
||||
|
||||
val layoutParams = ivThumbnail.layoutParams
|
||||
val screenWidth = context.resources.displayMetrics.widthPixels
|
||||
layoutParams.width = screenWidth
|
||||
layoutParams.height = (screenWidth * 300) / 1000
|
||||
ivThumbnail.layoutParams = layoutParams
|
||||
}
|
||||
ivThumbnail.setOnClickListener { itemClick(data) }
|
||||
}
|
||||
|
||||
override fun getLayoutId(viewType: Int): Int {
|
||||
return R.layout.item_event_slider
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package kr.co.vividnext.sodalive.live.now
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
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.ItemLiveNowBinding
|
||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||
import kr.co.vividnext.sodalive.live.GetRoomListResponse
|
||||
|
||||
class LiveNowAdapter(
|
||||
private val onClick: (GetRoomListResponse) -> Unit
|
||||
) : RecyclerView.Adapter<LiveNowAdapter.ViewHolder>() {
|
||||
|
||||
var items = mutableListOf<GetRoomListResponse>()
|
||||
|
||||
inner class ViewHolder(
|
||||
private val binding: ItemLiveNowBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(item: GetRoomListResponse) {
|
||||
binding.ivCover.load(item.coverImageUrl) {
|
||||
crossfade(true)
|
||||
placeholder(R.drawable.bg_placeholder)
|
||||
transformations(RoundedCornersTransformation(4.7f.dpToPx()))
|
||||
}
|
||||
binding.tvManager.text = item.managerNickname
|
||||
binding.tvNumberOfMembers.text = "${item.numberOfParticipate}"
|
||||
binding.ivLock.visibility = if (item.isPrivateRoom) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
|
||||
if (item.price > 0) {
|
||||
binding.tvPrice.text = "유료"
|
||||
binding.tvPrice.setBackgroundResource(R.drawable.bg_round_corner_10_881609)
|
||||
} else {
|
||||
binding.tvPrice.text = "무료"
|
||||
binding.tvPrice.setBackgroundResource(R.drawable.bg_round_corner_10_643bc8)
|
||||
}
|
||||
|
||||
binding.iv19.visibility = if (item.isAdult) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
|
||||
binding.root.setOnClickListener { onClick(item) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
|
||||
ItemLiveNowBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(items[position])
|
||||
}
|
||||
|
||||
override fun getItemCount() = items.count()
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun clear() {
|
||||
items.clear()
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package kr.co.vividnext.sodalive.live.recommend
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class GetRecommendLiveResponse(
|
||||
@SerializedName("imageUrl")
|
||||
val imageUrl: String,
|
||||
@SerializedName("creatorId")
|
||||
val creatorId: Long
|
||||
)
|
|
@ -0,0 +1,25 @@
|
|||
package kr.co.vividnext.sodalive.live.recommend
|
||||
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import kr.co.vividnext.sodalive.live.recommend_channel.GetRecommendChannelResponse
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
|
||||
interface LiveRecommendApi {
|
||||
@GET("/live/recommend")
|
||||
fun getRecommendLive(
|
||||
@Header("Authorization") authHeader: String
|
||||
): Flowable<ApiResponse<List<GetRecommendLiveResponse>>>
|
||||
|
||||
@GET("/live/recommend/channel")
|
||||
fun getRecommendChannelList(
|
||||
@Header("Authorization") authHeader: String
|
||||
): Flowable<ApiResponse<List<GetRecommendChannelResponse>>>
|
||||
|
||||
@GET("/live/following/channel")
|
||||
fun getFollowingChannelList(
|
||||
@Header("Authorization") authHeader: String
|
||||
): Single<ApiResponse<List<GetRecommendChannelResponse>>>
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package kr.co.vividnext.sodalive.live.recommend
|
||||
|
||||
class LiveRecommendRepository(private val api: LiveRecommendApi) {
|
||||
fun getRecommendLive(token: String) = api.getRecommendLive(authHeader = token)
|
||||
fun getRecommendChannelList(token: String) = api.getRecommendChannelList(authHeader = token)
|
||||
fun getFollowingChannelList(token: String) = api.getFollowingChannelList(authHeader = token)
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package kr.co.vividnext.sodalive.live.recommend
|
||||
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import coil.load
|
||||
import coil.transform.RoundedCornersTransformation
|
||||
import com.zhpan.bannerview.BaseBannerAdapter
|
||||
import com.zhpan.bannerview.BaseViewHolder
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||
|
||||
class RecommendLiveAdapter(
|
||||
private val itemWidth: Int,
|
||||
private val itemHeight: Int,
|
||||
private val onClick: (Long) -> Unit
|
||||
) : BaseBannerAdapter<GetRecommendLiveResponse>() {
|
||||
override fun bindData(
|
||||
holder: BaseViewHolder<GetRecommendLiveResponse>,
|
||||
data: GetRecommendLiveResponse,
|
||||
position: Int,
|
||||
pageSize: Int
|
||||
) {
|
||||
val ivRecommendLive = holder.findViewById<ImageView>(R.id.iv_recommend_live)
|
||||
val layoutParams = ivRecommendLive.layoutParams as FrameLayout.LayoutParams
|
||||
|
||||
layoutParams.width = itemWidth
|
||||
layoutParams.height = itemHeight
|
||||
|
||||
ivRecommendLive.load(data.imageUrl) {
|
||||
crossfade(true)
|
||||
placeholder(R.drawable.bg_placeholder)
|
||||
transformations(RoundedCornersTransformation(5.3f.dpToPx()))
|
||||
}
|
||||
ivRecommendLive.layoutParams = layoutParams
|
||||
ivRecommendLive.setOnClickListener { onClick(data.creatorId) }
|
||||
}
|
||||
|
||||
override fun getLayoutId(viewType: Int): Int {
|
||||
return R.layout.item_recommend_live
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package kr.co.vividnext.sodalive.live.recommend_channel
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class GetRecommendChannelResponse(
|
||||
@SerializedName("creatorId")
|
||||
val creatorId: Long,
|
||||
@SerializedName("nickname")
|
||||
val nickname: String,
|
||||
@SerializedName("profileImageUrl")
|
||||
val profileImageUrl: String,
|
||||
@SerializedName("isOnAir")
|
||||
val isOnAir: Boolean
|
||||
)
|
|
@ -0,0 +1,142 @@
|
|||
package kr.co.vividnext.sodalive.live.recommend_channel
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import coil.load
|
||||
import coil.transform.RoundedCornersTransformation
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.databinding.ItemRecommendChannelBinding
|
||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||
|
||||
class LiveRecommendChannelAdapter(
|
||||
private val onClick: (Long) -> Unit,
|
||||
private val onClickMore: () -> Unit,
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
var isFollowedCreatorLive = false
|
||||
|
||||
private val items = mutableListOf<GetRecommendChannelResponse>()
|
||||
|
||||
class FooterViewHolder(
|
||||
private val binding: ItemRecommendChannelBinding,
|
||||
private val onClickItem: () -> Unit
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind() {
|
||||
binding.ivRecommendChannel.setImageResource(R.drawable.btn_item_more)
|
||||
binding.tvRecommendChannelNickname.text = "더보기"
|
||||
|
||||
val layoutParams = binding.ivRecommendChannel.layoutParams as FrameLayout.LayoutParams
|
||||
layoutParams.width = 60f.dpToPx().toInt()
|
||||
layoutParams.height = 60f.dpToPx().toInt()
|
||||
|
||||
binding.ivRecommendChannel.layoutParams = layoutParams
|
||||
binding.ivRecommendChannelBg.layoutParams = layoutParams
|
||||
|
||||
binding.tvRecommendChannel.visibility = View.GONE
|
||||
binding.ivRecommendChannelBg.visibility = View.GONE
|
||||
binding.root.setOnClickListener { onClickItem() }
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val VIEW_TYPE = 1
|
||||
}
|
||||
}
|
||||
|
||||
class ViewHolder(
|
||||
private val binding: ItemRecommendChannelBinding,
|
||||
private val onClickItem: (Long) -> Unit
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(item: GetRecommendChannelResponse) {
|
||||
binding.ivRecommendChannel.load(item.profileImageUrl) {
|
||||
crossfade(true)
|
||||
placeholder(R.drawable.bg_placeholder)
|
||||
transformations(RoundedCornersTransformation(30f.dpToPx()))
|
||||
}
|
||||
binding.tvRecommendChannelNickname.text = item.nickname
|
||||
|
||||
val layoutParams = binding.ivRecommendChannel.layoutParams as FrameLayout.LayoutParams
|
||||
layoutParams.width = 60f.dpToPx().toInt()
|
||||
layoutParams.height = 60f.dpToPx().toInt()
|
||||
|
||||
binding.ivRecommendChannel.layoutParams = layoutParams
|
||||
binding.ivRecommendChannelBg.layoutParams = layoutParams
|
||||
|
||||
if (item.isOnAir) {
|
||||
binding.tvRecommendChannel.visibility = View.VISIBLE
|
||||
binding.ivRecommendChannelBg.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.tvRecommendChannel.visibility = View.GONE
|
||||
binding.ivRecommendChannelBg.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding.root.setOnClickListener { onClickItem(item.creatorId) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val VIEW_TYPE = 0
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return if (viewType == FooterViewHolder.VIEW_TYPE) {
|
||||
FooterViewHolder(
|
||||
ItemRecommendChannelBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
),
|
||||
onClickItem = onClickMore
|
||||
)
|
||||
} else {
|
||||
ViewHolder(
|
||||
ItemRecommendChannelBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
),
|
||||
onClickItem = onClick
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is FooterViewHolder) {
|
||||
holder.bind()
|
||||
} else {
|
||||
(holder as ViewHolder).bind(items[position])
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return if (isFollowedCreatorLive) {
|
||||
items.size + 1
|
||||
} else {
|
||||
items.size
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (position == items.size) {
|
||||
FooterViewHolder.VIEW_TYPE
|
||||
} else {
|
||||
ViewHolder.VIEW_TYPE
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun clear() {
|
||||
items.clear()
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun addItems(items: List<GetRecommendChannelResponse>) {
|
||||
this.items.addAll(items)
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
package kr.co.vividnext.sodalive.live.reservation
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
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.common.SharedPreferenceManager
|
||||
import kr.co.vividnext.sodalive.databinding.ItemLiveReservationBinding
|
||||
import kr.co.vividnext.sodalive.databinding.ItemMyLiveReservationBinding
|
||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||
import kr.co.vividnext.sodalive.extensions.moneyFormat
|
||||
import kr.co.vividnext.sodalive.live.GetRoomListResponse
|
||||
|
||||
class LiveReservationAdapter(
|
||||
private val isMain: Boolean = false,
|
||||
private val onClick: (GetRoomListResponse) -> Unit
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
var items = mutableListOf<GetRoomListResponse>()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return if (viewType == 1) {
|
||||
MyLiveViewHolder(
|
||||
ItemMyLiveReservationBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
} else {
|
||||
ViewHolder(
|
||||
ItemLiveReservationBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
if (isMyLive(item)) {
|
||||
(holder as MyLiveViewHolder).bind(item, position)
|
||||
} else {
|
||||
(holder as ViewHolder).bind(item)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = items.count()
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (isMyLive(items[position])) {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
private fun isMyLive(item: GetRoomListResponse) =
|
||||
item.managerId == SharedPreferenceManager.userId && isMain
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun clear() {
|
||||
items.clear()
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
inner class ViewHolder(
|
||||
private val binding: ItemLiveReservationBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(item: GetRoomListResponse) {
|
||||
binding.ivCover.load(item.coverImageUrl) {
|
||||
crossfade(true)
|
||||
placeholder(R.drawable.bg_placeholder)
|
||||
transformations(RoundedCornersTransformation(4.7f.dpToPx()))
|
||||
}
|
||||
binding.tvDate.text = item.beginDateTime
|
||||
binding.tvNickname.text = item.managerNickname
|
||||
binding.tvTitle.text = item.title
|
||||
binding.root.setOnClickListener { onClick(item) }
|
||||
binding.ivLock.visibility = if (item.isPrivateRoom) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
|
||||
if (item.isReservation) {
|
||||
binding.tvPrice.visibility = View.GONE
|
||||
binding.tvCompleteReservation.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.tvPrice.visibility = View.VISIBLE
|
||||
binding.tvCompleteReservation.visibility = View.GONE
|
||||
|
||||
binding.tvPrice.text = if (item.price <= 0) {
|
||||
"무료"
|
||||
} else {
|
||||
"${item.price.moneyFormat()}코인"
|
||||
}
|
||||
}
|
||||
|
||||
binding.iv19.visibility = if (item.isAdult) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class MyLiveViewHolder(
|
||||
private val binding: ItemMyLiveReservationBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(item: GetRoomListResponse, position: Int) {
|
||||
binding.tvMyLive.visibility = if (position == 0) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
binding.ivCover.load(item.coverImageUrl) {
|
||||
crossfade(true)
|
||||
placeholder(R.drawable.bg_placeholder)
|
||||
transformations(RoundedCornersTransformation(4f.dpToPx()))
|
||||
}
|
||||
binding.tvDate.text = item.beginDateTime
|
||||
binding.tvNickname.text = item.managerNickname
|
||||
binding.tvTitle.text = item.title
|
||||
binding.root.setOnClickListener { onClick(item) }
|
||||
|
||||
binding.ivLock.visibility = if (item.isPrivateRoom) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
|
||||
binding.iv19.visibility = if (item.isAdult) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package kr.co.vividnext.sodalive.live.room
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
enum class LiveRoomStatus {
|
||||
@SerializedName("NOW") NOW,
|
||||
@SerializedName("RESERVATION") RESERVATION
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package kr.co.vividnext.sodalive.settings.event
|
||||
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
import retrofit2.http.Query
|
||||
|
||||
interface EventApi {
|
||||
@GET("/event")
|
||||
fun getEvents(
|
||||
@Query("page") page: Int,
|
||||
@Query("size") size: Int,
|
||||
@Header("Authorization") authHeader: String
|
||||
): Flowable<ApiResponse<GetEventResponse>>
|
||||
|
||||
@GET("/event/popup")
|
||||
fun getEventPopup(@Header("Authorization") authHeader: String): Single<ApiResponse<EventItem>>
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package kr.co.vividnext.sodalive.settings.event
|
||||
|
||||
class EventRepository(private val api: EventApi) {
|
||||
fun getEvents(
|
||||
page: Int,
|
||||
size: Int,
|
||||
token: String
|
||||
) = api.getEvents(page, size, authHeader = token)
|
||||
|
||||
fun getEventPopup(token: String) = api.getEventPopup(authHeader = token)
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package kr.co.vividnext.sodalive.settings.event
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
data class GetEventResponse(
|
||||
@SerializedName("totalCount") val totalCount: Int,
|
||||
@SerializedName("eventList") val eventList: List<EventItem>
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
data class EventItem(
|
||||
@SerializedName("id") val id: Long,
|
||||
@SerializedName("thumbnailImageUrl") val thumbnailImageUrl: String,
|
||||
@SerializedName("detailImageUrl") val detailImageUrl: String? = null,
|
||||
@SerializedName("popupImageUrl") val popupImageUrl: String? = null,
|
||||
@SerializedName("link") val link: String? = null
|
||||
) : Parcelable
|
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 362 B |
After Width: | Height: | Size: 824 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 551 B |
After Width: | Height: | Size: 101 KiB |
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/color_533d89" />
|
||||
<corners android:radius="10dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/color_533d89" />
|
||||
</shape>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/color_643bc8" />
|
||||
<corners android:radius="10dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/color_643bc8" />
|
||||
</shape>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/color_881609" />
|
||||
<corners android:radius="10dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/color_881609" />
|
||||
</shape>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
<corners android:radius="33.3dp" />
|
||||
<stroke
|
||||
android:width="3dp"
|
||||
android:color="@color/color_9970ff" />
|
||||
</shape>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/color_2b2635" />
|
||||
<corners android:radius="4.7dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/color_2b2635" />
|
||||
</shape>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/color_9970ff" />
|
||||
<corners android:radius="4.7dp" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/color_9970ff" />
|
||||
</shape>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<gradient
|
||||
android:type="linear"
|
||||
android:startColor="#cc000000"
|
||||
android:endColor="#19000000"
|
||||
android:angle="90" />
|
||||
</shape>
|
|
@ -0,0 +1,170 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
|
@ -4,13 +4,83 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipe_refresh_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include
|
||||
android:id="@+id/layout_recommend_live"
|
||||
layout="@layout/layout_recommend_live"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:layout_marginTop="13.3dp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_how_to_use"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="21.3dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/img_how_to_use" />
|
||||
|
||||
<include
|
||||
android:id="@+id/layout_recommend_channel"
|
||||
layout="@layout/layout_live_recommend_channel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:layout_marginTop="40dp" />
|
||||
|
||||
<include
|
||||
android:id="@+id/layout_live_now"
|
||||
layout="@layout/layout_live_now"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="40dp" />
|
||||
|
||||
<com.zhpan.bannerview.BannerViewPager
|
||||
android:id="@+id/event_banner_slider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="40dp" />
|
||||
|
||||
<com.zhpan.indicator.IndicatorView
|
||||
android:id="@+id/indicator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="6.7dp" />
|
||||
|
||||
<include
|
||||
android:id="@+id/layout_live_reservation"
|
||||
layout="@layout/layout_live_reservation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="40dp" />
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_make_room"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16.7dp"
|
||||
android:layout_marginBottom="16.7dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/btn_make_live"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:text="라이브"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_thumbnail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@null"
|
||||
android:scaleType="centerCrop" />
|
||||
|
||||
</FrameLayout>
|
|
@ -0,0 +1,97 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="133.3dp"
|
||||
android:layout_height="176.7dp"
|
||||
android:background="@color/black">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_cover"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@null"
|
||||
android:scaleType="centerCrop"
|
||||
tools:src="@drawable/ic_launcher_background" />
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:background="@drawable/gradient_live_room_item"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_price"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="3.3dp"
|
||||
android:layout_marginTop="3.3dp"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:paddingHorizontal="7.3dp"
|
||||
android:paddingVertical="4dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:background="@drawable/bg_round_corner_10_881609"
|
||||
tools:text="유료" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_19"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="3.3dp"
|
||||
android:layout_marginEnd="3.3dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_19"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_lock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="3.3dp"
|
||||
android:layout_marginEnd="3.3dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_lock"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toStartOf="@+id/iv_19"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_number_of_members"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6.7dp"
|
||||
android:layout_marginBottom="6.7dp"
|
||||
android:gravity="center_vertical|start"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="13.3sp"
|
||||
app:drawableStartCompat="@drawable/ic_avatar"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/tv_manager"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="12" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_manager"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="6.7dp"
|
||||
android:layout_marginBottom="6.7dp"
|
||||
android:ellipsize="end"
|
||||
android:ems="4"
|
||||
android:gravity="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="13.3sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:text="자입니다sss" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,127 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="131dp"
|
||||
tools:background="@color/black">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_cover"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="116.7dp"
|
||||
android:contentDescription="@null"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_19"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="3.3dp"
|
||||
android:layout_marginTop="3.3dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_19"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_room_info"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginEnd="13.3dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toStartOf="@+id/iv_lock"
|
||||
app:layout_constraintStart_toEndOf="@+id/iv_cover"
|
||||
app:layout_constraintTop_toTopOf="@+id/iv_cover"
|
||||
app:layout_goneMarginEnd="20dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:textColor="@color/color_ffd300"
|
||||
android:textSize="9.3sp"
|
||||
tools:ignore="SmallSp"
|
||||
tools:text="2021.06.20 SUN 10:00 PM" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_nickname"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:textColor="@color/color_bbbbbb"
|
||||
android:textSize="11.3sp"
|
||||
tools:text="사냥꾼 1004" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:maxLines="2"
|
||||
android:textColor="@color/color_e2e2e2"
|
||||
android:textSize="15.3sp"
|
||||
tools:text="여자들이 좋아하는 남자 스타일은?" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_lock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="13.3dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_lock"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/iv_cover" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_price"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
android:gravity="start|center_vertical"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/iv_cover"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/iv_cover">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_price"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:textColor="@color/color_7fe2e2e2"
|
||||
android:textSize="12sp"
|
||||
tools:text="300코인" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_complete_reservation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_round_corner_10_533d89"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:paddingHorizontal="7.5dp"
|
||||
android:paddingVertical="4.3dp"
|
||||
android:text="예약완료"
|
||||
android:textColor="@color/color_d2d2d2"
|
||||
android:textSize="11.3sp"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/color_88909090"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,113 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
tools:background="@color/black">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_my_live"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:drawablePadding="8dp"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="내가 개설한 라이브"
|
||||
android:textColor="@color/color_9970ff"
|
||||
android:textSize="16sp"
|
||||
app:drawableStartCompat="@drawable/ic_mic_colored" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_round_corner_8_transparent_9970ff"
|
||||
android:orientation="horizontal"
|
||||
android:padding="1dp">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/ll_cover"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_cover"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="116.7dp"
|
||||
android:contentDescription="@null"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_19"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="3.3dp"
|
||||
android:layout_marginTop="3.3dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_19"
|
||||
android:visibility="gone" />
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="30dp"
|
||||
android:layout_toStartOf="@+id/iv_lock"
|
||||
android:layout_toEndOf="@+id/ll_cover"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:textColor="@color/color_ffd300"
|
||||
android:textSize="9.3sp"
|
||||
tools:ignore="SmallSp"
|
||||
tools:text="2021.06.20 SUN 10:00 PM" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_nickname"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:textColor="@color/color_bbbbbb"
|
||||
android:textSize="11.3sp"
|
||||
tools:text="사냥꾼 1004" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:maxLines="2"
|
||||
android:textColor="@color/color_e2e2e2"
|
||||
android:textSize="15.3sp"
|
||||
tools:text="여자들이 좋아하는 남자 스타일은?" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_lock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginTop="13.3dp"
|
||||
android:layout_marginEnd="13.3dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_lock"
|
||||
android:visibility="gone" />
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="13dp"
|
||||
android:background="@color/color_88909090" />
|
||||
</LinearLayout>
|
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_recommend_channel"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_recommend_channel_bg"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/bg_round_corner_33_3_transparent_9970ff" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_recommend_channel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:background="@drawable/bg_round_corner_6_7_9970ff"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:paddingHorizontal="5.7dp"
|
||||
android:paddingVertical="2.7dp"
|
||||
android:text="LIVE"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="8.7sp"
|
||||
tools:ignore="SmallSp" />
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_recommend_channel_nickname"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="11.3dp"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:lines="1"
|
||||
android:textColor="@color/color_bbbbbb"
|
||||
android:textSize="11.3sp"
|
||||
tools:text="검은사신" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_recommend_live"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:scaleType="centerCrop" />
|
||||
|
||||
</FrameLayout>
|
|
@ -0,0 +1,100 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="13.3dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="지금 "
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textSize="18.3sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="라이브중"
|
||||
android:textColor="@color/color_ff5c49"
|
||||
android:textSize="18.3sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_all_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:fontFamily="@font/gmarket_sans_light"
|
||||
android:text="전체보기"
|
||||
android:textColor="@color/color_bbbbbb"
|
||||
android:textSize="11.3sp" />
|
||||
</RelativeLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_suda_now"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="28.3dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_no_items"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:layout_marginTop="28.3dp"
|
||||
android:background="@drawable/bg_round_corner_4_7_2b2635"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingVertical="16.7dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_no_item" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="10dp"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:gravity="center"
|
||||
android:text="🙀지금 참여가능한 라이브가 없습니다.\n직접 라이브를 만들어 보세요!"
|
||||
android:textColor="@color/color_bbbbbb"
|
||||
android:textSize="10.7sp"
|
||||
tools:ignore="SmallSp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_make_room"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_round_corner_4_7_9970ff"
|
||||
android:drawablePadding="8.3dp"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:paddingHorizontal="51.7dp"
|
||||
android:paddingVertical="8.3dp"
|
||||
android:text="라이브 만들기"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="13.3sp"
|
||||
app:drawableStartCompat="@drawable/ic_plus_no_bg" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,88 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_title_1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="visible"
|
||||
android:layout_centerVertical="true"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="추천 "
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textSize="18.3sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="채널"
|
||||
android:textColor="@color/color_9970ff"
|
||||
android:textSize="18.3sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_title_2"
|
||||
android:layout_width="match_parent"
|
||||
android:visibility="gone"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="팔로잉 "
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textSize="18.3sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="채널"
|
||||
android:textColor="@color/color_9970ff"
|
||||
android:textSize="18.3sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="6.7dp"
|
||||
android:layout_toStartOf="@+id/iv_switch"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:text="팔로잉 채널"
|
||||
android:textColor="@color/color_777777"
|
||||
android:textSize="13.3sp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_switch"
|
||||
android:layout_width="33.3dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/btn_toggle_off_big" />
|
||||
</RelativeLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_recommend_channel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="21.3dp" />
|
||||
</LinearLayout>
|
|
@ -0,0 +1,101 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="13.3dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="지금 "
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textSize="18.3sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="예약중"
|
||||
android:textColor="@color/color_9970ff"
|
||||
android:textSize="18.3sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_all_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:fontFamily="@font/gmarket_sans_light"
|
||||
android:text="전체보기"
|
||||
android:textColor="@color/color_bbbbbb"
|
||||
android:textSize="11.3sp" />
|
||||
</RelativeLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_suda_reservation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="28.3dp"
|
||||
android:nestedScrollingEnabled="false"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_no_items"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="13.3dp"
|
||||
android:layout_marginVertical="28.3dp"
|
||||
android:background="@drawable/bg_round_corner_4_7_2b2635"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingVertical="16.7dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_no_item" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="10dp"
|
||||
android:fontFamily="@font/gmarket_sans_medium"
|
||||
android:gravity="center"
|
||||
android:text="지금 예약중인 라이브가 없습니다.\n직접 라이브를 만들어 보세요!"
|
||||
android:textColor="@color/color_bbbbbb"
|
||||
android:textSize="10.7sp"
|
||||
tools:ignore="SmallSp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_make_room"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_round_corner_4_7_9970ff"
|
||||
android:drawablePadding="8.3dp"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:gravity="center"
|
||||
android:paddingHorizontal="51.7dp"
|
||||
android:paddingVertical="8.3dp"
|
||||
android:text="라이브 만들기"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="13.3sp"
|
||||
app:drawableStartCompat="@drawable/ic_plus_no_bg" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="추천 "
|
||||
android:textColor="@color/color_ff5c49"
|
||||
android:textSize="18.3sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/gmarket_sans_bold"
|
||||
android:text="라이브"
|
||||
android:textColor="@color/color_eeeeee"
|
||||
android:textSize="18.3sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.zhpan.bannerview.BannerViewPager
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="26.7dp" />
|
||||
|
||||
<com.zhpan.indicator.IndicatorView
|
||||
android:id="@+id/indicator2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="6.7dp" />
|
||||
</LinearLayout>
|
|
@ -13,8 +13,17 @@
|
|||
<color name="color_a0e2ff">#A0E2FF</color>
|
||||
<color name="color_ecfaff">#ECFAFF</color>
|
||||
<color name="color_111111">#111111</color>
|
||||
<color name="color_ff5c49">#FF5C49</color>
|
||||
<color name="color_2b2635">#2b2635</color>
|
||||
<color name="color_ffd300">#FFD300</color>
|
||||
<color name="color_e2e2e2">#E2E2E2</color>
|
||||
<color name="color_d2d2d2">#D2D2D2</color>
|
||||
<color name="color_533d89">#533D89</color>
|
||||
<color name="color_643bc8">#643BC8</color>
|
||||
<color name="color_881609">#881609</color>
|
||||
|
||||
<color name="color_b3909090">#B3909090</color>
|
||||
<color name="color_88909090">#88909090</color>
|
||||
<color name="color_339970ff">#339970FF</color>
|
||||
<color name="color_7fe2e2e2">#7FE2E2E2</color>
|
||||
</resources>
|
||||
|
|