feat: 메인 라이브
- 최근 종료한 라이브 UI 추가
@@ -0,0 +1,13 @@
|
|||||||
|
package kr.co.vividnext.sodalive.live
|
||||||
|
|
||||||
|
import androidx.annotation.Keep
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
data class GetLatestFinishedLiveResponse(
|
||||||
|
@SerializedName("memberId") val memberId: Long,
|
||||||
|
@SerializedName("nickname") val nickname: String,
|
||||||
|
@SerializedName("profileImageUrl") val profileImageUrl: String,
|
||||||
|
@SerializedName("title") val title: String,
|
||||||
|
@SerializedName("timeAgo") val timeAgo: String
|
||||||
|
)
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package kr.co.vividnext.sodalive.live
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.request.RequestOptions
|
||||||
|
import kr.co.vividnext.sodalive.databinding.ItemLatestFinishedLiveBinding
|
||||||
|
|
||||||
|
class LatestFinishedLiveAdapter(
|
||||||
|
private val onClick: (Long) -> Unit
|
||||||
|
) : RecyclerView.Adapter<LatestFinishedLiveAdapter.ViewHolder>() {
|
||||||
|
|
||||||
|
private val items = mutableListOf<GetLatestFinishedLiveResponse>()
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: android.view.ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
return ViewHolder(
|
||||||
|
parent.context,
|
||||||
|
ItemLatestFinishedLiveBinding.inflate(
|
||||||
|
android.view.LayoutInflater.from(parent.context),
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
holder.bind(items[position])
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = items.count()
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
fun addItems(items: List<GetLatestFinishedLiveResponse>) {
|
||||||
|
this.items.clear()
|
||||||
|
this.items.addAll(items)
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class ViewHolder(
|
||||||
|
private val context: Context,
|
||||||
|
private val binding: ItemLatestFinishedLiveBinding
|
||||||
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
fun bind(item: GetLatestFinishedLiveResponse) {
|
||||||
|
Glide
|
||||||
|
.with(context)
|
||||||
|
.load(item.profileImageUrl)
|
||||||
|
.apply(RequestOptions.circleCropTransform())
|
||||||
|
.into(binding.ivProfile)
|
||||||
|
|
||||||
|
binding.tvNickname.text = item.nickname
|
||||||
|
binding.tvTimeAgo.text = item.timeAgo
|
||||||
|
binding.tvTitle.text = item.title
|
||||||
|
binding.root.setOnClickListener { onClick(item.memberId) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -233,4 +233,9 @@ interface LiveApi {
|
|||||||
@Path("id") id: Long,
|
@Path("id") id: Long,
|
||||||
@Header("Authorization") authHeader: String
|
@Header("Authorization") authHeader: String
|
||||||
): Single<ApiResponse<GetLiveRoomHeartListResponse>>
|
): Single<ApiResponse<GetLiveRoomHeartListResponse>>
|
||||||
|
|
||||||
|
@GET("/live/room/latest-finished-live")
|
||||||
|
fun getLatestFinishedLive(
|
||||||
|
@Header("Authorization") authHeader: String
|
||||||
|
): Flowable<ApiResponse<List<GetLatestFinishedLiveResponse>>>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ class LiveFragment : BaseFragment<FragmentLiveBinding>(FragmentLiveBinding::infl
|
|||||||
setupCommunityPost()
|
setupCommunityPost()
|
||||||
setupRecommendLive()
|
setupRecommendLive()
|
||||||
setupRecommendChannel()
|
setupRecommendChannel()
|
||||||
|
setupLatestFinishedLiveChannel()
|
||||||
setupLiveReservation()
|
setupLiveReservation()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,6 +349,60 @@ class LiveFragment : BaseFragment<FragmentLiveBinding>(FragmentLiveBinding::infl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupLatestFinishedLiveChannel() {
|
||||||
|
val adapter = LatestFinishedLiveAdapter {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
requireContext(),
|
||||||
|
UserProfileActivity::class.java
|
||||||
|
).apply {
|
||||||
|
putExtra(Constants.EXTRA_USER_ID, it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val recyclerView = binding.rvLatestFinishedLiveChannel
|
||||||
|
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 = 0
|
||||||
|
outRect.right = 8f.dpToPx().toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
liveRecommendChannelAdapter.itemCount - 1 -> {
|
||||||
|
outRect.left = 8f.dpToPx().toInt()
|
||||||
|
outRect.right = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
outRect.left = 8f.dpToPx().toInt()
|
||||||
|
outRect.right = 8f.dpToPx().toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
recyclerView.adapter = adapter
|
||||||
|
|
||||||
|
viewModel.latestFinishedLiveListLiveData.observe(viewLifecycleOwner) {
|
||||||
|
adapter.addItems(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun setupLiveNow() {
|
private fun setupLiveNow() {
|
||||||
binding
|
binding
|
||||||
|
|||||||
@@ -261,4 +261,8 @@ class LiveRepository(
|
|||||||
roomId,
|
roomId,
|
||||||
authHeader = token
|
authHeader = token
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun getLatestFinishedLive(token: String) = api.getLatestFinishedLive(
|
||||||
|
authHeader = token
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,14 @@ import kr.co.vividnext.sodalive.settings.event.GetEventResponse
|
|||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
data class LiveSummary(
|
data class LiveSummary(
|
||||||
@SerializedName("liveNow") val liveNow: ApiResponse<List<GetRoomListResponse>>,
|
@SerializedName("liveNow")
|
||||||
@SerializedName("liveReservation") val liveReservation: ApiResponse<List<GetRoomListResponse>>,
|
val liveNow: ApiResponse<List<GetRoomListResponse>>,
|
||||||
@SerializedName("event") val event: ApiResponse<GetEventResponse>,
|
@SerializedName("liveReservation")
|
||||||
@SerializedName("recommendLive") val recommendLive: ApiResponse<List<GetRecommendLiveResponse>>,
|
val liveReservation: ApiResponse<List<GetRoomListResponse>>,
|
||||||
|
@SerializedName("event")
|
||||||
|
val event: ApiResponse<GetEventResponse>,
|
||||||
|
@SerializedName("recommendLive")
|
||||||
|
val recommendLive: ApiResponse<List<GetRecommendLiveResponse>>,
|
||||||
|
@SerializedName("latestFinishedLive")
|
||||||
|
val latestFinishedLive: ApiResponse<List<GetLatestFinishedLiveResponse>>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -61,6 +61,11 @@ class LiveViewModel(
|
|||||||
val communityPostItemLiveData: LiveData<List<GetCommunityPostListResponse>>
|
val communityPostItemLiveData: LiveData<List<GetCommunityPostListResponse>>
|
||||||
get() = _communityPostItemLiveData
|
get() = _communityPostItemLiveData
|
||||||
|
|
||||||
|
private val _latestFinishedLiveListLiveData =
|
||||||
|
MutableLiveData<List<GetLatestFinishedLiveResponse>>()
|
||||||
|
val latestFinishedLiveListLiveData: LiveData<List<GetLatestFinishedLiveResponse>>
|
||||||
|
get() = _latestFinishedLiveListLiveData
|
||||||
|
|
||||||
var page = 1
|
var page = 1
|
||||||
var isLast = false
|
var isLast = false
|
||||||
private val pageSize = 10
|
private val pageSize = 10
|
||||||
@@ -157,6 +162,10 @@ class LiveViewModel(
|
|||||||
token = "Bearer ${SharedPreferenceManager.token}"
|
token = "Bearer ${SharedPreferenceManager.token}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val latestFinishedLive = repository.getLatestFinishedLive(
|
||||||
|
token = "Bearer ${SharedPreferenceManager.token}"
|
||||||
|
)
|
||||||
|
|
||||||
_isLoading.postValue(true)
|
_isLoading.postValue(true)
|
||||||
|
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
@@ -165,7 +174,9 @@ class LiveViewModel(
|
|||||||
liveReservation,
|
liveReservation,
|
||||||
event,
|
event,
|
||||||
recommendLive,
|
recommendLive,
|
||||||
) { t1, t2, t3, t4 -> LiveSummary(t1, t2, t3, t4) }
|
latestFinishedLive
|
||||||
|
) { t1, t2, t3, t4, t5 -> LiveSummary(t1, t2, t3, t4, t5) }
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{
|
{
|
||||||
val now = it.liveNow
|
val now = it.liveNow
|
||||||
@@ -223,6 +234,17 @@ class LiveViewModel(
|
|||||||
_recommendLiveData.postValue(emptyList())
|
_recommendLiveData.postValue(emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val latestFinishedLiveResponse = it.latestFinishedLive
|
||||||
|
if (
|
||||||
|
latestFinishedLiveResponse.success &&
|
||||||
|
latestFinishedLiveResponse.data != null
|
||||||
|
) {
|
||||||
|
val data = latestFinishedLiveResponse.data!!
|
||||||
|
_latestFinishedLiveListLiveData.postValue(data)
|
||||||
|
} else {
|
||||||
|
_latestFinishedLiveListLiveData.postValue(emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
_isLoading.postValue(false)
|
_isLoading.postValue(false)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
BIN
app/src/main/res/drawable-xxhdpi/rank1.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
app/src/main/res/drawable-xxhdpi/rank2.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
app/src/main/res/drawable-xxhdpi/rank3.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
@@ -1,5 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:shape="oval">
|
android:shape="oval">
|
||||||
<solid android:color="@color/color_3bb9f1" />
|
<solid android:color="@android:color/transparent" />
|
||||||
|
<stroke
|
||||||
|
android:width="3dp"
|
||||||
|
android:color="@color/color_3bb9f1" />
|
||||||
</shape>
|
</shape>
|
||||||
|
|||||||
32
app/src/main/res/drawable/img_live.xml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="60dp"
|
||||||
|
android:height="21dp"
|
||||||
|
android:viewportWidth="60"
|
||||||
|
android:viewportHeight="21">
|
||||||
|
<path
|
||||||
|
android:pathData="M11.046,1.579L49.846,1.579A9.04,9.04 0,0 1,58.886 10.619L58.886,10.619A9.04,9.04 0,0 1,49.846 19.659L11.046,19.659A9.04,9.04 0,0 1,2.006 10.619L2.006,10.619A9.04,9.04 0,0 1,11.046 1.579z"
|
||||||
|
android:fillColor="#263238"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M11.046,1.579L49.846,1.579A9.04,9.04 0,0 1,58.886 10.619L58.886,10.619A9.04,9.04 0,0 1,49.846 19.659L11.046,19.659A9.04,9.04 0,0 1,2.006 10.619L2.006,10.619A9.04,9.04 0,0 1,11.046 1.579z"
|
||||||
|
android:strokeWidth="2.2"
|
||||||
|
android:fillColor="#00000000">
|
||||||
|
<aapt:attr name="android:strokeColor">
|
||||||
|
<gradient
|
||||||
|
android:startX="30.446"
|
||||||
|
android:startY="-14.749"
|
||||||
|
android:endX="30.446"
|
||||||
|
android:endY="20.759"
|
||||||
|
android:type="linear">
|
||||||
|
<item android:offset="0.236" android:color="#FF80D8FF"/>
|
||||||
|
<item android:offset="1" android:color="#FF6D5ED7"/>
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
<path
|
||||||
|
android:pathData="M16.746,10.619m-4.4,0a4.4,4.4 0,1 1,8.8 0a4.4,4.4 0,1 1,-8.8 0"
|
||||||
|
android:fillColor="#FF5C49"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M26.176,6.653H27.723V12.84H30.94V14.119H26.176V6.653ZM33.487,14.119H31.941V6.653H33.487V14.119ZM37.87,12.345H37.943L39.768,6.653H41.48L38.902,14.119H36.911L34.323,6.653H36.055L37.87,12.345ZM42.325,6.653H47.337V7.932H43.872V9.747H47.079V11.025H43.872V12.84H47.347V14.119H42.325V6.653Z"
|
||||||
|
android:fillColor="#ffffff"/>
|
||||||
|
</vector>
|
||||||
@@ -102,6 +102,39 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="48dp" />
|
android:layout_marginBottom="48dp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="24dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/pretendard_bold"
|
||||||
|
android:text="최근 "
|
||||||
|
android:textColor="@color/color_3bb9f1"
|
||||||
|
android:textSize="26sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/pretendard_bold"
|
||||||
|
android:text="종료한 라이브"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="26sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rv_latest_finished_live_channel"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginBottom="48dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingHorizontal="24dp" />
|
||||||
|
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/layout_recommend_channel"
|
android:id="@+id/layout_recommend_channel"
|
||||||
layout="@layout/layout_live_recommend_channel"
|
layout="@layout/layout_live_recommend_channel"
|
||||||
|
|||||||
@@ -11,25 +11,24 @@
|
|||||||
|
|
||||||
<!-- 프로필 이미지 컨테이너 -->
|
<!-- 프로필 이미지 컨테이너 -->
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:layout_width="72dp"
|
android:layout_width="76dp"
|
||||||
android:layout_height="72dp"
|
android:layout_height="76dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:background="@drawable/circle_background">
|
android:background="@drawable/circle_background">
|
||||||
|
|
||||||
<!-- 프로필 이미지 -->
|
<!-- 프로필 이미지 -->
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/iv_profile"
|
android:id="@+id/iv_profile"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="62dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="62dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:background="@drawable/circle_background"
|
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
android:scaleType="centerCrop" />
|
android:scaleType="centerCrop" />
|
||||||
|
|
||||||
<!-- LIVE 배지 -->
|
<!-- LIVE 배지 -->
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="50dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="18dp"
|
||||||
android:layout_gravity="bottom|center_horizontal"
|
android:layout_gravity="bottom|center_horizontal"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
android:src="@drawable/img_live" />
|
android:src="@drawable/img_live" />
|
||||||
|
|||||||
84
app/src/main/res/layout/item_latest_finished_live.xml
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<?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="168dp"
|
||||||
|
android:layout_height="238dp"
|
||||||
|
android:background="@drawable/bg_home_creator"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<!-- 프로필 이미지 컨테이너 -->
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/fl_profile"
|
||||||
|
android:layout_width="76dp"
|
||||||
|
android:layout_height="76dp"
|
||||||
|
android:background="@drawable/circle_background"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<!-- 프로필 이미지 -->
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_profile"
|
||||||
|
android:layout_width="62dp"
|
||||||
|
android:layout_height="62dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:scaleType="centerCrop" />
|
||||||
|
|
||||||
|
<!-- LIVE 배지 -->
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="18dp"
|
||||||
|
android:layout_gravity="bottom|center_horizontal"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:src="@drawable/img_live" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_nickname"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:fontFamily="@font/pretendard_regular"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="18sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/fl_profile"
|
||||||
|
tools:text="도화" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:fontFamily="@font/pretendard_regular"
|
||||||
|
android:gravity="center"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:textColor="#B0BEC5"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/tv_time_ago"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/tv_nickname"
|
||||||
|
tools:text="제목제목제목제목제목제목" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_time_ago"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:fontFamily="@font/pretendard_regular"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="#78909C"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
tools:text="111" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||