@@ -6,6 +6,8 @@ import android.view.LayoutInflater
66import android.view.View
77import android.view.ViewGroup
88import android.widget.LinearLayout
9+ import androidx.core.view.OneShotPreDrawListener
10+ import androidx.core.view.doOnPreDraw
911import androidx.core.view.isVisible
1012import androidx.databinding.DataBindingUtil
1113import androidx.fragment.app.Fragment
@@ -19,8 +21,12 @@ import ceui.lisa.utils.PixivOperate
1921import ceui.lisa.viewmodel.UserViewModel
2022import ceui.loxia.Event
2123import ceui.loxia.WebUserDetail
24+ import ceui.pixiv.ui.comments.translateComment
2225import ceui.pixiv.session.SessionManager
2326
27+ /* * 作者简介折叠阈值,与 V3 详情页简介一致。 */
28+ private const val BIO_COLLAPSED_LINES = 5
29+
2430/* *
2531 * V3 用户主页右侧 Tab —— 资料 / 工作环境 / 社交链接 / 简介 / 屏蔽。
2632 *
@@ -32,6 +38,10 @@ class UserV3InfoFragment : Fragment() {
3238 private val binding get() = _binding !!
3339 private val userViewModel: UserViewModel by activityViewModels()
3440
41+ /* * 作者简介展开态(对齐 V3 详情页简介折叠)。 */
42+ private var bioExpanded = false
43+ private var bioFullText: CharSequence? = null
44+
3545 override fun onCreateView (
3646 inflater : LayoutInflater ,
3747 container : ViewGroup ? ,
@@ -73,25 +83,85 @@ class UserV3InfoFragment : Fragment() {
7383 binding.muteSwitch.setOnCheckedChangeListener(muteSwitchListener)
7484 }
7585 }
86+ binding.bioTranslate.setOnClickListener { translateBio() }
87+ binding.bioToggle.setOnClickListener {
88+ bioExpanded = ! bioExpanded
89+ applyBioCollapseState()
90+ }
7691 }
7792
7893 override fun onDestroyView () {
94+ clearPendingBioPreDraw()
95+ bioFullText = null
7996 super .onDestroyView()
8097 _binding = null
8198 }
8299
100+ private fun bindBio (full : CharSequence ) {
101+ bioFullText = full
102+ binding.bioSection.isVisible = true
103+ binding.bio.text = full
104+ binding.bio.movementMethod = android.text.method.LinkMovementMethod .getInstance()
105+ applyBioCollapseState()
106+ }
107+
108+ private fun translateBio () {
109+ val plain = (bioFullText ? : binding.bio.text).toString().trim()
110+ translateComment(plain)
111+ }
112+
113+ /* *
114+ * 长简介折叠,对齐 V3 详情页简介区:#965/#1005 同款实现口径。
115+ * 折叠态在文本层面截到第 [BIO_COLLAPSED_LINES] 行止,避免 textIsSelectable /
116+ * LinkMovementMethod 把隐藏行滚出来。
117+ */
118+ private fun applyBioCollapseState () {
119+ val full = bioFullText ? : return
120+ binding.bio.maxLines = if (bioExpanded) Int .MAX_VALUE else BIO_COLLAPSED_LINES
121+ binding.bio.text = full
122+ binding.bio.scrollTo(0 , 0 )
123+ binding.bioToggle.setText(
124+ if (bioExpanded) R .string.v3_desc_collapse else R .string.v3_desc_expand
125+ )
126+ clearPendingBioPreDraw()
127+ lateinit var request: OneShotPreDrawListener
128+ request = binding.bio.doOnPreDraw {
129+ if (binding.bio.getTag(R .id.v3_desc_predraw_listener) == = request &&
130+ bioFullText == = full
131+ ) {
132+ binding.bio.setTag(R .id.v3_desc_predraw_listener, null )
133+ val layout = binding.bio.layout
134+ if (layout != null ) {
135+ val overflow = layout.lineCount > BIO_COLLAPSED_LINES
136+ binding.bioToggle.isVisible = overflow
137+ if (! bioExpanded && overflow) {
138+ val end = layout.getLineEnd(BIO_COLLAPSED_LINES - 1 ).coerceIn(0 , full.length)
139+ binding.bio.text = full.subSequence(0 , end).trimEnd()
140+ }
141+ }
142+ }
143+ }
144+ binding.bio.setTag(R .id.v3_desc_predraw_listener, request)
145+ }
146+
147+ private fun clearPendingBioPreDraw () {
148+ (binding.bio.getTag(R .id.v3_desc_predraw_listener) as ? OneShotPreDrawListener )
149+ ?.removeListener()
150+ binding.bio.setTag(R .id.v3_desc_predraw_listener, null )
151+ }
152+
83153 private fun bindUserDetail (data : UserDetailResponse ) {
84154 val user = data.user
85155 val profile = data.profile
86156 val isSelf = user.id == SessionManager .loggedInUid
87157
88158 // Bio
89159 if (! TextUtils .isEmpty(user.comment)) {
90- binding.bio.visibility = View .VISIBLE
91- binding.bio.text = androidx.core.text.HtmlCompat .fromHtml(
92- user.comment.orEmpty(), androidx.core.text.HtmlCompat .FROM_HTML_MODE_COMPACT
160+ bindBio(
161+ androidx.core.text.HtmlCompat .fromHtml(
162+ user.comment.orEmpty(), androidx.core.text.HtmlCompat .FROM_HTML_MODE_COMPACT
163+ )
93164 )
94- binding.bio.movementMethod = android.text.method.LinkMovementMethod .getInstance()
95165 }
96166
97167 // Social chips from app API (web API may add more later)
@@ -113,11 +183,11 @@ class UserV3InfoFragment : Fragment() {
113183 private fun bindWebUserDetail (detail : WebUserDetail ) {
114184 // Web 端的 commentHtml 比 app 端的 user.comment 排版更全(有 <a> 等标签),有就覆盖。
115185 if (! detail.commentHtml.isNullOrEmpty()) {
116- binding.bio.isVisible = true
117- binding.bio.text = androidx.core.text.HtmlCompat .fromHtml(
118- detail.commentHtml, androidx.core.text.HtmlCompat .FROM_HTML_MODE_COMPACT
186+ bindBio(
187+ androidx.core.text.HtmlCompat .fromHtml(
188+ detail.commentHtml, androidx.core.text.HtmlCompat .FROM_HTML_MODE_COMPACT
189+ )
119190 )
120- binding.bio.movementMethod = android.text.method.LinkMovementMethod .getInstance()
121191 }
122192
123193 // Supplement social links from Web API
0 commit comments