Skip to content

Commit 27162c6

Browse files
committed
feat(user-v3): 作者自我介绍支持翻译与长简介折叠 (#1079)
1 parent 69501b9 commit 27162c6

2 files changed

Lines changed: 140 additions & 18 deletions

File tree

app/src/main/java/ceui/lisa/activities/UserV3InfoFragment.kt

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import android.view.LayoutInflater
66
import android.view.View
77
import android.view.ViewGroup
88
import android.widget.LinearLayout
9+
import androidx.core.view.OneShotPreDrawListener
10+
import androidx.core.view.doOnPreDraw
911
import androidx.core.view.isVisible
1012
import androidx.databinding.DataBindingUtil
1113
import androidx.fragment.app.Fragment
@@ -19,8 +21,12 @@ import ceui.lisa.utils.PixivOperate
1921
import ceui.lisa.viewmodel.UserViewModel
2022
import ceui.loxia.Event
2123
import ceui.loxia.WebUserDetail
24+
import ceui.pixiv.ui.comments.translateComment
2225
import 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

app/src/main/res/layout/fragment_user_v3_info.xml

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,19 +80,71 @@
8080
</LinearLayout>
8181

8282
<!-- Bio (between profile and workspace) -->
83-
<TextView
84-
android:id="@+id/bio"
83+
<LinearLayout
84+
android:id="@+id/bio_section"
8585
android:layout_width="match_parent"
8686
android:layout_height="wrap_content"
8787
android:layout_marginTop="16dp"
88-
android:alpha="0.78"
89-
android:autoLink="all"
90-
android:lineSpacingMultiplier="1.6"
91-
android:textColor="@color/v3_text_1"
92-
android:textColorLink="#3D8BFD"
93-
android:textIsSelectable="true"
94-
android:textSize="14sp"
95-
android:visibility="gone" />
88+
android:orientation="vertical"
89+
android:visibility="gone">
90+
91+
<LinearLayout
92+
android:layout_width="match_parent"
93+
android:layout_height="wrap_content"
94+
android:gravity="center_vertical"
95+
android:orientation="horizontal">
96+
97+
<TextView
98+
android:layout_width="wrap_content"
99+
android:layout_height="wrap_content"
100+
android:letterSpacing="0.12"
101+
android:text="@string/label_personal_intro"
102+
android:textAllCaps="true"
103+
android:textColor="@color/v3_text_3"
104+
android:textSize="12sp"
105+
android:textStyle="bold" />
106+
107+
<View
108+
android:layout_width="0dp"
109+
android:layout_height="0dp"
110+
android:layout_weight="1" />
111+
112+
<ImageView
113+
android:id="@+id/bio_translate"
114+
android:layout_width="48dp"
115+
android:layout_height="48dp"
116+
android:background="?attr/selectableItemBackgroundBorderless"
117+
android:padding="12dp"
118+
android:contentDescription="@string/string_translate_caption"
119+
android:src="@drawable/ic_baseline_translate_24"
120+
app:tint="@color/v3_text_3" />
121+
</LinearLayout>
122+
123+
<TextView
124+
android:id="@+id/bio"
125+
android:layout_width="match_parent"
126+
android:layout_height="wrap_content"
127+
android:alpha="0.78"
128+
android:autoLink="all"
129+
android:lineSpacingMultiplier="1.6"
130+
android:textColor="@color/v3_text_1"
131+
android:textColorLink="#3D8BFD"
132+
android:textIsSelectable="true"
133+
android:textSize="14sp" />
134+
135+
<TextView
136+
android:id="@+id/bio_toggle"
137+
android:layout_width="match_parent"
138+
android:layout_height="wrap_content"
139+
android:background="?attr/selectableItemBackground"
140+
android:gravity="center_vertical"
141+
android:minHeight="48dp"
142+
android:text="@string/v3_desc_expand"
143+
android:textColor="@color/v3_blue"
144+
android:textSize="13sp"
145+
android:textStyle="bold"
146+
android:visibility="gone" />
147+
</LinearLayout>
96148

97149
<!-- Workspace Card -->
98150
<LinearLayout

0 commit comments

Comments
 (0)