This commit is contained in:
pengxiaolong
2026-01-23 16:52:51 +08:00
parent affe08c8b4
commit 63415e1fde
13 changed files with 266 additions and 326 deletions

View File

@@ -209,7 +209,7 @@ class GuideActivity : AppCompatActivity() {
}, 1500) }, 1500)
scrollView.postDelayed({ scrollView.postDelayed({
titleTextView.text = "The other party is typing..." titleTextView.text = getString(R.string.currently_inputting)
}, 500) }, 500)
inputMessage.isFocusable = true inputMessage.isFocusable = true
inputMessage.isFocusableInTouchMode = true inputMessage.isFocusableInTouchMode = true

View File

@@ -69,6 +69,10 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment {
private val wordDictionary = WordDictionary(this) // 词库 private val wordDictionary = WordDictionary(this) // 词库
private var currentInput = StringBuilder() // 当前输入前缀 private var currentInput = StringBuilder() // 当前输入前缀
private var completionSuggestions = emptyList<String>() // 自动完成建议 private var completionSuggestions = emptyList<String>() // 自动完成建议
private val suggestionViews = mutableListOf<TextView>() // 缓存动态创建的候选视图
private var suggestionSlotCount: Int = 21 // 包含前缀位,调这里可修改渲染数量
private val completionCapacity: Int
get() = (suggestionSlotCount - 1).coerceAtLeast(0)
@Volatile private var isSpecialToken: BooleanArray = BooleanArray(0) @Volatile private var isSpecialToken: BooleanArray = BooleanArray(0)
@@ -866,76 +870,116 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment {
// 统一处理补全/联想 // 统一处理补全/联想
override fun updateCompletionsAndRender(prefix: String) { override fun updateCompletionsAndRender(prefix: String) {
val ic = currentInputConnection val ic = currentInputConnection
// 先判断整个编辑框是不是“真的空”
val beforeAll = ic?.getTextBeforeCursor(256, 0)?.toString().orEmpty() val beforeAll = ic?.getTextBeforeCursor(256, 0)?.toString().orEmpty()
val afterAll = ic?.getTextAfterCursor(256, 0)?.toString().orEmpty() val afterAll = ic?.getTextAfterCursor(256, 0)?.toString().orEmpty()
val editorReallyEmpty = beforeAll.isEmpty() && afterAll.isEmpty() val editorReallyEmpty = beforeAll.isEmpty() && afterAll.isEmpty()
// 当前输入前缀
currentInput.clear() currentInput.clear()
currentInput.append(prefix) currentInput.append(prefix)
// 如果整个编辑框都是空的:直接清空联想 & 刷新 UI什么都不算
if (editorReallyEmpty) { if (editorReallyEmpty) {
clearEditorState() clearEditorState()
return return
} }
// 否则再去算 lastWord
val lastWord = getPrevWordBeforeCursor() val lastWord = getPrevWordBeforeCursor()
val maxCompletions = completionCapacity
Thread { Thread {
val list = try { val list =
if (prefix.isEmpty()) { if (maxCompletions <= 0) {
if (lastWord == null) {
// 这里也保持 emptyList防止空前缀 + 无上文时走全局高频随机词
emptyList()
} else {
suggestWithBigram("", lastWord, topK = 20)
}
} else {
val fromBi = suggestWithBigram(prefix, lastWord, topK = 20)
if (fromBi.isNotEmpty()) {
fromBi.filter { it != prefix }
} else {
wordDictionary.wordTrie.startsWith(prefix, 20)
.filter { it != prefix }
}
}
} catch (_: Throwable) {
if (prefix.isNotEmpty()) {
wordDictionary.wordTrie.startsWith(prefix, 20)
.filterNot { it == prefix }
} else {
emptyList() emptyList()
} else {
try {
if (prefix.isEmpty()) {
if (lastWord == null) {
emptyList()
} else {
suggestWithBigram("", lastWord, topK = maxCompletions)
}
} else {
val fromBi = suggestWithBigram(prefix, lastWord, topK = maxCompletions)
if (fromBi.isNotEmpty()) {
fromBi.filter { it != prefix }
} else {
wordDictionary.wordTrie.startsWith(prefix, maxCompletions)
.filter { it != prefix }
}
}
} catch (_: Throwable) {
if (prefix.isNotEmpty()) {
wordDictionary.wordTrie.startsWith(prefix, maxCompletions)
.filterNot { it == prefix }
} else {
emptyList()
}
}
} }
}
mainHandler.post { mainHandler.post {
completionSuggestions = suggestionStats.sortByCount(list.distinct().take(20)) val limited = if (maxCompletions > 0) list.distinct().take(maxCompletions) else emptyList()
completionSuggestions = suggestionStats.sortByCount(limited)
showCompletionSuggestions() showCompletionSuggestions()
} }
}.start() }.start()
} }
private fun ensureSuggestionViews(): List<TextView> {
val container = mainKeyboardView?.findViewById<LinearLayout>(R.id.completion_suggestions)
?: return emptyList()
val targetCount = maxOf(suggestionSlotCount, 1)
if (suggestionViews.size < targetCount) {
repeat(targetCount - suggestionViews.size) {
val view = buildSuggestionView(container)
suggestionViews.add(view)
container.addView(view)
}
} else if (suggestionViews.size > targetCount) {
val removeCount = suggestionViews.size - targetCount
repeat(removeCount) {
val view = suggestionViews.removeLast()
container.removeView(view)
}
}
suggestionViews.forEach { view ->
if (view.parent == null) container.addView(view)
}
return suggestionViews.take(targetCount)
}
private fun buildSuggestionView(parent: LinearLayout): TextView {
val dp = resources.displayMetrics.density
return TextView(parent.context).apply {
layoutParams = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
textSize = 16f
setPadding((12 * dp).toInt(), 0, (12 * dp).toInt(), 0)
gravity = Gravity.CENTER
isClickable = true
setBackgroundResource(R.drawable.btn_keyboard)
setTextColor(Color.parseColor("#000000"))
}
}
// 显示自动完成建议(布局不变) // 显示自动完成建议(布局不变)
private fun showCompletionSuggestions() { private fun showCompletionSuggestions() {
mainHandler.post { mainHandler.post {
val suggestionsView =
mainKeyboardView?.findViewById<LinearLayout>(R.id.completion_suggestions)
// 新增:联想滚动条 & 控制面板
val completionScroll = val completionScroll =
mainKeyboardView?.findViewById<ConstraintLayout>(R.id.completion_scroll) mainKeyboardView?.findViewById<ConstraintLayout>(R.id.completion_scroll)
val controlLayout = val controlLayout =
mainKeyboardView?.findViewById<LinearLayout>(R.id.control_layout) mainKeyboardView?.findViewById<LinearLayout>(R.id.control_layout)
val suggestions = (0..20).map { i -> val suggestions = ensureSuggestionViews()
mainKeyboardView?.findViewById<TextView>( if (suggestions.isEmpty()) {
resources.getIdentifier("suggestion_$i", "id", packageName) completionScroll?.visibility = View.GONE
) controlLayout?.visibility = View.VISIBLE
return@post
} }
// 当前前缀 // 当前前缀
@@ -962,25 +1006,46 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment {
controlLayout?.visibility = View.GONE controlLayout?.visibility = View.GONE
} }
// suggestion_0 显示 prefix val prefixView = suggestions.first()
suggestions[0]?.text = prefix prefixView.text = prefix
suggestions[0]?.visibility = if (prefix.isEmpty()) View.GONE else View.VISIBLE prefixView.visibility = if (prefix.isEmpty()) View.GONE else View.VISIBLE
suggestions[0]?.setOnClickListener { if (prefix.isEmpty()) {
insertCompletion(prefix) prefixView.setOnClickListener(null)
} else {
prefixView.setOnClickListener { insertCompletion(prefix) }
} }
// suggestion_1.. 按 completionSuggestions 填充 // 按 completionSuggestions 填充
suggestions.drop(1).forEachIndexed { index, textView -> suggestions.drop(1).forEachIndexed { index, textView ->
textView?.text = completionSuggestions.getOrNull(index) ?: "" val word = completionSuggestions.getOrNull(index)
if (index < completionSuggestions.size) { if (word != null) {
textView?.visibility = View.VISIBLE textView.text = word
textView?.setOnClickListener { textView.visibility = View.VISIBLE
suggestionStats.incClick(completionSuggestions[index]) textView.setOnClickListener {
insertCompletion(completionSuggestions[index]) suggestionStats.incClick(word)
insertCompletion(word)
} }
} else { } else {
textView?.visibility = View.GONE textView.text = ""
textView?.setOnClickListener(null) textView.visibility = View.GONE
textView.setOnClickListener(null)
}
}
// 给最后一个可见候选留出右侧距离,避免被关闭按钮遮挡
val spacingEndPx = (44 * resources.displayMetrics.density).toInt()
suggestions.forEach { view ->
val lp = view.layoutParams
if (lp is LinearLayout.LayoutParams) {
lp.marginEnd = 0
view.layoutParams = lp
}
}
suggestions.lastOrNull { it.visibility == View.VISIBLE }?.let { lastView ->
val lp = lastView.layoutParams
if (lp is LinearLayout.LayoutParams) {
lp.marginEnd = spacingEndPx
lastView.layoutParams = lp
} }
} }
@@ -1251,6 +1316,8 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment {
// ================== bigram & 联想实现 ================== // ================== bigram & 联想实现 ==================
private fun suggestWithBigram(prefix: String, lastWord: String?, topK: Int = 20): List<String> { private fun suggestWithBigram(prefix: String, lastWord: String?, topK: Int = 20): List<String> {
if (topK <= 0) return emptyList()
val m = bigramModel val m = bigramModel
if (m == null || !bigramReady) { if (m == null || !bigramReady) {
return if (prefix.isNotEmpty()) { return if (prefix.isNotEmpty()) {
@@ -1308,6 +1375,7 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment {
} }
private fun unigramTopKFiltered(topK: Int): List<String> { private fun unigramTopKFiltered(topK: Int): List<String> {
if (topK <= 0) return emptyList()
val m = bigramModel ?: return emptyList() val m = bigramModel ?: return emptyList()
if (!bigramReady) return emptyList() if (!bigramReady) return emptyList()
@@ -1332,6 +1400,7 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment {
} }
private fun topKByScore(pairs: List<Pair<String, Float>>, k: Int): List<String> { private fun topKByScore(pairs: List<Pair<String, Float>>, k: Int): List<String> {
if (k <= 0) return emptyList()
val heap = java.util.PriorityQueue<Pair<String, Float>>(k.coerceAtLeast(1)) { a, b -> val heap = java.util.PriorityQueue<Pair<String, Float>>(k.coerceAtLeast(1)) { a, b ->
a.second.compareTo(b.second) a.second.compareTo(b.second)
} }
@@ -1399,15 +1468,11 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment {
controlLayout?.visibility = View.VISIBLE controlLayout?.visibility = View.VISIBLE
// 再让联想区域里的文本都清空一下 // 再让联想区域里的文本都清空一下
val suggestions = (0..20).map { i -> val suggestions = ensureSuggestionViews()
mainKeyboardView?.findViewById<TextView>(
resources.getIdentifier("suggestion_$i", "id", packageName)
)
}
suggestions.forEach { tv -> suggestions.forEach { tv ->
tv?.text = "" tv.text = ""
tv?.visibility = View.GONE tv.visibility = View.GONE
tv?.setOnClickListener(null) tv.setOnClickListener(null)
} }
} }
} }

View File

@@ -77,11 +77,23 @@ abstract class BaseKeyboard(
if (id != 0) add(id) if (id != 0) add(id)
} }
} }
val suggestionContainerId =
env.ctx.resources.getIdentifier("completion_suggestions", "id", env.ctx.packageName)
fun isInSuggestionContainer(view: View): Boolean {
if (suggestionContainerId == 0) return false
var parent = view.parent
while (parent is View) {
if (parent.id == suggestionContainerId) return true
parent = parent.parent
}
return false
}
fun dfs(v: View?) { fun dfs(v: View?) {
when (v) { when (v) {
is TextView -> { is TextView -> {
if (ignoredIds.contains(v.id)) return if (ignoredIds.contains(v.id) || isInSuggestionContainer(v)) return
val lp = v.layoutParams val lp = v.layoutParams
if (lp is LinearLayout.LayoutParams) { if (lp is LinearLayout.LayoutParams) {

View File

@@ -9,6 +9,7 @@ import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody import okhttp3.ResponseBody.Companion.toResponseBody
import com.example.myapplication.utils.EncryptedSharedPreferencesUtil import com.example.myapplication.utils.EncryptedSharedPreferencesUtil
import android.content.Context import android.content.Context
import com.example.myapplication.AppContext
import com.example.myapplication.network.security.BodyParamsExtractor import com.example.myapplication.network.security.BodyParamsExtractor
import com.example.myapplication.network.security.NonceUtils import com.example.myapplication.network.security.NonceUtils
import com.example.myapplication.network.security.SignUtils import com.example.myapplication.network.security.SignUtils
@@ -28,6 +29,9 @@ private val NO_LOGIN_REQUIRED_PATHS = setOf(
"/themes/listByStyle", "/themes/listByStyle",
"/wallet/balance", "/wallet/balance",
"/character/listByUser", "/character/listByUser",
"/user/detail",
"/character/listByTag",
"/character/list",
) )
private val NO_SIGN_REQUIRED_PATHS = setOf( private val NO_SIGN_REQUIRED_PATHS = setOf(
@@ -294,7 +298,7 @@ val responseInterceptor = Interceptor { chain ->
if (errorResponse.code == 40102|| errorResponse.code == 40103) { if (errorResponse.code == 40102|| errorResponse.code == 40103) {
val isNoLoginApi = noLoginRequired(request.url) val isNoLoginApi = noLoginRequired(request.url)
EncryptedSharedPreferencesUtil.remove(AppContext.context, "user")
Log.w( Log.w(
"1314520-HTTP", "1314520-HTTP",
"40102 path=${request.url.encodedPath}, noLogin=$isNoLoginApi" "40102 path=${request.url.encodedPath}, noLogin=$isNoLoginApi"

View File

@@ -129,6 +129,12 @@ class HomeFragment : Fragment() {
} }
} }
is AuthEvent.TokenExpired,
is AuthEvent.Logout -> {
// token 被清理或主动退出后,刷新首页为未登录态数据
refreshHomeAfterNetwork()
}
is AuthEvent.CharacterAdded -> { is AuthEvent.CharacterAdded -> {
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
loadingOverlay.show() loadingOverlay.show()

View File

@@ -41,6 +41,7 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
private lateinit var tagContainer: LinearLayout private lateinit var tagContainer: LinearLayout
private lateinit var balance: TextView private lateinit var balance: TextView
private lateinit var swipeRefreshLayout: SwipeRefreshLayout private lateinit var swipeRefreshLayout: SwipeRefreshLayout
private lateinit var shopTitle: TextView
// ===== Data ===== // ===== Data =====
private var tabTitles: List<Theme> = emptyList() private var tabTitles: List<Theme> = emptyList()
@@ -335,19 +336,34 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
private fun setupSwipeRefreshConflictFix() { private fun setupSwipeRefreshConflictFix() {
val appBar = requireView().findViewById<AppBarLayout>(R.id.appBar) val appBar = requireView().findViewById<AppBarLayout>(R.id.appBar)
// 1) 监听 AppBar 是否完全展开 appBar.addOnOffsetChangedListener { appBarLayout, verticalOffset ->
appBar.addOnOffsetChangedListener { _, verticalOffset -> // 你原来的逻辑:是否完全展开
appBarFullyExpanded = (verticalOffset == 0) appBarFullyExpanded = (verticalOffset == 0)
// ===== 1) 快吸顶才展开:最后 20% 才开始从 0 -> 50dp =====
val ratio = kotlin.math.abs(verticalOffset).toFloat() / appBarLayout.totalScrollRange
val start = 0.8f // 80% 之后开始出现
val range = 0.2f // 用最后 20% 展开到满
val progress = ((ratio - start) / range).coerceIn(0f, 1f)
val maxHeightPx = (50 * resources.displayMetrics.density).toInt()
val newHeight = (progress * maxHeightPx).toInt()
// ===== 2) 同步文字渐显 =====
shopTitle.alpha = progress
// ===== 3) 防止抖动:高度没变就不 setLayoutParams =====
val lp = shopTitle.layoutParams
if (lp.height != newHeight) {
lp.height = newHeight
shopTitle.layoutParams = lp
}
} }
// 2) 核心:自定义"子 View 是否能向上滚"的判断
swipeRefreshLayout.setOnChildScrollUpCallback { _, _ -> swipeRefreshLayout.setOnChildScrollUpCallback { _, _ ->
// AppBar 没完全展开:不要让刷新抢手势(优先展开/折叠头部)
if (!appBarFullyExpanded) return@setOnChildScrollUpCallback true if (!appBarFullyExpanded) return@setOnChildScrollUpCallback true
// 找到 ViewPager2 当前页的 RecyclerView
val rv = findCurrentPageRecyclerView() val rv = findCurrentPageRecyclerView()
// rv 能向上滚:说明列表不在顶部 -> 禁止触发刷新
rv?.canScrollVertically(-1) ?: false rv?.canScrollVertically(-1) ?: false
} }
} }
@@ -405,6 +421,7 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
runCatching { RetrofitClient.apiService.themeList() }.getOrNull() runCatching { RetrofitClient.apiService.themeList() }.getOrNull()
private fun bindViews(view: View) { private fun bindViews(view: View) {
shopTitle = view.findViewById(R.id.shopTitle)
viewPager = view.findViewById(R.id.viewPager) viewPager = view.findViewById(R.id.viewPager)
tagScroll = view.findViewById(R.id.tagScroll) tagScroll = view.findViewById(R.id.tagScroll)
tagContainer = view.findViewById(R.id.tagContainer) tagContainer = view.findViewById(R.id.tagContainer)
@@ -442,6 +459,17 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
"element_id" to "search_btn", "element_id" to "search_btn",
) )
} }
view.findViewById<View>(R.id.recordButton).setOnClickListener {
//消费记录
AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.consumptionRecordFragment))
BehaviorReporter.report(
isNewUser = false,
"page_id" to "my",
"element_id" to "menu_item",
"item_title" to "消费记录"
)
}
} }
} }

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="90"
android:startColor="#F6F7FB"
android:endColor="#E9FFF1"
android:centerColor="#F6F7FB"
android:centerY="0.05" />
</shape>

View File

@@ -0,0 +1,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#E8FFFD" /> <!-- 背景色 -->
<corners android:radius="8dp" /> <!-- 圆角半径,越大越圆 -->
</shape>

View File

@@ -9,12 +9,10 @@
tools:context=".ui.home.HomeFragment"> tools:context=".ui.home.HomeFragment">
<!-- 背景--> <!-- 背景-->
<ImageView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:src="@drawable/bg" android:background="#F6F7FB"/>
android:scaleType="fitXY"
android:adjustViewBounds="true" />
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@@ -12,19 +12,21 @@
android:layout_height="match_parent"> android:layout_height="match_parent">
<!-- 背景--> <!-- 背景-->
<ImageView <!-- <ImageView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:src="@drawable/bg" android:src="@drawable/bg"
android:scaleType="fitXY" android:scaleType="fitXY"
android:adjustViewBounds="true" /> android:adjustViewBounds="true" /> -->
<!-- 头部 + 标签行,放进 AppBarLayout 里 --> <!-- 头部 + 标签行,放进 AppBarLayout 里 -->
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBar" android:id="@+id/appBar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@android:color/transparent"> android:background="@drawable/bg_shop_gradient"
android:elevation="0dp"
android:stateListAnimator="@null">
<!-- 这一块会跟着滚动,滑出屏幕 --> <!-- 这一块会跟着滚动,滑出屏幕 -->
<LinearLayout <LinearLayout
@@ -35,14 +37,39 @@
android:orientation="vertical" android:orientation="vertical"
app:layout_scrollFlags="scroll|exitUntilCollapsed"> app:layout_scrollFlags="scroll|exitUntilCollapsed">
<!-- 搜索、皮肤栏 --> <!--消费记录,搜索、皮肤栏 -->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="40dp" android:layout_height="40dp"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:gravity="end|bottom"
android:orientation="horizontal"> android:orientation="horizontal">
<LinearLayout
android:id="@+id/recordButton"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:gravity="center"
android:paddingStart="7dp"
android:paddingEnd="7dp"
android:background="@drawable/shop_record_bg"
android:orientation="horizontal">
<ImageView
android:layout_width="15dp"
android:layout_height="16dp"
android:layout_marginEnd="4dp"
android:src="@drawable/record" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/mine_consumption_record"
android:textColor="#02BEAC"/>
</LinearLayout>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<ImageView <ImageView
android:id="@+id/searchButton" android:id="@+id/searchButton"
android:layout_width="24dp" android:layout_width="24dp"
@@ -198,21 +225,34 @@
<HorizontalScrollView <HorizontalScrollView
android:id="@+id/tagScroll" android:id="@+id/tagScroll"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="30dp" android:layout_height="wrap_content"
android:paddingStart="16dp" android:paddingStart="16dp"
android:paddingEnd="16dp" android:paddingEnd="16dp"
android:layout_marginTop="18dp"
android:layout_marginBottom="18dp" android:layout_marginBottom="18dp"
android:fillViewport="true" android:fillViewport="true"
android:scrollbars="none" android:scrollbars="none"
android:overScrollMode="never"> android:overScrollMode="never">
<LinearLayout <LinearLayout
android:id="@+id/tagContainer"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="vertical"
android:gravity="center_vertical" /> android:gravity="center_vertical">
<TextView
android:id="@+id/shopTitle"
android:layout_width="match_parent"
android:layout_height="0dp"
android:gravity="center"
android:text="@string/shop_title"
android:textColor="#1B1F1A"
android:textSize="20sp" />
<LinearLayout
android:id="@+id/tagContainer"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:orientation="horizontal"
android:gravity="center_vertical" />
</LinearLayout>
</HorizontalScrollView> </HorizontalScrollView>
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>

View File

@@ -68,8 +68,9 @@ xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_marginTop="3dp" android:layout_marginTop="3dp"
android:background="@drawable/complete_bg"> android:background="@drawable/complete_bg">
<HorizontalScrollView <HorizontalScrollView
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="50dp" android:layout_height="50dp"
android:layout_weight="1"
android:scrollbars="none" android:scrollbars="none"
android:overScrollMode="never" android:overScrollMode="never"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -84,239 +85,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingStart="4dp" android:paddingStart="4dp"
android:paddingEnd="4dp"> android:paddingEnd="4dp" />
<TextView
android:id="@+id/suggestion_0"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_2"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_3"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_4"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_5"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_6"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_7"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_8"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_9"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_10"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_11"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_12"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_13"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_14"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_15"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_16"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_17"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_18"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_19"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
<TextView
android:id="@+id/suggestion_20"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="16sp"
android:paddingHorizontal="12dp"
android:gravity="center"
android:clickable="true"
android:background="@drawable/btn_keyboard"
android:textColor="#FFFFFF"/>
</LinearLayout>
</HorizontalScrollView> </HorizontalScrollView>
<LinearLayout <LinearLayout

View File

@@ -99,6 +99,7 @@
<string name="add">添加</string> <string name="add">添加</string>
<!-- 商城 --> <!-- 商城 -->
<string name="shop_title">商城</string>
<string name="shop_mall">积分商城</string> <string name="shop_mall">积分商城</string>
<string name="shop_points">我的积分</string> <string name="shop_points">我的积分</string>
<string name="shop_recharge">充值</string> <string name="shop_recharge">充值</string>
@@ -140,7 +141,7 @@
<string name="imguide_btn_2">去切换</string> <string name="imguide_btn_2">去切换</string>
<!-- ai键盘 --> <!-- ai键盘 -->
<string name="ai_keyboard_input_hint">点击粘贴您的内容</string> <string name="ai_keyboard_input_hint">粘贴TA的话</string>
<string name="ai_keyboard_paste_btn">粘贴</string> <string name="ai_keyboard_paste_btn">粘贴</string>
<string name="ai_keyboard_clear_btn">清空</string> <string name="ai_keyboard_clear_btn">清空</string>
<string name="ai_keyboard_send_btn">发送</string> <string name="ai_keyboard_send_btn">发送</string>
@@ -156,6 +157,7 @@
<string name="skip">跳过</string> <string name="skip">跳过</string>
<string name="delete">删除</string> <string name="delete">删除</string>
<string name="next">下一步</string> <string name="next">下一步</string>
<string name="currently_inputting">对方正在输入...</string>
<!-- 服务条款与隐私政策(小字提醒区) --> <!-- 服务条款与隐私政策(小字提醒区) -->
<string name="terms_and_privacy_1">继续操作即表示您已经阅读并同意我们的</string> <string name="terms_and_privacy_1">继续操作即表示您已经阅读并同意我们的</string>

View File

@@ -103,6 +103,7 @@
<!-- 商城 --> <!-- 商城 -->
<string name="shop_title">Shop</string>
<string name="shop_mall">Points Mall</string> <string name="shop_mall">Points Mall</string>
<string name="shop_points">My points</string> <string name="shop_points">My points</string>
<string name="shop_recharge">Recharge</string> <string name="shop_recharge">Recharge</string>
@@ -162,6 +163,7 @@
<string name="skip">Skip</string> <string name="skip">Skip</string>
<string name="delete">Delete</string> <string name="delete">Delete</string>
<string name="next">Next step</string> <string name="next">Next step</string>
<string name="currently_inputting">The other party is currently inputting...</string>
<!-- 服务条款与隐私政策(小字提醒区) --> <!-- 服务条款与隐私政策(小字提醒区) -->
<string name="terms_and_privacy_1">By Continuing, You Agree To Our </string> <string name="terms_and_privacy_1">By Continuing, You Agree To Our </string>