feat: 메인 홈
- 인기 크리에이터 UI 추가
This commit is contained in:
@@ -22,5 +22,6 @@ data class GetExplorerSectionCreatorResponse(
|
|||||||
@SerializedName("id") val id: Long,
|
@SerializedName("id") val id: Long,
|
||||||
@SerializedName("nickname") val nickname: String,
|
@SerializedName("nickname") val nickname: String,
|
||||||
@SerializedName("tags") val tags: String,
|
@SerializedName("tags") val tags: String,
|
||||||
@SerializedName("profileImageUrl") val profileImageUrl: String
|
@SerializedName("profileImageUrl") val profileImageUrl: String,
|
||||||
|
@SerializedName("followerCount") val followerCount: Int
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
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.CircleCrop
|
||||||
|
import com.bumptech.glide.request.RequestOptions
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
import kr.co.vividnext.sodalive.databinding.ItemHomeCreatorBinding
|
||||||
|
import kr.co.vividnext.sodalive.explorer.GetExplorerSectionCreatorResponse
|
||||||
|
import kr.co.vividnext.sodalive.extensions.moneyFormat
|
||||||
|
|
||||||
|
class CreatorRankingAdapter(
|
||||||
|
private val onClickItem: (Long) -> Unit
|
||||||
|
) : RecyclerView.Adapter<CreatorRankingAdapter.ViewHolder>() {
|
||||||
|
|
||||||
|
private val items = mutableListOf<GetExplorerSectionCreatorResponse>()
|
||||||
|
|
||||||
|
inner class ViewHolder(
|
||||||
|
private val context: Context,
|
||||||
|
private val binding: ItemHomeCreatorBinding
|
||||||
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
fun bind(item: GetExplorerSectionCreatorResponse, index: Int) {
|
||||||
|
binding.root.setOnClickListener { onClickItem(item.id) }
|
||||||
|
|
||||||
|
Glide
|
||||||
|
.with(context)
|
||||||
|
.load(item.profileImageUrl)
|
||||||
|
.apply(
|
||||||
|
RequestOptions().transform(
|
||||||
|
CircleCrop()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.into(binding.ivProfile)
|
||||||
|
|
||||||
|
binding.tvNickname.text = item.nickname
|
||||||
|
binding.tvFollower.text = item.followerCount.moneyFormat()
|
||||||
|
|
||||||
|
when (index) {
|
||||||
|
0 -> {
|
||||||
|
binding.ivCrown.setImageResource(R.drawable.rank1)
|
||||||
|
binding.ivCrown.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
1 -> {
|
||||||
|
binding.ivCrown.setImageResource(R.drawable.rank2)
|
||||||
|
binding.ivCrown.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
2 -> {
|
||||||
|
binding.ivCrown.setImageResource(R.drawable.rank3)
|
||||||
|
binding.ivCrown.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
binding.ivCrown.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
|
||||||
|
parent.context,
|
||||||
|
ItemHomeCreatorBinding.inflate(
|
||||||
|
LayoutInflater.from(parent.context),
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
holder.bind(items[position], index = position)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount() = items.size
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
fun addItems(items: List<GetExplorerSectionCreatorResponse>) {
|
||||||
|
this.items.addAll(items)
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ import kr.co.vividnext.sodalive.common.Constants
|
|||||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
import kr.co.vividnext.sodalive.databinding.FragmentHomeBinding
|
import kr.co.vividnext.sodalive.databinding.FragmentHomeBinding
|
||||||
|
import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity
|
||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
import kr.co.vividnext.sodalive.live.LiveViewModel
|
import kr.co.vividnext.sodalive.live.LiveViewModel
|
||||||
import kr.co.vividnext.sodalive.live.room.LiveRoomActivity
|
import kr.co.vividnext.sodalive.live.room.LiveRoomActivity
|
||||||
@@ -40,6 +41,7 @@ import java.text.SimpleDateFormat
|
|||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
|
@OptIn(UnstableApi::class)
|
||||||
class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::inflate) {
|
class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::inflate) {
|
||||||
private val viewModel: HomeViewModel by inject()
|
private val viewModel: HomeViewModel by inject()
|
||||||
private val liveViewModel: LiveViewModel by inject()
|
private val liveViewModel: LiveViewModel by inject()
|
||||||
@@ -47,6 +49,7 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::infl
|
|||||||
private lateinit var loadingDialog: LoadingDialog
|
private lateinit var loadingDialog: LoadingDialog
|
||||||
|
|
||||||
private lateinit var liveAdapter: HomeLiveAdapter
|
private lateinit var liveAdapter: HomeLiveAdapter
|
||||||
|
private lateinit var creatorRankingAdapter: CreatorRankingAdapter
|
||||||
|
|
||||||
private val handler = Handler(Looper.getMainLooper())
|
private val handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
@@ -133,9 +136,10 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::infl
|
|||||||
}
|
}
|
||||||
|
|
||||||
setupLiveView()
|
setupLiveView()
|
||||||
|
setupSectionCreator()
|
||||||
|
setupLatestContent()
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(UnstableApi::class)
|
|
||||||
private fun setupLiveView() {
|
private fun setupLiveView() {
|
||||||
val spSectionTitle = SpannableString(binding.tvLiveTitle.text)
|
val spSectionTitle = SpannableString(binding.tvLiveTitle.text)
|
||||||
spSectionTitle.setSpan(
|
spSectionTitle.setSpan(
|
||||||
@@ -191,17 +195,17 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::infl
|
|||||||
when (parent.getChildAdapterPosition(view)) {
|
when (parent.getChildAdapterPosition(view)) {
|
||||||
0 -> {
|
0 -> {
|
||||||
outRect.left = 0
|
outRect.left = 0
|
||||||
outRect.right = 16f.dpToPx().toInt()
|
outRect.right = 8f.dpToPx().toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
liveAdapter.itemCount - 1 -> {
|
liveAdapter.itemCount - 1 -> {
|
||||||
outRect.left = 16f.dpToPx().toInt()
|
outRect.left = 8f.dpToPx().toInt()
|
||||||
outRect.right = 0
|
outRect.right = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
outRect.left = 16f.dpToPx().toInt()
|
outRect.left = 8f.dpToPx().toInt()
|
||||||
outRect.right = 16f.dpToPx().toInt()
|
outRect.right = 8f.dpToPx().toInt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,6 +223,87 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::infl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setupSectionCreator() {
|
||||||
|
val spSectionTitle = SpannableString(binding.tvFamousCreatorTitle.text)
|
||||||
|
spSectionTitle.setSpan(
|
||||||
|
ForegroundColorSpan(
|
||||||
|
ContextCompat.getColor(
|
||||||
|
requireContext(),
|
||||||
|
R.color.color_3bb9f1
|
||||||
|
)
|
||||||
|
),
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
|
)
|
||||||
|
binding.tvFamousCreatorTitle.text = spSectionTitle
|
||||||
|
|
||||||
|
creatorRankingAdapter = CreatorRankingAdapter {
|
||||||
|
if (SharedPreferenceManager.token.isNotBlank()) {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
requireActivity(),
|
||||||
|
UserProfileActivity::class.java
|
||||||
|
).apply {
|
||||||
|
putExtra(Constants.EXTRA_USER_ID, it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(requireActivity() as MainActivity).showLoginActivity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val recyclerView = binding.rvFamousCreator
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
creatorRankingAdapter.itemCount - 1 -> {
|
||||||
|
outRect.left = 8f.dpToPx().toInt()
|
||||||
|
outRect.right = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
outRect.left = 8f.dpToPx().toInt()
|
||||||
|
outRect.right = 8f.dpToPx().toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
recyclerView.adapter = creatorRankingAdapter
|
||||||
|
|
||||||
|
viewModel.creatorRankingLiveData.observe(viewLifecycleOwner) {
|
||||||
|
if (it.isNotEmpty()) {
|
||||||
|
binding.llFamousCreator.visibility = View.VISIBLE
|
||||||
|
creatorRankingAdapter.addItems(it)
|
||||||
|
} else {
|
||||||
|
binding.llFamousCreator.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupLatestContent() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private fun bindData() {
|
private fun bindData() {
|
||||||
viewModel.isLoading.observe(viewLifecycleOwner) {
|
viewModel.isLoading.observe(viewLifecycleOwner) {
|
||||||
if (it) {
|
if (it) {
|
||||||
|
|||||||
BIN
app/src/main/res/drawable-mdpi/rank1.png
Normal file
BIN
app/src/main/res/drawable-mdpi/rank1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
app/src/main/res/drawable-mdpi/rank2.png
Normal file
BIN
app/src/main/res/drawable-mdpi/rank2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
BIN
app/src/main/res/drawable-mdpi/rank3.png
Normal file
BIN
app/src/main/res/drawable-mdpi/rank3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
9
app/src/main/res/drawable/bg_home_creator.xml
Normal file
9
app/src/main/res/drawable/bg_home_creator.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<corners android:radius="16dp" />
|
||||||
|
<gradient
|
||||||
|
android:angle="-45"
|
||||||
|
android:endColor="#2A339D"
|
||||||
|
android:startColor="#5ACDE1"
|
||||||
|
android:type="linear" />
|
||||||
|
</shape>
|
||||||
58
app/src/main/res/layout/item_home_creator.xml
Normal file
58
app/src/main/res/layout/item_home_creator.xml
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="133dp"
|
||||||
|
android:layout_height="188dp"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:background="@drawable/bg_home_creator"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_profile"
|
||||||
|
android:layout_width="70dp"
|
||||||
|
android:layout_height="70dp"
|
||||||
|
android:contentDescription="@null" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_nickname"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:fontFamily="@font/pretendard_regular"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="18sp"
|
||||||
|
tools:text="도화" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:fontFamily="@font/pretendard_regular"
|
||||||
|
android:text="팔로워"
|
||||||
|
android:textColor="#78909C"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_follower"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:fontFamily="@font/pretendard_regular"
|
||||||
|
android:textColor="#78909C"
|
||||||
|
android:textSize="14sp"
|
||||||
|
tools:text="111" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_crown"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
tools:src="@drawable/rank1" />
|
||||||
|
</RelativeLayout>
|
||||||
Reference in New Issue
Block a user