feat(home): 사업자 정보 inline 더보기를 추가한다
This commit is contained in:
@@ -30,6 +30,7 @@ import kr.co.vividnext.sodalive.v2.main.home.model.RecommendedActivityType
|
||||
import kr.co.vividnext.sodalive.v2.main.home.model.visibleHomeGenreCreatorGroups
|
||||
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeAiCharacterAdapter
|
||||
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeBannerBinder
|
||||
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeBusinessInfoBinder
|
||||
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeCheerCreatorAdapter
|
||||
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeFirstAudioAdapter
|
||||
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeGenreCreatorAdapter
|
||||
@@ -69,9 +70,29 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
|
||||
binding.textTabBarHome.root.setOnTabSelectedListener { }
|
||||
setUpSectionTitles()
|
||||
setUpRecommendationAdapters()
|
||||
setUpBusinessInfo()
|
||||
bindHomeRecommendationContent(phase6SampleContent())
|
||||
}
|
||||
|
||||
private fun setUpBusinessInfo() {
|
||||
val businessInfoText = binding.tvHomeBusinessInfo.text
|
||||
HomeBusinessInfoBinder.bind(binding.tvHomeBusinessInfo)
|
||||
binding.tvHomeBusinessInfo.post {
|
||||
binding.tvHomeBusinessInfo.maxLines = Int.MAX_VALUE
|
||||
binding.tvHomeBusinessInfo.ellipsize = null
|
||||
binding.tvHomeBusinessInfo.text = businessInfoText
|
||||
binding.tvHomeBusinessInfo.post {
|
||||
val totalLines = binding.tvHomeBusinessInfo.layout?.lineCount
|
||||
?: binding.tvHomeBusinessInfo.lineCount
|
||||
HomeBusinessInfoBinder.updateToggleVisibility(
|
||||
textView = binding.tvHomeBusinessInfo,
|
||||
originalText = businessInfoText,
|
||||
totalLineCount = totalLines
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRecommendationAdapters() {
|
||||
bannerBinder = HomeBannerBinder(binding.rvHomeBanners)
|
||||
binding.rvHomeLives.adapter = liveAdapter
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
package kr.co.vividnext.sodalive.v2.main.home.ui
|
||||
|
||||
import android.graphics.Color
|
||||
import android.text.SpannableString
|
||||
import android.text.Spanned
|
||||
import android.text.StaticLayout
|
||||
import android.text.TextPaint
|
||||
import android.text.TextUtils
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.text.style.ClickableSpan
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import kr.co.vividnext.sodalive.R
|
||||
|
||||
object HomeBusinessInfoBinder {
|
||||
private const val COLLAPSED_MAX_LINES = 3
|
||||
private const val ELLIPSIS = "… "
|
||||
private const val ACTION_SPACING = " "
|
||||
|
||||
fun bind(textView: TextView) {
|
||||
textView.movementMethod = LinkMovementMethod.getInstance()
|
||||
textView.highlightColor = Color.TRANSPARENT
|
||||
}
|
||||
|
||||
fun updateToggleVisibility(
|
||||
textView: TextView,
|
||||
originalText: CharSequence,
|
||||
totalLineCount: Int
|
||||
) {
|
||||
if (totalLineCount > COLLAPSED_MAX_LINES) {
|
||||
applyCollapsed(textView, originalText)
|
||||
} else {
|
||||
textView.maxLines = COLLAPSED_MAX_LINES
|
||||
textView.ellipsize = TextUtils.TruncateAt.END
|
||||
textView.text = originalText
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyExpanded(
|
||||
textView: TextView,
|
||||
originalText: CharSequence
|
||||
) {
|
||||
textView.maxLines = Int.MAX_VALUE
|
||||
textView.ellipsize = null
|
||||
textView.text = originalText.withAction(
|
||||
actionText = textView.context.getString(R.string.home_recommendation_collapse),
|
||||
actionSpacing = ACTION_SPACING,
|
||||
onClick = { applyCollapsed(textView, originalText) }
|
||||
)
|
||||
}
|
||||
|
||||
private fun applyCollapsed(
|
||||
textView: TextView,
|
||||
originalText: CharSequence
|
||||
) {
|
||||
textView.maxLines = COLLAPSED_MAX_LINES
|
||||
textView.ellipsize = null
|
||||
val actionText = textView.context.getString(R.string.home_recommendation_more)
|
||||
val collapsedText = originalText.truncateForInlineAction(textView, actionText)
|
||||
textView.text = collapsedText.withAction(
|
||||
actionText = actionText,
|
||||
actionSpacing = "",
|
||||
onClick = { applyExpanded(textView, originalText) }
|
||||
)
|
||||
}
|
||||
|
||||
private fun CharSequence.truncateForInlineAction(
|
||||
textView: TextView,
|
||||
actionText: String
|
||||
): CharSequence {
|
||||
val suffix = ELLIPSIS + actionText
|
||||
val availableWidth = textView.width - textView.paddingLeft - textView.paddingRight
|
||||
if (availableWidth <= 0) return this
|
||||
|
||||
var endIndex = length
|
||||
while (endIndex > 0) {
|
||||
val candidate = take(endIndex).trimEnd().toString() + suffix
|
||||
if (candidate.lineCount(textView, availableWidth) <= COLLAPSED_MAX_LINES) {
|
||||
return take(endIndex).trimEnd().toString() + ELLIPSIS
|
||||
}
|
||||
endIndex -= 1
|
||||
}
|
||||
return ELLIPSIS
|
||||
}
|
||||
|
||||
private fun CharSequence.withAction(
|
||||
actionText: String,
|
||||
actionSpacing: String,
|
||||
onClick: () -> Unit
|
||||
): SpannableString {
|
||||
val textWithAction = "$this$actionSpacing$actionText"
|
||||
return SpannableString(textWithAction).apply {
|
||||
setSpan(
|
||||
object : ClickableSpan() {
|
||||
override fun onClick(widget: View) = onClick()
|
||||
|
||||
override fun updateDrawState(ds: TextPaint) {
|
||||
super.updateDrawState(ds)
|
||||
ds.isUnderlineText = false
|
||||
}
|
||||
},
|
||||
textWithAction.length - actionText.length,
|
||||
textWithAction.length,
|
||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun CharSequence.lineCount(
|
||||
textView: TextView,
|
||||
availableWidth: Int
|
||||
): Int {
|
||||
return StaticLayout.Builder
|
||||
.obtain(this, 0, length, textView.paint, availableWidth)
|
||||
.setLineSpacing(textView.lineSpacingExtra, textView.lineSpacingMultiplier)
|
||||
.setIncludePad(textView.includeFontPadding)
|
||||
.build()
|
||||
.lineCount
|
||||
}
|
||||
}
|
||||
@@ -228,10 +228,12 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_home_business_info"
|
||||
style="@style/Typography.Body2"
|
||||
style="@style/Typography.Body6"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/home_recommendation_business_info"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="3"
|
||||
android:text="@string/company_info"
|
||||
android:textColor="@color/gray_500" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
Reference in New Issue
Block a user