feat: 메인 홈
- 오직 보이스온에서만 UI 추가
This commit is contained in:
@@ -67,7 +67,7 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::infl
|
|||||||
|
|
||||||
private lateinit var homeContentAdapter: HomeContentAdapter
|
private lateinit var homeContentAdapter: HomeContentAdapter
|
||||||
private lateinit var contentBannerAdapter: AudioContentMainBannerAdapter
|
private lateinit var contentBannerAdapter: AudioContentMainBannerAdapter
|
||||||
private lateinit var seriesAdapter: HomeSeriesAdapter
|
private lateinit var originalSeriesAdapter: HomeSeriesAdapter
|
||||||
|
|
||||||
private val handler = Handler(Looper.getMainLooper())
|
private val handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
@@ -157,6 +157,7 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::infl
|
|||||||
setupSectionCreator()
|
setupSectionCreator()
|
||||||
setupLatestContent()
|
setupLatestContent()
|
||||||
setupContentBanner()
|
setupContentBanner()
|
||||||
|
setupOriginalSeries()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupLiveView() {
|
private fun setupLiveView() {
|
||||||
@@ -525,6 +526,73 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::infl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupOriginalSeries() {
|
||||||
|
val spSectionTitle = SpannableString(binding.tvSeriesOriginal.text)
|
||||||
|
spSectionTitle.setSpan(
|
||||||
|
ForegroundColorSpan(
|
||||||
|
ContextCompat.getColor(
|
||||||
|
requireContext(),
|
||||||
|
R.color.color_3bb9f1
|
||||||
|
)
|
||||||
|
),
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
|
)
|
||||||
|
binding.tvSeriesOriginal.text = spSectionTitle
|
||||||
|
|
||||||
|
originalSeriesAdapter = HomeSeriesAdapter {
|
||||||
|
startActivity(
|
||||||
|
Intent(requireContext(), SeriesDetailActivity::class.java).apply {
|
||||||
|
putExtra(Constants.EXTRA_SERIES_ID, it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val recyclerView = binding.rvSeriesOriginal
|
||||||
|
recyclerView.layoutManager = LinearLayoutManager(
|
||||||
|
context,
|
||||||
|
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 = 0
|
||||||
|
outRect.right = 8f.dpToPx().toInt()
|
||||||
|
}
|
||||||
|
originalSeriesAdapter.itemCount - 1 -> {
|
||||||
|
outRect.left = 8f.dpToPx().toInt()
|
||||||
|
outRect.right = 0
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
outRect.left = 8f.dpToPx().toInt()
|
||||||
|
outRect.right = 8f.dpToPx().toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
recyclerView.adapter = originalSeriesAdapter
|
||||||
|
|
||||||
|
viewModel.originalAudioDramaListLiveData.observe(viewLifecycleOwner) {
|
||||||
|
if (it.isNotEmpty()) {
|
||||||
|
binding.llSeriesOriginal.visibility = View.VISIBLE
|
||||||
|
originalSeriesAdapter.addItems(it)
|
||||||
|
} else {
|
||||||
|
binding.llSeriesOriginal.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun bindData() {
|
private fun bindData() {
|
||||||
viewModel.isLoading.observe(viewLifecycleOwner) {
|
viewModel.isLoading.observe(viewLifecycleOwner) {
|
||||||
if (it) {
|
if (it) {
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package kr.co.vividnext.sodalive.home
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.CenterCrop
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
||||||
|
import com.bumptech.glide.request.RequestOptions
|
||||||
|
import kr.co.vividnext.sodalive.audio_content.series.GetSeriesListResponse
|
||||||
|
import kr.co.vividnext.sodalive.databinding.ItemHomeSeriesBinding
|
||||||
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
|
|
||||||
|
class HomeSeriesAdapter(
|
||||||
|
private val onClickItem: (Long) -> Unit
|
||||||
|
) : RecyclerView.Adapter<HomeSeriesAdapter.ViewHolder>() {
|
||||||
|
|
||||||
|
val items = mutableListOf<GetSeriesListResponse.SeriesListItem>()
|
||||||
|
|
||||||
|
inner class ViewHolder(
|
||||||
|
private val context: Context,
|
||||||
|
private val binding: ItemHomeSeriesBinding
|
||||||
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
fun bind(item: GetSeriesListResponse.SeriesListItem) {
|
||||||
|
Glide
|
||||||
|
.with(context)
|
||||||
|
.load(item.coverImage)
|
||||||
|
.apply(
|
||||||
|
RequestOptions().transform(
|
||||||
|
CenterCrop(),
|
||||||
|
RoundedCorners(16f.dpToPx().toInt())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.into(binding.ivCover)
|
||||||
|
|
||||||
|
binding.tvTitle.text = item.title
|
||||||
|
binding.tvNickname.text = item.creator.nickname
|
||||||
|
binding.tvSeriesContentCount.text = "총 ${item.numberOfContent}화"
|
||||||
|
binding.tvNew.visibility = if (item.isNew) {
|
||||||
|
View.VISIBLE
|
||||||
|
} else {
|
||||||
|
View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.tvPopular.visibility = if (item.isPopular) {
|
||||||
|
View.VISIBLE
|
||||||
|
} else {
|
||||||
|
View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.isComplete) {
|
||||||
|
binding.tvComplete.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
binding.tvComplete.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.root.setOnClickListener { onClickItem(item.seriesId) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
|
||||||
|
parent.context,
|
||||||
|
ItemHomeSeriesBinding.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 addItems(items: List<GetSeriesListResponse.SeriesListItem>) {
|
||||||
|
this.items.addAll(items)
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isVisibleRecyclerView(): Boolean {
|
||||||
|
return items.isNotEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="#b2000000" />
|
||||||
|
<corners
|
||||||
|
android:bottomRightRadius="16dp"
|
||||||
|
android:topLeftRadius="16dp" />
|
||||||
|
</shape>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="#ef5247" />
|
||||||
|
<corners
|
||||||
|
android:bottomRightRadius="16dp"
|
||||||
|
android:topLeftRadius="16dp" />
|
||||||
|
</shape>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<gradient
|
||||||
|
android:type="linear"
|
||||||
|
android:angle="270"
|
||||||
|
android:startColor="#0001B1"
|
||||||
|
android:centerColor="#0001B1"
|
||||||
|
android:endColor="#3B5FF1"
|
||||||
|
android:centerY="0.24" />
|
||||||
|
|
||||||
|
<corners
|
||||||
|
android:bottomRightRadius="16dp"
|
||||||
|
android:topLeftRadius="16dp" />
|
||||||
|
</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="39dp" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="@color/white" />
|
||||||
|
</shape>
|
||||||
112
app/src/main/res/layout/item_home_series.xml
Normal file
112
app/src/main/res/layout/item_home_series.xml
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
<?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="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_cover"
|
||||||
|
android:layout_width="160dp"
|
||||||
|
android:layout_height="227dp"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:src="@drawable/ic_launcher_background" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/iv_cover"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/iv_cover">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_popular"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/bg_left_top_right_bottom_round_corner_16_ef5247"
|
||||||
|
android:fontFamily="@font/pretendard_regular"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
|
android:paddingVertical="3dp"
|
||||||
|
android:text="인기"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_new"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/bg_left_top_right_bottom_round_corner_16_gradient"
|
||||||
|
android:fontFamily="@font/pretendard_regular"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
|
android:paddingVertical="3dp"
|
||||||
|
android:text="신작"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_complete"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/bg_left_top_right_bottom_round_corner_16_black_70"
|
||||||
|
android:fontFamily="@font/pretendard_regular"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
|
android:paddingVertical="3dp"
|
||||||
|
android:text="완결"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_series_content_count"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:background="@drawable/bg_round_corner_39_transparent_white"
|
||||||
|
android:fontFamily="@font/pretendard_regular"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
|
android:paddingVertical="3dp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="12sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/iv_cover"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/iv_cover"
|
||||||
|
tools:text="총 24화" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:fontFamily="@font/pretendard_regular"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="#b0bec5"
|
||||||
|
android:textSize="18sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/iv_cover"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/iv_cover"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/iv_cover"
|
||||||
|
tools:text="제목, 관심사,프로필+방장, 참여인원(어딘가..)" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_nickname"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:fontFamily="@font/pretendard_regular"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="#78909C"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/iv_cover"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/iv_cover"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/tv_title"
|
||||||
|
tools:text="설린" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
Reference in New Issue
Block a user