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