国际化

This commit is contained in:
pengxiaolong
2026-01-21 21:53:34 +08:00
parent 066cea19df
commit bab447c23f
90 changed files with 1699 additions and 343 deletions

View File

@@ -4,10 +4,10 @@
<selectionStates> <selectionStates>
<SelectionState runConfigName="app"> <SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" /> <option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2026-01-12T07:53:30.395553200Z"> <DropdownSelection timestamp="2026-01-19T05:47:34.214081500Z">
<Target type="DEFAULT_BOOT"> <Target type="DEFAULT_BOOT">
<handle> <handle>
<DeviceId pluginId="PhysicalDevice" identifier="serial=7PRDU19930003674" /> <DeviceId pluginId="PhysicalDevice" identifier="serial=3B15A70100N00000" />
</handle> </handle>
</Target> </Target>
</DropdownSelection> </DropdownSelection>

View File

@@ -55,6 +55,7 @@ dependencies {
implementation("com.google.android.material:material:1.12.0") implementation("com.google.android.material:material:1.12.0")
implementation("de.hdodenhof:circleimageview:3.1.0") implementation("de.hdodenhof:circleimageview:3.1.0")
implementation("com.google.android.flexbox:flexbox:3.0.0") implementation("com.google.android.flexbox:flexbox:3.0.0")
implementation("com.github.Dimezis:BlurView:version-2.0.2")
// Jetpack Compose // Jetpack Compose
implementation("androidx.activity:activity-compose:1.8.0") implementation("androidx.activity:activity-compose:1.8.0")

View File

@@ -2,6 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA" />

View File

@@ -100,7 +100,7 @@ class GuideActivity : AppCompatActivity() {
val text = it as TextView val text = it as TextView
val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
clipboard.setPrimaryClip(ClipData.newPlainText("text", text.text)) clipboard.setPrimaryClip(ClipData.newPlainText("text", text.text))
Toast.makeText(this, "Copy successfully", Toast.LENGTH_SHORT).show() Toast.makeText(this, getString(R.string.personal_settings_copy), Toast.LENGTH_SHORT).show()
} }
findViewById<TextView>(R.id.love_words_2).setOnClickListener { findViewById<TextView>(R.id.love_words_2).setOnClickListener {
BehaviorReporter.report( BehaviorReporter.report(
@@ -111,7 +111,7 @@ class GuideActivity : AppCompatActivity() {
val text = it as TextView val text = it as TextView
val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
clipboard.setPrimaryClip(ClipData.newPlainText("text", text.text)) clipboard.setPrimaryClip(ClipData.newPlainText("text", text.text))
Toast.makeText(this, "Copy successfully", Toast.LENGTH_SHORT).show() Toast.makeText(this, getString(R.string.personal_settings_copy), Toast.LENGTH_SHORT).show()
} }
// 关闭按钮 // 关闭按钮
findViewById<FrameLayout>(R.id.iv_close).setOnClickListener { findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {

View File

@@ -145,7 +145,6 @@ class ImeGuideActivity : AppCompatActivity() {
enableText == null || selectText == null || enableText == null || selectText == null ||
enableImg == null || selectImg == null enableImg == null || selectImg == null
) { ) {
Log.e(TAG, "有 View 为 null检查 activity_ime_guide.xml 的 id 是否匹配")
return return
} }
@@ -178,22 +177,24 @@ class ImeGuideActivity : AppCompatActivity() {
if (!enabled && !selected) { if (!enabled && !selected) {
enableLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_unfinished) enableLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_unfinished)
selectLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_unfinished) selectLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_completed)
enableText.setTextColor(Color.parseColor("#FFFFFF")) enableText.setTextColor(Color.parseColor("#FFFFFF"))
selectText.setTextColor(Color.parseColor("#FFFFFF")) selectText.setTextColor(Color.parseColor("#A1A1A1"))
enableImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img) enableImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img)
selectImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img) selectImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img)
step1.text = "Step one" step1.text = getString(R.string.imguide_text1_step1)
step2.text = "Check to enable key of love" step2.text = getString(R.string.imguide_text2_step1)
selectLayout.setOnClickListener(null)
} else if (!enabled && selected) { } else if (!enabled && selected) {
enableLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_unfinished) enableLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_unfinished)
selectLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_unfinished) selectLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_completed)
enableImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img) enableImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img)
selectImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img) selectImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img)
enableText.setTextColor(Color.parseColor("#FFFFFF")) enableText.setTextColor(Color.parseColor("#FFFFFF"))
selectText.setTextColor(Color.parseColor("#FFFFFF")) selectText.setTextColor(Color.parseColor("#A1A1A1"))
step1.text = "Step one" step1.text = getString(R.string.imguide_text1_step1)
step2.text = "Check to enable key of love" step2.text = getString(R.string.imguide_text2_step1)
selectLayout.setOnClickListener(null)
} else if (enabled && !selected) { } else if (enabled && !selected) {
enableLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_completed) enableLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_completed)
selectLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_unfinished) selectLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_unfinished)
@@ -201,8 +202,8 @@ class ImeGuideActivity : AppCompatActivity() {
selectImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img) selectImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img)
enableText.setTextColor(Color.parseColor("#A1A1A1")) enableText.setTextColor(Color.parseColor("#A1A1A1"))
selectText.setTextColor(Color.parseColor("#FFFFFF")) selectText.setTextColor(Color.parseColor("#FFFFFF"))
step1.text = "Step two" step1.text =getString(R.string.imguide_text1_step2)
step2.text = "Select key of love as your default input method" step2.text = getString(R.string.imguide_text2_step2)
} else if (enabled && selected) { } else if (enabled && selected) {
enableLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_completed) enableLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_completed)
selectLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_completed) selectLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_completed)
@@ -210,14 +211,14 @@ class ImeGuideActivity : AppCompatActivity() {
selectImg.setImageResource(R.drawable.ime_guide_activity_btn_completed_img) selectImg.setImageResource(R.drawable.ime_guide_activity_btn_completed_img)
enableText.setTextColor(Color.parseColor("#A1A1A1")) enableText.setTextColor(Color.parseColor("#A1A1A1"))
selectText.setTextColor(Color.parseColor("#A1A1A1")) selectText.setTextColor(Color.parseColor("#A1A1A1"))
step1.text = "Completed" step1.text =getString(R.string.imguide_text1_step3)
step2.text = "You have completed the relevant Settings" step2.text = getString(R.string.imguide_text2_step3)
BehaviorReporter.report( BehaviorReporter.report(
isNewUser = false, isNewUser = false,
"page_id" to "keyboard_permission_guide", "page_id" to "keyboard_permission_guide",
"element_id" to "close_btn", "element_id" to "close_btn",
) )
Toast.makeText(this, "The input method is all set!", Toast.LENGTH_SHORT).show() Toast.makeText(this, getString(R.string.imguide_text2_step3_hint), Toast.LENGTH_SHORT).show()
try { try {
startActivity(Intent(this, GuideActivity::class.java)) startActivity(Intent(this, GuideActivity::class.java))
} catch (e: Exception) { } catch (e: Exception) {

View File

@@ -1,20 +1,37 @@
package com.example.myapplication package com.example.myapplication
import android.app.AlertDialog
import android.content.Context
import android.graphics.drawable.ColorDrawable
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import eightbitlab.com.blurview.BlurView
import eightbitlab.com.blurview.RenderEffectBlur
import eightbitlab.com.blurview.RenderScriptBlur
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.navOptions
import com.example.myapplication.network.AuthEvent import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus import com.example.myapplication.network.AuthEventBus
import com.example.myapplication.network.BehaviorReporter import com.example.myapplication.network.BehaviorReporter
import com.example.myapplication.network.NetworkEvent
import com.example.myapplication.network.NetworkEventBus
import com.example.myapplication.utils.EncryptedSharedPreferencesUtil import com.example.myapplication.utils.EncryptedSharedPreferencesUtil
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.button.MaterialButton
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -25,6 +42,7 @@ class MainActivity : AppCompatActivity() {
private val TAB_HOME = "tab_home" private val TAB_HOME = "tab_home"
private val TAB_SHOP = "tab_shop" private val TAB_SHOP = "tab_shop"
private val TAB_MINE = "tab_mine" private val TAB_MINE = "tab_mine"
private val TAB_CIRCLE = "tab_circle"
private val GLOBAL_HOST = "global_host" private val GLOBAL_HOST = "global_host"
private var currentTabTag = TAB_HOME private var currentTabTag = TAB_HOME
@@ -41,20 +59,29 @@ class MainActivity : AppCompatActivity() {
mapOf( mapOf(
R.id.home_graph to TAB_HOME, R.id.home_graph to TAB_HOME,
R.id.shop_graph to TAB_SHOP, R.id.shop_graph to TAB_SHOP,
R.id.mine_graph to TAB_MINE R.id.mine_graph to TAB_MINE,
R.id.circle_graph to TAB_CIRCLE
) )
} }
private lateinit var homeHost: NavHostFragment private lateinit var homeHost: NavHostFragment
private lateinit var shopHost: NavHostFragment private lateinit var shopHost: NavHostFragment
private lateinit var circleHost: NavHostFragment
private lateinit var mineHost: NavHostFragment private lateinit var mineHost: NavHostFragment
private lateinit var globalHost: NavHostFragment private lateinit var globalHost: NavHostFragment
private var lastGlobalDestId: Int = R.id.globalEmptyFragment private var lastGlobalDestId: Int = R.id.globalEmptyFragment
private lateinit var bottomNavBlur: BlurView
private var blurReady: Boolean = false
private var connectivityManager: ConnectivityManager? = null
private var networkCallback: ConnectivityManager.NetworkCallback? = null
private var hasNetworkConnection: Boolean = true
private var noNetworkDialog: AlertDialog? = null
private val currentTabHost: NavHostFragment private val currentTabHost: NavHostFragment
get() = when (currentTabTag) { get() = when (currentTabTag) {
TAB_SHOP -> shopHost TAB_SHOP -> shopHost
TAB_MINE -> mineHost TAB_MINE -> mineHost
TAB_CIRCLE -> circleHost
else -> homeHost else -> homeHost
} }
@@ -71,6 +98,7 @@ class MainActivity : AppCompatActivity() {
private var lastHomeDestIdForReport: Int? = null private var lastHomeDestIdForReport: Int? = null
private var lastShopDestIdForReport: Int? = null private var lastShopDestIdForReport: Int? = null
private var lastCircleDestIdForReport: Int? = null
private var lastMineDestIdForReport: Int? = null private var lastMineDestIdForReport: Int? = null
private var lastGlobalDestIdForReport: Int? = null private var lastGlobalDestIdForReport: Int? = null
@@ -89,6 +117,13 @@ class MainActivity : AppCompatActivity() {
reportPageView(source = "shop_tab", destId = dest.id) reportPageView(source = "shop_tab", destId = dest.id)
} }
private val circleRouteListener =
NavController.OnDestinationChangedListener { _, dest, _ ->
if (lastCircleDestIdForReport == dest.id) return@OnDestinationChangedListener
lastCircleDestIdForReport = dest.id
reportPageView(source = "circle_tab", destId = dest.id)
}
private val mineRouteListener = private val mineRouteListener =
NavController.OnDestinationChangedListener { _, dest, _ -> NavController.OnDestinationChangedListener { _, dest, _ ->
if (lastMineDestIdForReport == dest.id) return@OnDestinationChangedListener if (lastMineDestIdForReport == dest.id) return@OnDestinationChangedListener
@@ -108,8 +143,10 @@ class MainActivity : AppCompatActivity() {
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
bottomNav = findViewById(R.id.bottom_nav) bottomNav = findViewById(R.id.bottom_nav)
bottomNavBlur = findViewById(R.id.bottom_nav_blur)
bottomNav.itemIconTintList = null bottomNav.itemIconTintList = null
bottomNav.setOnItemReselectedListener { /* ignore */ } bottomNav.setOnItemReselectedListener { /* ignore */ }
setupBottomNavBlur()
// 1) 恢复当前tab // 1) 恢复当前tab
currentTabTag = savedInstanceState?.getString("current_tab_tag") ?: TAB_HOME currentTabTag = savedInstanceState?.getString("current_tab_tag") ?: TAB_HOME
@@ -127,6 +164,7 @@ class MainActivity : AppCompatActivity() {
bottomNav.selectedItemId = when (currentTabTag) { bottomNav.selectedItemId = when (currentTabTag) {
TAB_SHOP -> R.id.shop_graph TAB_SHOP -> R.id.shop_graph
TAB_MINE -> R.id.mine_graph TAB_MINE -> R.id.mine_graph
TAB_CIRCLE -> R.id.circle_graph
else -> R.id.home_graph else -> R.id.home_graph
} }
pendingTabAfterLogin = tabTag // 记录目标tab pendingTabAfterLogin = tabTag // 记录目标tab
@@ -164,6 +202,7 @@ class MainActivity : AppCompatActivity() {
switchTab(tag) switchTab(tag)
bottomNav.selectedItemId = when (tag) { bottomNav.selectedItemId = when (tag) {
TAB_SHOP -> R.id.shop_graph TAB_SHOP -> R.id.shop_graph
TAB_CIRCLE -> R.id.circle_graph
TAB_MINE -> R.id.mine_graph TAB_MINE -> R.id.mine_graph
else -> R.id.home_graph else -> R.id.home_graph
} }
@@ -195,7 +234,7 @@ class MainActivity : AppCompatActivity() {
// 打开全局页面事件处理 // 打开全局页面事件处理
is AuthEvent.OpenGlobalPage -> { is AuthEvent.OpenGlobalPage -> {
openGlobal(event.destinationId, event.bundle) openGlobal(event.destinationId, event.bundle, event.clearGlobalBackStack)
} }
is AuthEvent.UserUpdated -> { is AuthEvent.UserUpdated -> {
@@ -224,10 +263,13 @@ class MainActivity : AppCompatActivity() {
bottomNav.selectedItemId = when (currentTabTag) { bottomNav.selectedItemId = when (currentTabTag) {
TAB_SHOP -> R.id.shop_graph TAB_SHOP -> R.id.shop_graph
TAB_MINE -> R.id.mine_graph TAB_MINE -> R.id.mine_graph
TAB_CIRCLE -> R.id.circle_graph
else -> R.id.home_graph else -> R.id.home_graph
} }
updateBottomNavVisibility() updateBottomNavVisibility()
} }
setupNetworkMonitor()
} }
override fun onResume() { override fun onResume() {
@@ -241,9 +283,16 @@ class MainActivity : AppCompatActivity() {
runCatching { runCatching {
homeHost.navController.removeOnDestinationChangedListener(homeRouteListener) homeHost.navController.removeOnDestinationChangedListener(homeRouteListener)
shopHost.navController.removeOnDestinationChangedListener(shopRouteListener) shopHost.navController.removeOnDestinationChangedListener(shopRouteListener)
circleHost.navController.removeOnDestinationChangedListener(circleRouteListener)
mineHost.navController.removeOnDestinationChangedListener(mineRouteListener) mineHost.navController.removeOnDestinationChangedListener(mineRouteListener)
globalHost.navController.removeOnDestinationChangedListener(globalRouteListener) globalHost.navController.removeOnDestinationChangedListener(globalRouteListener)
} }
connectivityManager?.let { cm ->
networkCallback?.let { cm.unregisterNetworkCallback(it) }
}
networkCallback = null
noNetworkDialog?.dismiss()
noNetworkDialog = null
super.onDestroy() super.onDestroy()
} }
@@ -254,6 +303,8 @@ class MainActivity : AppCompatActivity() {
?: NavHostFragment.create(R.navigation.home_graph) ?: NavHostFragment.create(R.navigation.home_graph)
shopHost = fm.findFragmentByTag(TAB_SHOP) as? NavHostFragment shopHost = fm.findFragmentByTag(TAB_SHOP) as? NavHostFragment
?: NavHostFragment.create(R.navigation.shop_graph) ?: NavHostFragment.create(R.navigation.shop_graph)
circleHost = fm.findFragmentByTag(TAB_CIRCLE) as? NavHostFragment
?: NavHostFragment.create(R.navigation.circle_graph)
mineHost = fm.findFragmentByTag(TAB_MINE) as? NavHostFragment mineHost = fm.findFragmentByTag(TAB_MINE) as? NavHostFragment
?: NavHostFragment.create(R.navigation.mine_graph) ?: NavHostFragment.create(R.navigation.mine_graph)
@@ -266,6 +317,7 @@ class MainActivity : AppCompatActivity() {
.setReorderingAllowed(true) .setReorderingAllowed(true)
.add(R.id.tab_container, homeHost, TAB_HOME) .add(R.id.tab_container, homeHost, TAB_HOME)
.add(R.id.tab_container, shopHost, TAB_SHOP).hide(shopHost) .add(R.id.tab_container, shopHost, TAB_SHOP).hide(shopHost)
.add(R.id.tab_container, circleHost, TAB_CIRCLE).hide(circleHost)
.add(R.id.tab_container, mineHost, TAB_MINE).hide(mineHost) .add(R.id.tab_container, mineHost, TAB_MINE).hide(mineHost)
.commitNow() .commitNow()
} }
@@ -293,7 +345,7 @@ class MainActivity : AppCompatActivity() {
} }
/** /**
* 这些页面需要隐藏底部导航栏:你按需加/减 * 需要隐藏底部导航栏的页面
*/ */
private fun shouldHideBottomNav(destId: Int): Boolean { private fun shouldHideBottomNav(destId: Int): Boolean {
return destId in setOf( return destId in setOf(
@@ -301,6 +353,7 @@ class MainActivity : AppCompatActivity() {
R.id.searchResultFragment, R.id.searchResultFragment,
R.id.MySkin, R.id.MySkin,
R.id.notificationFragment, R.id.notificationFragment,
R.id.languageFragment,
R.id.feedbackFragment, R.id.feedbackFragment,
R.id.MyKeyboard, R.id.MyKeyboard,
R.id.PersonalSettings, R.id.PersonalSettings,
@@ -308,19 +361,19 @@ class MainActivity : AppCompatActivity() {
} }
/** /**
* 统一底栏显隐逻辑:任何地方状态变化都调用它 * 统一底栏显隐逻辑:任何地方状态变化都调用它
*/ */
private fun updateBottomNavVisibility() { private fun updateBottomNavVisibility() {
// ✅ 只要 global overlay 不在 empty底栏必须隐藏用 NavController 判断,别用 View.visibility
if (isGlobalVisible()) { if (isGlobalVisible()) {
bottomNav.visibility = View.GONE bottomNav.visibility = View.GONE
bottomNavBlur.visibility = View.GONE
return return
} }
// 否则按“当前可见 tab 的当前目的地”判断
val destId = currentTabNavController.currentDestination?.id val destId = currentTabNavController.currentDestination?.id
bottomNav.visibility = val shouldShow = destId == null || !shouldHideBottomNav(destId)
if (destId != null && shouldHideBottomNav(destId)) View.GONE else View.VISIBLE bottomNav.visibility = if (shouldShow) View.VISIBLE else View.GONE
bottomNavBlur.visibility = if (shouldShow && blurReady) View.VISIBLE else View.GONE
} }
private fun bindGlobalVisibility() { private fun bindGlobalVisibility() {
@@ -371,6 +424,7 @@ class MainActivity : AppCompatActivity() {
val targetHost = when (targetTag) { val targetHost = when (targetTag) {
TAB_SHOP -> shopHost TAB_SHOP -> shopHost
TAB_MINE -> mineHost TAB_MINE -> mineHost
TAB_CIRCLE -> circleHost
else -> homeHost else -> homeHost
} }
val currentHost = currentTabHost val currentHost = currentTabHost
@@ -386,6 +440,7 @@ class MainActivity : AppCompatActivity() {
.hide(homeHost) .hide(homeHost)
.hide(shopHost) .hide(shopHost)
.hide(mineHost) .hide(mineHost)
.hide(circleHost)
.show(targetHost) .show(targetHost)
} else if (currentHost != targetHost) { } else if (currentHost != targetHost) {
transaction transaction
@@ -397,9 +452,11 @@ class MainActivity : AppCompatActivity() {
.setMaxLifecycle(homeHost, if (targetHost == homeHost) Lifecycle.State.RESUMED else Lifecycle.State.STARTED) .setMaxLifecycle(homeHost, if (targetHost == homeHost) Lifecycle.State.RESUMED else Lifecycle.State.STARTED)
.setMaxLifecycle(shopHost, if (targetHost == shopHost) Lifecycle.State.RESUMED else Lifecycle.State.STARTED) .setMaxLifecycle(shopHost, if (targetHost == shopHost) Lifecycle.State.RESUMED else Lifecycle.State.STARTED)
.setMaxLifecycle(mineHost, if (targetHost == mineHost) Lifecycle.State.RESUMED else Lifecycle.State.STARTED) .setMaxLifecycle(mineHost, if (targetHost == mineHost) Lifecycle.State.RESUMED else Lifecycle.State.STARTED)
.setMaxLifecycle(circleHost, if (targetHost == circleHost) Lifecycle.State.RESUMED else Lifecycle.State.STARTED)
.setPrimaryNavigationFragment(targetHost) .setPrimaryNavigationFragment(targetHost)
.runOnCommit { .runOnCommit {
isSwitchingTab = false isSwitchingTab = false
if (targetTag == TAB_CIRCLE) applyCircleTabBackground() else resetBottomNavBackground()
updateBottomNavVisibility() updateBottomNavVisibility()
if (!force) { if (!force) {
@@ -417,14 +474,72 @@ class MainActivity : AppCompatActivity() {
.commit() .commit()
} }
private fun applyCircleTabBackground() {
bottomNav.itemBackground = null
if (blurReady) {
bottomNavBlur.visibility = View.VISIBLE
bottomNav.background = ColorDrawable(android.graphics.Color.TRANSPARENT)
} else {
bottomNavBlur.visibility = View.GONE
bottomNav.background = ColorDrawable(ContextCompat.getColor(this, R.color.black_30_percent))
}
}
private fun resetBottomNavBackground() {
bottomNav.itemBackground = null
bottomNav.background = ColorDrawable(ContextCompat.getColor(this, android.R.color.white))
bottomNav.backgroundTintList = null
}
private fun setupBottomNavBlur() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
blurReady = false
bottomNavBlur.visibility = View.GONE
return
}
val rootView = findViewById<ViewGroup>(android.R.id.content)?.getChildAt(0) as? ViewGroup
?: run { blurReady = false; bottomNavBlur.visibility = View.GONE; return }
// Lighter blur for higher transparency
val blurRadius = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) 8f else 6f
try {
val algorithm = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
RenderEffectBlur()
} else {
RenderScriptBlur(this)
}
bottomNavBlur.setupWith(rootView, algorithm)
.setFrameClearDrawable(window.decorView.background)
.setBlurRadius(blurRadius)
.setBlurAutoUpdate(true)
.setOverlayColor(ContextCompat.getColor(this, R.color.frosted_glass_bg))
blurReady = true
} catch (e: Exception) {
blurReady = false
bottomNavBlur.visibility = View.GONE
}
}
/** 打开全局页login/recharge等 */ /** 打开全局页login/recharge等 */
private fun openGlobal(destId: Int, bundle: Bundle? = null) { private fun openGlobal(destId: Int, bundle: Bundle? = null, clearBackStack: Boolean = false) {
val fm = supportFragmentManager val fm = supportFragmentManager
if (fm.isStateSaved) return if (fm.isStateSaved) return
val navOptions = if (clearBackStack) {
navOptions {
// 清理 global overlay 栈,但不短暂显示 empty避免闪屏
popUpTo(R.id.globalEmptyFragment) { inclusive = false }
}
} else {
null
}
try { try {
if (bundle != null) globalNavController.navigate(destId, bundle) if (bundle != null) globalNavController.navigate(destId, bundle, navOptions)
else globalNavController.navigate(destId) else globalNavController.navigate(destId, null, navOptions)
} catch (e: IllegalArgumentException) { } catch (e: IllegalArgumentException) {
e.printStackTrace() e.printStackTrace()
} }
@@ -441,6 +556,7 @@ class MainActivity : AppCompatActivity() {
homeHost.navController.addOnDestinationChangedListener(listener) homeHost.navController.addOnDestinationChangedListener(listener)
shopHost.navController.addOnDestinationChangedListener(listener) shopHost.navController.addOnDestinationChangedListener(listener)
mineHost.navController.addOnDestinationChangedListener(listener) mineHost.navController.addOnDestinationChangedListener(listener)
circleHost.navController.addOnDestinationChangedListener(listener)
BehaviorReporter.report( BehaviorReporter.report(
isNewUser = false, isNewUser = false,
"page_id" to "home", "page_id" to "home",
@@ -452,6 +568,7 @@ class MainActivity : AppCompatActivity() {
homeHost.navController.addOnDestinationChangedListener(homeRouteListener) homeHost.navController.addOnDestinationChangedListener(homeRouteListener)
shopHost.navController.addOnDestinationChangedListener(shopRouteListener) shopHost.navController.addOnDestinationChangedListener(shopRouteListener)
mineHost.navController.addOnDestinationChangedListener(mineRouteListener) mineHost.navController.addOnDestinationChangedListener(mineRouteListener)
circleHost.navController.addOnDestinationChangedListener(circleRouteListener)
globalHost.navController.addOnDestinationChangedListener(globalRouteListener) globalHost.navController.addOnDestinationChangedListener(globalRouteListener)
// ✅ 删除:初始化手动上报(否则启动时会重复上报) // ✅ 删除:初始化手动上报(否则启动时会重复上报)
@@ -559,6 +676,7 @@ class MainActivity : AppCompatActivity() {
R.id.notificationFragment -> "notice" // 消息通知 R.id.notificationFragment -> "notice" // 消息通知
R.id.feedbackFragment -> "feedback" // 意见反馈 R.id.feedbackFragment -> "feedback" // 意见反馈
R.id.consumptionRecordFragment -> "consumption_record" // 消费记录 R.id.consumptionRecordFragment -> "consumption_record" // 消费记录
R.id.languageFragment -> "language_settings" // 语言切换页
/** ==================== 登录 & 注册 ==================== */ /** ==================== 登录 & 注册 ==================== */
R.id.loginFragment -> "login" // 登录页 R.id.loginFragment -> "login" // 登录页
@@ -598,4 +716,97 @@ class MainActivity : AppCompatActivity() {
"page_id" to pageId, "page_id" to pageId,
) )
} }
// 网络检测:无网络时弹窗提醒,恢复后分发刷新事件
private fun setupNetworkMonitor() {
val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
connectivityManager = cm
if (cm == null) return
hasNetworkConnection = isNetworkConnected(cm)
if (!hasNetworkConnection) {
showNoNetworkDialog()
NetworkEventBus.emit(NetworkEvent.NetworkLost)
}
val callback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
handleNetworkStateChange(true)
}
override fun onLost(network: Network) {
handleNetworkStateChange(isNetworkConnected(cm))
}
}
networkCallback = callback
runCatching {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
cm.registerDefaultNetworkCallback(callback)
} else {
cm.registerNetworkCallback(buildNetworkRequest(), callback)
}
}.onFailure { e ->
Log.e("MainActivity", "registerNetworkCallback failed: ${e.message}")
}
}
private fun handleNetworkStateChange(connected: Boolean) {
if (connected == hasNetworkConnection) return
hasNetworkConnection = connected
runOnUiThread {
if (connected) {
dismissNoNetworkDialog()
NetworkEventBus.emit(NetworkEvent.NetworkAvailable)
} else {
showNoNetworkDialog()
NetworkEventBus.emit(NetworkEvent.NetworkLost)
}
}
}
private fun showNoNetworkDialog() {
if (isFinishing || isDestroyed) return
if (noNetworkDialog?.isShowing == true) return
val dialogView = layoutInflater.inflate(R.layout.dialog_no_network, null)
dialogView.findViewById<MaterialButton>(R.id.btnDismiss)?.setOnClickListener {
noNetworkDialog?.dismiss()
}
noNetworkDialog = AlertDialog.Builder(this)
.setView(dialogView)
.setCancelable(false)
.create()
noNetworkDialog?.window?.setBackgroundDrawable(ColorDrawable(android.graphics.Color.TRANSPARENT))
noNetworkDialog?.show()
}
private fun dismissNoNetworkDialog() {
noNetworkDialog?.dismiss()
noNetworkDialog = null
}
private fun isNetworkConnected(cm: ConnectivityManager): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val network = cm.activeNetwork ?: return false
val capabilities = cm.getNetworkCapabilities(network) ?: return false
capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) ||
capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
} else {
@Suppress("DEPRECATION")
cm.activeNetworkInfo?.isConnected == true
}
}
private fun buildNetworkRequest(): NetworkRequest {
val builder = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
// 让低版本也能触达 Wi-Fi / 蜂窝网络
builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
return builder.build()
}
} }

View File

@@ -9,9 +9,9 @@ class MyApp : Application() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
AppContext.init(this) // ✅ 新增:全局 Application Context AppContext.init(this) // ?? Application Context
RetrofitClient.init(this) RetrofitClient.init(this)
NetworkClient.init(this) // SSE 用(带 token/签名拦截器) NetworkClient.init(this) // SSE ???token/??????
} }
} }

View File

@@ -58,7 +58,7 @@ class OnboardingActivity : AppCompatActivity() {
startActivity(Intent(this, MainActivity::class.java)) startActivity(Intent(this, MainActivity::class.java))
finish() finish()
}else{ }else{
Toast.makeText(this, "Please select your gender.", Toast.LENGTH_SHORT).show() Toast.makeText(this, getString(R.string.gender_hint), Toast.LENGTH_SHORT).show()
} }
} }

View File

@@ -11,6 +11,8 @@ import com.example.myapplication.network.BehaviorReporter
class SplashActivity : AppCompatActivity() { class SplashActivity : AppCompatActivity() {
// private lateinit var progressBar: ProgressBar // private lateinit var progressBar: ProgressBar
private val handler = Handler(Looper.getMainLooper())
private var pendingNavigation: Runnable? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -18,7 +20,6 @@ class SplashActivity : AppCompatActivity() {
// progressBar = findViewById(R.id.progressBar) // progressBar = findViewById(R.id.progressBar)
Handler(Looper.getMainLooper()).postDelayed({
val prefs = getSharedPreferences("app_prefs", MODE_PRIVATE) val prefs = getSharedPreferences("app_prefs", MODE_PRIVATE)
val isFirstLaunch = prefs.getBoolean("is_first_launch", true) val isFirstLaunch = prefs.getBoolean("is_first_launch", true)
if (isFirstLaunch) { if (isFirstLaunch) {
@@ -32,24 +33,30 @@ class SplashActivity : AppCompatActivity() {
) )
} }
val targetIntent = if (isFirstLaunch) { val navigationTask = Runnable {
// 第一次启动 → 进入引导页 val stillFirstLaunch = prefs.getBoolean("is_first_launch", true)
val targetIntent = if (stillFirstLaunch) {
prefs.edit().putBoolean("is_first_launch", false).apply() prefs.edit().putBoolean("is_first_launch", false).apply()
Intent(this, OnboardingActivity::class.java) Intent(this, OnboardingActivity::class.java)
} else { } else {
// 不是第一次 → 进入主界面携带原始intent的参数
Intent(this, MainActivity::class.java).apply { Intent(this, MainActivity::class.java).apply {
intent.extras?.let { putExtras(it) } intent.extras?.let { putExtras(it) }
} }
} }
startActivity(targetIntent) startActivity(targetIntent)
finish() finish()
}, 1000) // 0.5秒延迟,确保初始化 }
pendingNavigation = navigationTask
val skipDelay = intent?.getBooleanExtra("skip_splash_delay", false) ?: false
val delayMs = if (skipDelay) 0L else 1000L
handler.postDelayed(navigationTask, delayMs)
} }
override fun onDestroy() { override fun onDestroy() {
pendingNavigation?.let { handler.removeCallbacks(it) }
pendingNavigation = null
// progressBar.clearAnimation() // progressBar.clearAnimation()
super.onDestroy() super.onDestroy()
} }
} }

View File

@@ -629,7 +629,7 @@ class AiKeyboard(
val list = resp.data ?: emptyList() val list = resp.data ?: emptyList()
renderPersonaCards(container, list) renderPersonaCards(container, list)
} else if (resp.code == 40102) { } else if (resp.code == 40102) {
Toast.makeText(env.ctx, "You need to log in to use this function.", Toast.LENGTH_LONG).show() Toast.makeText(env.ctx, env.ctx.getString(com.example.myapplication.R.string.Pop_up_window_ai_1), Toast.LENGTH_LONG).show()
} else { } else {
Toast.makeText(env.ctx, resp.message, Toast.LENGTH_LONG).show() Toast.makeText(env.ctx, resp.message, Toast.LENGTH_LONG).show()
} }

View File

@@ -25,7 +25,11 @@ sealed class AuthEvent {
data class GenericError(val message: String) : AuthEvent() data class GenericError(val message: String) : AuthEvent()
object LoginSuccess : AuthEvent() object LoginSuccess : AuthEvent()
data class Logout(val returnTabTag: String) : AuthEvent() data class Logout(val returnTabTag: String) : AuthEvent()
data class OpenGlobalPage(val destinationId: Int, val bundle: Bundle? = null) : AuthEvent() data class OpenGlobalPage(
val destinationId: Int,
val bundle: Bundle? = null,
val clearGlobalBackStack: Boolean = false
) : AuthEvent()
object UserUpdated : AuthEvent() object UserUpdated : AuthEvent()
data class CharacterDeleted(val characterId: Int) : AuthEvent() data class CharacterDeleted(val characterId: Int) : AuthEvent()
} }

View File

@@ -0,0 +1,22 @@
package com.example.myapplication.network
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
sealed class NetworkEvent {
object NetworkAvailable : NetworkEvent()
object NetworkLost : NetworkEvent()
}
object NetworkEventBus {
private val _events = MutableSharedFlow<NetworkEvent>(
replay = 0,
extraBufferCapacity = 1
)
val events: SharedFlow<NetworkEvent> = _events
fun emit(event: NetworkEvent) {
_events.tryEmit(event)
}
}

View File

@@ -0,0 +1,67 @@
package com.example.myapplication.ui.circle
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.fragment.app.setFragmentResultListener
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import com.bumptech.glide.Glide
import com.example.myapplication.R
import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus
import com.example.myapplication.network.NetworkEvent
import com.example.myapplication.network.NetworkEventBus
import com.example.myapplication.network.LoginResponse
import com.example.myapplication.network.ApiResponse
import com.example.myapplication.network.ShareResponse
import com.example.myapplication.network.RetrofitClient
import com.example.myapplication.ui.common.LoadingOverlay
import com.example.myapplication.utils.EncryptedSharedPreferencesUtil
import de.hdodenhof.circleimageview.CircleImageView
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import com.example.myapplication.network.BehaviorReporter
class CircleFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = inflater.inflate(R.layout.fragment_circle, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
NetworkEventBus.events.collect { event ->
if (event is NetworkEvent.NetworkAvailable) {
Log.d("CircleFragment", "Network restored, refresh circle content if needed")
}
}
}
}
}
}

View File

@@ -31,6 +31,8 @@ import com.example.myapplication.network.AddPersonaClick
import com.example.myapplication.network.AuthEvent import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus import com.example.myapplication.network.AuthEventBus
import com.example.myapplication.network.BehaviorReporter import com.example.myapplication.network.BehaviorReporter
import com.example.myapplication.network.NetworkEvent
import com.example.myapplication.network.NetworkEventBus
import com.example.myapplication.network.RetrofitClient import com.example.myapplication.network.RetrofitClient
import com.example.myapplication.network.listByTagWithNotLogin import com.example.myapplication.network.listByTagWithNotLogin
import com.example.myapplication.utils.EncryptedSharedPreferencesUtil import com.example.myapplication.utils.EncryptedSharedPreferencesUtil
@@ -58,6 +60,7 @@ class HomeFragment : Fragment() {
private lateinit var loadingOverlay: LoadingOverlay private lateinit var loadingOverlay: LoadingOverlay
private var preloadJob: Job? = null private var preloadJob: Job? = null
private var networkRefreshJob: Job? = null
private var allPersonaCache: List<listByTagWithNotLogin> = emptyList() private var allPersonaCache: List<listByTagWithNotLogin> = emptyList()
private val personaCache = mutableMapOf<Int, List<listByTagWithNotLogin>>() private val personaCache = mutableMapOf<Int, List<listByTagWithNotLogin>>()
@@ -79,6 +82,7 @@ class HomeFragment : Fragment() {
override fun onDestroyView() { override fun onDestroyView() {
preloadJob?.cancel() preloadJob?.cancel()
networkRefreshJob?.cancel()
pageChangeCallback?.let { viewPager.unregisterOnPageChangeCallback(it) } pageChangeCallback?.let { viewPager.unregisterOnPageChangeCallback(it) }
pageChangeCallback = null pageChangeCallback = null
sheetAdapter = null sheetAdapter = null
@@ -238,6 +242,16 @@ class HomeFragment : Fragment() {
loadingOverlay = LoadingOverlay.attach(root) loadingOverlay = LoadingOverlay.attach(root)
Log.d("HomeFragment", "LoadingOverlay initialized") Log.d("HomeFragment", "LoadingOverlay initialized")
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
NetworkEventBus.events.collect { event ->
if (event is NetworkEvent.NetworkAvailable) {
refreshHomeAfterNetwork()
}
}
}
}
root.post { root.post {
if (!isAdded) return@post if (!isAdded) return@post
parentWidth = root.width parentWidth = root.width
@@ -634,6 +648,37 @@ class HomeFragment : Fragment() {
} }
} }
private fun refreshHomeAfterNetwork() {
networkRefreshJob?.cancel()
networkRefreshJob = viewLifecycleOwner.lifecycleScope.launch {
preloadJob?.cancel()
loadingOverlay.show()
try {
val list = fetchAllPersonaList()
if (!isAdded) return@launch
allPersonaCache = list
lastList1RenderKey = null
personaCache.clear()
notifyPageChangedOnMain(0)
val response = RetrofitClient.apiService.tagList()
if (!isAdded) return@launch
tags.clear()
response.data?.let { networkTags ->
tags.addAll(networkTags.map { Tag(it.id, it.tagName) })
}
sheetAdapter?.updatePageCount(1 + tags.size)
setupTags()
startPreloadAllTagsFillCacheOnly()
} catch (e: Exception) {
Log.e("HomeFragment", "refresh after network fail", e)
} finally {
loadingOverlay.hide()
}
}
}
// ---------------- 预加载:只填缓存,不刷新 UI ---------------- // ---------------- 预加载:只填缓存,不刷新 UI ----------------
private fun startPreloadAllTagsFillCacheOnly() { private fun startPreloadAllTagsFillCacheOnly() {

View File

@@ -62,7 +62,7 @@ class PersonaDetailDialogFragment : DialogFragment() {
tvName.text = data.characterName ?: "" tvName.text = data.characterName ?: ""
download.text = data.download ?: "" download.text = data.download ?: ""
tvBackground.text = data.characterBackground ?: "" tvBackground.text = data.characterBackground ?: ""
btnAdd.text = if (data.added == true) "Added" else "Add" btnAdd.text = if (data.added == true) getString(R.string.added) else getString(R.string.add)
btnAdd.setBackgroundResource(if (data.added == true) R.drawable.ic_added else R.drawable.keyboard_ettings) btnAdd.setBackgroundResource(if (data.added == true) R.drawable.ic_added else R.drawable.keyboard_ettings)
val newAdded = !(data.added ?: false) val newAdded = !(data.added ?: false)

View File

@@ -36,6 +36,8 @@ import com.example.myapplication.work.ThemeDownloadWorker
import com.example.myapplication.ui.shop.ShopEvent import com.example.myapplication.ui.shop.ShopEvent
import com.example.myapplication.ui.shop.ShopEventBus import com.example.myapplication.ui.shop.ShopEventBus
import com.example.myapplication.network.BehaviorReporter import com.example.myapplication.network.BehaviorReporter
import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus
class KeyboardDetailFragment : Fragment() { class KeyboardDetailFragment : Fragment() {
@@ -103,7 +105,8 @@ class KeyboardDetailFragment : Fragment() {
} }
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener { view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
parentFragmentManager.popBackStack() AuthEventBus.emit(AuthEvent.UserUpdated)
requireActivity().onBackPressedDispatcher.onBackPressed()
} }
//充值主题 //充值主题
@@ -143,7 +146,7 @@ class KeyboardDetailFragment : Fragment() {
.into(shapeableImageView) .into(shapeableImageView)
tvKeyboardName.text = themeDetailResp?.themeName tvKeyboardName.text = themeDetailResp?.themeName
tvDownloadCount.text = "Download:${themeDetailResp?.themeDownload}" tvDownloadCount.text = getString(R.string.detail_download)+"${themeDetailResp?.themeDownload}"
tvPrice.text = "${themeDetailResp?.themePrice}" tvPrice.text = "${themeDetailResp?.themePrice}"
if (themeDetailResp?.isPurchased ?: false) { if (themeDetailResp?.isPurchased ?: false) {
@@ -417,7 +420,7 @@ class KeyboardDetailFragment : Fragment() {
// 在主线程中更新UI // 在主线程中更新UI
view?.post { view?.post {
progressBar.visibility = View.VISIBLE progressBar.visibility = View.VISIBLE
enabledButtonText.text = "Loading..." enabledButtonText.text = getString(R.string.loading)
// 完全禁用按钮交互 // 完全禁用按钮交互
enabledButton.isEnabled = false enabledButton.isEnabled = false
enabledButton.isClickable = false enabledButton.isClickable = false
@@ -436,7 +439,7 @@ class KeyboardDetailFragment : Fragment() {
// 在主线程中更新UI // 在主线程中更新UI
view?.post { view?.post {
progressBar.visibility = View.GONE progressBar.visibility = View.GONE
enabledButtonText.text = "Enabled" enabledButtonText.text = getString(R.string.detail_enabled)
// 恢复按钮交互 // 恢复按钮交互
enabledButton.isEnabled = true enabledButton.isEnabled = true
enabledButton.isClickable = true enabledButton.isClickable = true

View File

@@ -60,11 +60,11 @@ class MyKeyboard : Fragment() {
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
val resp = setdelUserCharacter(item.id) val resp = setdelUserCharacter(item.id)
if (resp?.code == 0 && resp.data == true) { if (resp?.code == 0 && resp.data == true) {
Toast.makeText(requireContext(),"Deleted successfully", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(),getString(R.string.keyboard_delete_delete_success), Toast.LENGTH_SHORT).show()
AuthEventBus.emit(AuthEvent.CharacterDeleted(item.id)) AuthEventBus.emit(AuthEvent.CharacterDeleted(item.id))
loadList() loadList()
} else { } else {
Toast.makeText(requireContext(), resp?.message ?: "Delete failed", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), resp?.message ?:getString(R.string.keyboard_delete_delete_failed), Toast.LENGTH_SHORT).show()
} }
} }
} }
@@ -102,9 +102,9 @@ class MyKeyboard : Fragment() {
val resp = setupdateUserCharacterSort(body) val resp = setupdateUserCharacterSort(body)
if (resp?.code == 0 && resp.data == true) { if (resp?.code == 0 && resp.data == true) {
requireActivity().onBackPressedDispatcher.onBackPressed() requireActivity().onBackPressedDispatcher.onBackPressed()
Toast.makeText(requireContext(), "Sorting has been successfully modified.", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(),getString(R.string.Pop_up_window_my_keyboard_1), Toast.LENGTH_SHORT).show()
} else { } else {
Toast.makeText(requireContext(), resp?.message ?: "Save failed", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), resp?.message ?: getString(R.string.Pop_up_window_my_keyboard_2), Toast.LENGTH_SHORT).show()
} }
} catch (e: Exception) { } catch (e: Exception) {
Toast.makeText(requireContext(), "Network error: ${e.message}", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), "Network error: ${e.message}", Toast.LENGTH_SHORT).show()
@@ -124,10 +124,10 @@ class MyKeyboard : Fragment() {
adapter.submitList(resp.data) adapter.submitList(resp.data)
Log.d("1314520-list", resp.data.toString()) Log.d("1314520-list", resp.data.toString())
} else { } else {
Toast.makeText(requireContext(), resp?.message ?: "Load failed", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), resp?.message ?: getString(R.string.Pop_up_window_my_keyboard_3), Toast.LENGTH_SHORT).show()
} }
} catch (e: Exception) { } catch (e: Exception) {
Toast.makeText(requireContext(), "Load failed: ${e.message}", Toast.LENGTH_SHORT).show() Log.d("MyKeyboard-loadList", e.message.toString())
} finally { } finally {
swipeRefresh.isRefreshing = false swipeRefresh.isRefreshing = false
} }

View File

@@ -19,6 +19,8 @@ import com.example.myapplication.network.RetrofitClient
import com.example.myapplication.utils.EncryptedSharedPreferencesUtil import com.example.myapplication.utils.EncryptedSharedPreferencesUtil
import android.util.Log import android.util.Log
import com.example.myapplication.network.BehaviorReporter import com.example.myapplication.network.BehaviorReporter
import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus
class ForgetPasswordEmailFragment : Fragment() { class ForgetPasswordEmailFragment : Fragment() {
@@ -42,9 +44,9 @@ class ForgetPasswordEmailFragment : Fragment() {
emailEditText = view.findViewById<EditText>(R.id.et_email) emailEditText = view.findViewById<EditText>(R.id.et_email)
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener { view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
parentFragmentManager.popBackStack() AuthEventBus.emit(AuthEvent.UserUpdated)
requireActivity().onBackPressedDispatcher.onBackPressed()
} }
// 下一步按钮点击事件 // 下一步按钮点击事件
view.findViewById<TextView>(R.id.nextstep).setOnClickListener { view.findViewById<TextView>(R.id.nextstep).setOnClickListener {
// 对输入框去除首尾空格 // 对输入框去除首尾空格
@@ -52,9 +54,9 @@ class ForgetPasswordEmailFragment : Fragment() {
// 判断邮箱是否为空 // 判断邮箱是否为空
if (email.isEmpty()) { if (email.isEmpty()) {
Toast.makeText(activity, "Please enter your email address", Toast.LENGTH_SHORT).show() Toast.makeText(activity,getString(R.string.Pop_up_window_MForgetPasswordEmailFragmentyKeyboard_1), Toast.LENGTH_SHORT).show()
} else if (!isValidEmail(email)) { } else if (!isValidEmail(email)) {
Toast.makeText(activity, "The email address format is incorrect", Toast.LENGTH_SHORT).show() Toast.makeText(activity, getString(R.string.Pop_up_window_MForgetPasswordEmailFragmentyKeyboard_2), Toast.LENGTH_SHORT).show()
} else { } else {
BehaviorReporter.report( BehaviorReporter.report(
isNewUser = false, isNewUser = false,
@@ -68,8 +70,8 @@ class ForgetPasswordEmailFragment : Fragment() {
val response = RetrofitClient.apiService.sendVerifyCode(body) val response = RetrofitClient.apiService.sendVerifyCode(body)
if (response.code == 0) { if (response.code == 0) {
EncryptedSharedPreferencesUtil.save(requireContext(), "forget_email", email) EncryptedSharedPreferencesUtil.save(requireContext(), "forget_email", email)
findNavController().navigate(R.id.action_forgetPasswordEmailFragment_to_forgetPasswordVerifyFragment) AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.forgetPasswordVerifyFragment))
Toast.makeText(activity, "A verification email has been sent to ${email}. Please check your inbox to complete the verification.", Toast.LENGTH_LONG).show() Toast.makeText(activity, getString(R.string.register_email_verification_message_1)+"${email}"+getString(R.string.register_email_verification_message_2), Toast.LENGTH_LONG).show()
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e("1314520-MineFragment", "发送验证码失败", e) Log.e("1314520-MineFragment", "发送验证码失败", e)

View File

@@ -22,6 +22,8 @@ import com.example.myapplication.ui.common.LoadingOverlay
import com.example.myapplication.utils.EncryptedSharedPreferencesUtil import com.example.myapplication.utils.EncryptedSharedPreferencesUtil
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import com.example.myapplication.network.BehaviorReporter import com.example.myapplication.network.BehaviorReporter
import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus
class ForgetPasswordResetFragment : Fragment() { class ForgetPasswordResetFragment : Fragment() {
@@ -45,7 +47,8 @@ class ForgetPasswordResetFragment : Fragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener { view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
parentFragmentManager.popBackStack() AuthEventBus.emit(AuthEvent.UserUpdated)
requireActivity().onBackPressedDispatcher.onBackPressed()
} }
passwordEditText = view.findViewById<EditText>(R.id.et_password) passwordEditText = view.findViewById<EditText>(R.id.et_password)
@@ -107,9 +110,9 @@ class ForgetPasswordResetFragment : Fragment() {
//判断密码,邮箱,确认密码是否为空 //判断密码,邮箱,确认密码是否为空
if (password.isEmpty() || confirmPassword.isEmpty()) { if (password.isEmpty() || confirmPassword.isEmpty()) {
Toast.makeText(activity, "Please fill in the complete information", Toast.LENGTH_SHORT).show() Toast.makeText(activity, getString(R.string.Pop_up_window_MForgetPasswordEmailFragmentyKeyboard_2), Toast.LENGTH_SHORT).show()
} else if (password != confirmPassword) { } else if (password != confirmPassword) {
Toast.makeText(activity, "The two password entries are inconsistent", Toast.LENGTH_SHORT).show() Toast.makeText(activity, getString(R.string.Pop_up_window_ForgetPasswordResetFragment_1), Toast.LENGTH_SHORT).show()
} else { } else {
BehaviorReporter.report( BehaviorReporter.report(
isNewUser = false, isNewUser = false,
@@ -127,7 +130,7 @@ class ForgetPasswordResetFragment : Fragment() {
val response = RetrofitClient.apiService.resetPassword(body) val response = RetrofitClient.apiService.resetPassword(body)
if (response.code == 0) { if (response.code == 0) {
EncryptedSharedPreferencesUtil.remove(requireContext(), "forget_email") EncryptedSharedPreferencesUtil.remove(requireContext(), "forget_email")
Toast.makeText(activity, "Password reset successful. Please log in again.", Toast.LENGTH_LONG).show() Toast.makeText(activity, getString(R.string.Pop_up_window_ForgetPasswordResetFragment_2), Toast.LENGTH_LONG).show()
// 使用忘记密码专用的action跳转到登录页面 // 使用忘记密码专用的action跳转到登录页面
findNavController().navigate(R.id.action_global_loginFragment_from_forget_password) findNavController().navigate(R.id.action_global_loginFragment_from_forget_password)
} }

View File

@@ -22,6 +22,8 @@ import com.example.myapplication.network.RetrofitClient
import com.example.myapplication.network.VerifyCodeRequest import com.example.myapplication.network.VerifyCodeRequest
import android.util.Log import android.util.Log
import com.example.myapplication.network.BehaviorReporter import com.example.myapplication.network.BehaviorReporter
import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus
class ForgetPasswordVerifyFragment : Fragment() { class ForgetPasswordVerifyFragment : Fragment() {
@@ -42,18 +44,19 @@ class ForgetPasswordVerifyFragment : Fragment() {
val savedEmail = EncryptedSharedPreferencesUtil.get(requireContext(), "forget_email", String::class.java) val savedEmail = EncryptedSharedPreferencesUtil.get(requireContext(), "forget_email", String::class.java)
view.findViewById<TextView>(R.id.tv_code_hint).setText("A verification email has been sent to ${savedEmail}. Please check your inbox to complete the verification.") view.findViewById<TextView>(R.id.tv_code_hint).setText(getString(R.string.register_email_verification_message_1)+"${savedEmail}"+getString(R.string.register_email_verification_message_2))
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener { view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
parentFragmentManager.popBackStack() AuthEventBus.emit(AuthEvent.UserUpdated)
requireActivity().onBackPressedDispatcher.onBackPressed()
} }
view.findViewById<TextView>(R.id.nextstep).setOnClickListener { view.findViewById<TextView>(R.id.nextstep).setOnClickListener {
// 验证验证码 // 验证验证码
val verifyCode = getVerifyCode() val verifyCode = getVerifyCode()
if (verifyCode.length != 6) { if (verifyCode.length != 6) {
Toast.makeText(activity, "The verification code format is incorrect", Toast.LENGTH_SHORT).show() Toast.makeText(activity,getString(R.string.Pop_up_window_ForgetPasswordVerifyFragment_1), Toast.LENGTH_SHORT).show()
return@setOnClickListener return@setOnClickListener
} }
@@ -73,8 +76,8 @@ class ForgetPasswordVerifyFragment : Fragment() {
) )
val response = RetrofitClient.apiService.verifyCode(body) val response = RetrofitClient.apiService.verifyCode(body)
if (response.code == 0 && response.data == true){ if (response.code == 0 && response.data == true){
Toast.makeText(activity, "The verification code has been verified successfully", Toast.LENGTH_SHORT).show() Toast.makeText(activity, getString(R.string.Pop_up_window_ForgetPasswordVerifyFragment_2), Toast.LENGTH_SHORT).show()
findNavController().navigate(R.id.action_forgetPasswordVerifyFragment_to_forgetPasswordResetFragment) AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.forgetPasswordResetFragment))
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e("1314520-MineFragment", "验证码验证失败", e) Log.e("1314520-MineFragment", "验证码验证失败", e)

View File

@@ -63,7 +63,7 @@ class LoginFragment : Fragment() {
"page_id" to "login", "page_id" to "login",
"element_id" to "signup_btn", "element_id" to "signup_btn",
) )
findNavController().navigate(R.id.action_loginFragment_to_registerFragment) AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.registerFragment))
} }
// 忘记密码 // 忘记密码
view.findViewById<TextView>(R.id.tv_forgot_password).setOnClickListener { view.findViewById<TextView>(R.id.tv_forgot_password).setOnClickListener {
@@ -72,11 +72,12 @@ class LoginFragment : Fragment() {
"page_id" to "login", "page_id" to "login",
"element_id" to "forgot_btn", "element_id" to "forgot_btn",
) )
findNavController().navigate(R.id.action_loginFragment_to_forgetPasswordEmailFragment) AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.forgetPasswordEmailFragment))
} }
// 返回 - 在global_graph中直接popBackStack回到globalEmptyFragment // 返回 - 在global_graph中直接popBackStack回到globalEmptyFragment
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener { view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
findNavController().popBackStack() AuthEventBus.emit(AuthEvent.UserUpdated)
requireActivity().onBackPressedDispatcher.onBackPressed()
} }
// 绑定控件id 必须和 xml 里的一样) // 绑定控件id 必须和 xml 里的一样)
passwordEditText = view.findViewById(R.id.et_password) passwordEditText = view.findViewById(R.id.et_password)
@@ -119,7 +120,7 @@ class LoginFragment : Fragment() {
val email = emailEditText.text?.toString().orEmpty() val email = emailEditText.text?.toString().orEmpty()
if (pwd.isEmpty() || email.isEmpty()) { if (pwd.isEmpty() || email.isEmpty()) {
// 输入框不能为空 // 输入框不能为空
Toast.makeText(requireContext(), "The password and email address cannot be left empty!", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), getString(R.string.Pop_up_window_LoginFragment_1), Toast.LENGTH_SHORT).show()
} else { } else {
BehaviorReporter.report( BehaviorReporter.report(
isNewUser = false, isNewUser = false,
@@ -145,12 +146,12 @@ class LoginFragment : Fragment() {
AuthEventBus.emit(AuthEvent.CharacterDeleted(0)) AuthEventBus.emit(AuthEvent.CharacterDeleted(0))
// 不在这里popBackStack让MainActivity的LoginSuccess事件处理关闭全局overlay // 不在这里popBackStack让MainActivity的LoginSuccess事件处理关闭全局overlay
} else { } else {
Toast.makeText(requireContext(), "Login failed: ${response.message}", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), getString(R.string.Pop_up_window_LoginFragment_2)+"${response.message}", Toast.LENGTH_SHORT).show()
} }
loadingOverlay?.hide() loadingOverlay?.hide()
} catch (e: Exception) { } catch (e: Exception) {
Log.e("1314520-LoginFragment", "登录请求失败: ${e.message}", e) Log.e("1314520-LoginFragment", "登录请求失败: ${e.message}", e)
Toast.makeText(requireContext(), "Login failed: ${e.message}", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), getString(R.string.Pop_up_window_LoginFragment_2)+"${e.message}", Toast.LENGTH_SHORT).show()
loadingOverlay?.hide() loadingOverlay?.hide()
} }
} }

View File

@@ -20,6 +20,8 @@ import com.example.myapplication.utils.EncryptedSharedPreferencesUtil
import com.example.myapplication.ui.common.LoadingOverlay import com.example.myapplication.ui.common.LoadingOverlay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import android.util.Log import android.util.Log
import com.example.myapplication.network.AuthEventBus
import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.BehaviorReporter import com.example.myapplication.network.BehaviorReporter
class RegisterFragment : Fragment() { class RegisterFragment : Fragment() {
@@ -108,11 +110,11 @@ class RegisterFragment : Fragment() {
//判断密码,邮箱,确认密码是否为空 //判断密码,邮箱,确认密码是否为空
if (password.isEmpty() || email.isEmpty() || confirmPassword.isEmpty()) { if (password.isEmpty() || email.isEmpty() || confirmPassword.isEmpty()) {
Toast.makeText(activity, "Please fill in the complete information", Toast.LENGTH_SHORT).show() Toast.makeText(activity,getString(R.string.Pop_up_window_RegisterFragment_1), Toast.LENGTH_SHORT).show()
} else if (password != confirmPassword) { } else if (password != confirmPassword) {
Toast.makeText(activity, "The two password entries are inconsistent", Toast.LENGTH_SHORT).show() Toast.makeText(activity,getString(R.string.Pop_up_window_ForgetPasswordResetFragment_1), Toast.LENGTH_SHORT).show()
} else if (!isValidEmail(email)) { } else if (!isValidEmail(email)) {
Toast.makeText(activity, "The email address format is incorrect", Toast.LENGTH_SHORT).show() Toast.makeText(activity,getString(R.string.Pop_up_window_MForgetPasswordEmailFragmentyKeyboard_2), Toast.LENGTH_SHORT).show()
} else { } else {
BehaviorReporter.report( BehaviorReporter.report(
isNewUser = false, isNewUser = false,
@@ -128,8 +130,8 @@ class RegisterFragment : Fragment() {
EncryptedSharedPreferencesUtil.save(requireContext(), "register_email", email) EncryptedSharedPreferencesUtil.save(requireContext(), "register_email", email)
EncryptedSharedPreferencesUtil.save(requireContext(), "register_password", password) EncryptedSharedPreferencesUtil.save(requireContext(), "register_password", password)
EncryptedSharedPreferencesUtil.save(requireContext(), "register_confirm_password", confirmPassword) EncryptedSharedPreferencesUtil.save(requireContext(), "register_confirm_password", confirmPassword)
findNavController().navigate(R.id.action_registerFragment_to_registerVerifyFragment) AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.registerVerifyFragment))
Toast.makeText(activity, "A verification email has been sent to ${email}. Please check your inbox to complete the verification.", Toast.LENGTH_LONG).show() Toast.makeText(activity, getString(R.string.register_email_verification_message_1)+"${email}"+getString(R.string.register_email_verification_message_2), Toast.LENGTH_LONG).show()
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e("1314520-MineFragment", "获取失败", e) Log.e("1314520-MineFragment", "获取失败", e)
@@ -144,7 +146,8 @@ class RegisterFragment : Fragment() {
// 返回按钮 // 返回按钮
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener { view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
parentFragmentManager.popBackStack() AuthEventBus.emit(AuthEvent.UserUpdated)
requireActivity().onBackPressedDispatcher.onBackPressed()
} }
} }

View File

@@ -20,6 +20,8 @@ import com.example.myapplication.ui.common.CodeEditText
import com.example.myapplication.utils.EncryptedSharedPreferencesUtil import com.example.myapplication.utils.EncryptedSharedPreferencesUtil
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import android.widget.TextView import android.widget.TextView
import com.example.myapplication.network.AuthEventBus
import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.BehaviorReporter import com.example.myapplication.network.BehaviorReporter
class RegisterVerifyFragment : Fragment() { class RegisterVerifyFragment : Fragment() {
@@ -42,7 +44,8 @@ class RegisterVerifyFragment : Fragment() {
loadingOverlay = com.example.myapplication.ui.common.LoadingOverlay.attach(view as ViewGroup) loadingOverlay = com.example.myapplication.ui.common.LoadingOverlay.attach(view as ViewGroup)
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener { view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
parentFragmentManager.popBackStack() AuthEventBus.emit(AuthEvent.UserUpdated)
requireActivity().onBackPressedDispatcher.onBackPressed()
} }
// 注意:布局里的 6 个输入框需要是 CodeEditText // 注意:布局里的 6 个输入框需要是 CodeEditText
@@ -63,13 +66,12 @@ class RegisterVerifyFragment : Fragment() {
val savedGender = EncryptedSharedPreferencesUtil.get(requireContext(), "gender", String::class.java) val savedGender = EncryptedSharedPreferencesUtil.get(requireContext(), "gender", String::class.java)
val savedInviteCode = EncryptedSharedPreferencesUtil.get(requireContext(), "inviteCode", String::class.java) val savedInviteCode = EncryptedSharedPreferencesUtil.get(requireContext(), "inviteCode", String::class.java)
view.findViewById<TextView>(R.id.tv_code_hint).text = view.findViewById<TextView>(R.id.tv_code_hint).text = getString(R.string.register_email_verification_message_1)+"${savedEmail}"+getString(R.string.register_email_verification_message_2)
"A verification email has been sent to ${savedEmail}. Please check your inbox to complete the verification."
view.findViewById<TextView>(R.id.nextstep).setOnClickListener { view.findViewById<TextView>(R.id.nextstep).setOnClickListener {
val verifyCode = getVerifyCode() val verifyCode = getVerifyCode()
if (verifyCode.length != 6) { if (verifyCode.length != 6) {
Toast.makeText(activity, "The verification code format is incorrect", Toast.LENGTH_SHORT).show() Toast.makeText(activity, getString(R.string.Pop_up_window_ForgetPasswordVerifyFragment_1), Toast.LENGTH_SHORT).show()
return@setOnClickListener return@setOnClickListener
} }
@@ -92,11 +94,11 @@ class RegisterVerifyFragment : Fragment() {
val response = RetrofitClient.apiService.register(body) val response = RetrofitClient.apiService.register(body)
if (response.code == 0) { if (response.code == 0) {
Toast.makeText(activity, "Registration successful", Toast.LENGTH_SHORT).show() Toast.makeText(activity, getString(R.string.Pop_up_window_RegisterVerifyFragment_2), Toast.LENGTH_SHORT).show()
EncryptedSharedPreferencesUtil.remove(requireContext(), "register_email") EncryptedSharedPreferencesUtil.remove(requireContext(), "register_email")
EncryptedSharedPreferencesUtil.remove(requireContext(), "register_password") EncryptedSharedPreferencesUtil.remove(requireContext(), "register_password")
EncryptedSharedPreferencesUtil.remove(requireContext(), "register_confirm_password") EncryptedSharedPreferencesUtil.remove(requireContext(), "register_confirm_password")
findNavController().navigate(R.id.action_global_loginFragment) AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.loginFragment, clearGlobalBackStack = true))
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e("1314520-MineFragment", "注册失败", e) Log.e("1314520-MineFragment", "注册失败", e)

View File

@@ -24,6 +24,8 @@ import com.bumptech.glide.Glide
import com.example.myapplication.R import com.example.myapplication.R
import com.example.myapplication.network.AuthEvent import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus import com.example.myapplication.network.AuthEventBus
import com.example.myapplication.network.NetworkEvent
import com.example.myapplication.network.NetworkEventBus
import com.example.myapplication.network.LoginResponse import com.example.myapplication.network.LoginResponse
import com.example.myapplication.network.ApiResponse import com.example.myapplication.network.ApiResponse
import com.example.myapplication.network.ShareResponse import com.example.myapplication.network.ShareResponse
@@ -85,7 +87,7 @@ class MineFragment : Fragment() {
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText("h5Link", link) val clip = ClipData.newPlainText("h5Link", link)
clipboard.setPrimaryClip(clip) clipboard.setPrimaryClip(clip)
Toast.makeText(context, "The sharing link has been copied to the clipboard.", Toast.LENGTH_LONG).show() Toast.makeText(context, getString(R.string.copy_invite_link_success), Toast.LENGTH_LONG).show()
BehaviorReporter.report( BehaviorReporter.report(
isNewUser = false, isNewUser = false,
"page_id" to "my", "page_id" to "my",
@@ -155,6 +157,17 @@ class MineFragment : Fragment() {
"item_title" to "通知" "item_title" to "通知"
) )
} }
view.findViewById<LinearLayout>(R.id.click_Language).setOnClickListener {
AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.languageFragment))
BehaviorReporter.report(
isNewUser = false,
"page_id" to "my",
"element_id" to "menu_item",
"item_title" to "language_switch"
)
}
// ✅ 监听登录成功/登出事件(跨 NavHost 可靠) // ✅ 监听登录成功/登出事件(跨 NavHost 可靠)
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
@@ -175,6 +188,16 @@ class MineFragment : Fragment() {
} }
} }
} }
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
NetworkEventBus.events.collect { event ->
if (event is NetworkEvent.NetworkAvailable) {
refreshUser(force = true, showToast = false)
}
}
}
}
} }
override fun onResume() { override fun onResume() {
@@ -192,7 +215,7 @@ class MineFragment : Fragment() {
LoginResponse::class.java LoginResponse::class.java
) )
nickname.text = cached?.nickName ?: "" nickname.text = cached?.nickName ?: ""
time.text = cached?.vipExpiry?.let { "Due on November $it" } ?: "" time.text = cached?.vipExpiry?.let { getString(R.string.mine_vip_due_on, it) } ?: ""
cached?.avatarUrl?.let { url -> cached?.avatarUrl?.let { url ->
Glide.with(requireContext()) Glide.with(requireContext())
.load(url) .load(url)
@@ -207,7 +230,7 @@ class MineFragment : Fragment() {
*/ */
private fun refreshUser(force: Boolean, showToast: Boolean = false) { private fun refreshUser(force: Boolean, showToast: Boolean = false) {
if (!isLoggedIn()) { if (!isLoggedIn()) {
if (showToast && isAdded) Toast.makeText(requireContext(), "未登录", Toast.LENGTH_SHORT).show() if (showToast && isAdded) Toast.makeText(requireContext(), getString(R.string.not_logged_in_toast), Toast.LENGTH_SHORT).show()
return return
} }
@@ -222,7 +245,7 @@ class MineFragment : Fragment() {
nickname.text = u?.nickName ?: "" nickname.text = u?.nickName ?: ""
time.text = u?.vipExpiry?.let { "Due on November $it" } ?: "" time.text = u?.vipExpiry?.let { getString(R.string.mine_vip_due_on, it) } ?: ""
u?.avatarUrl?.let { url -> u?.avatarUrl?.let { url ->
Glide.with(requireContext()) Glide.with(requireContext())
@@ -232,11 +255,11 @@ class MineFragment : Fragment() {
EncryptedSharedPreferencesUtil.save(requireContext(), "Personal_information", u) EncryptedSharedPreferencesUtil.save(requireContext(), "Personal_information", u)
if (showToast) Toast.makeText(requireContext(), "Refreshed", Toast.LENGTH_SHORT).show() if (showToast) Toast.makeText(requireContext(), getString(R.string.refresh_success), Toast.LENGTH_SHORT).show()
} catch (e: Exception) { } catch (e: Exception) {
if (e is kotlinx.coroutines.CancellationException) return@launch if (e is kotlinx.coroutines.CancellationException) return@launch
Log.e(TAG, "getUser failed", e) Log.e(TAG, "getUser failed", e)
if (showToast && isAdded) Toast.makeText(requireContext(), "Refresh failed", Toast.LENGTH_SHORT).show() if (showToast && isAdded) Toast.makeText(requireContext(), getString(R.string.refresh_failed), Toast.LENGTH_SHORT).show()
} }
} }
} }

View File

@@ -17,6 +17,8 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import com.example.myapplication.network.BehaviorReporter import com.example.myapplication.network.BehaviorReporter
import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus
class FeedbackFragment : Fragment() { class FeedbackFragment : Fragment() {
@@ -33,7 +35,8 @@ class FeedbackFragment : Fragment() {
// 关闭按钮 // 关闭按钮
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener { view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
parentFragmentManager.popBackStack() AuthEventBus.emit(AuthEvent.UserUpdated)
requireActivity().onBackPressedDispatcher.onBackPressed()
} }
// 让多行输入框:不聚焦也能上下滑动内容 // 让多行输入框:不聚焦也能上下滑动内容
@@ -60,7 +63,7 @@ class FeedbackFragment : Fragment() {
view.findViewById<View>(R.id.btn_keyboard).setOnClickListener { view.findViewById<View>(R.id.btn_keyboard).setOnClickListener {
val feedbackText = etFeedback.text.toString().trim() val feedbackText = etFeedback.text.toString().trim()
if (feedbackText.isEmpty()) { if (feedbackText.isEmpty()) {
Toast.makeText(context, "Please enter your feedback", Toast.LENGTH_SHORT).show() Toast.makeText(context, getString(R.string.feedback_submit_hint), Toast.LENGTH_SHORT).show()
return@setOnClickListener return@setOnClickListener
} }
BehaviorReporter.report( BehaviorReporter.report(
@@ -72,10 +75,11 @@ class FeedbackFragment : Fragment() {
CoroutineScope(Dispatchers.Main).launch { CoroutineScope(Dispatchers.Main).launch {
val response = submitFeedback(feedbackRequest(content = feedbackText)) val response = submitFeedback(feedbackRequest(content = feedbackText))
if (response?.code == 0) { if (response?.code == 0) {
Toast.makeText(context, "Feedback submitted successfully", Toast.LENGTH_SHORT).show() Toast.makeText(context, getString(R.string.feedback_submit_btn), Toast.LENGTH_SHORT).show()
parentFragmentManager.popBackStack() AuthEventBus.emit(AuthEvent.UserUpdated)
requireActivity().onBackPressedDispatcher.onBackPressed()
} else { } else {
Toast.makeText(context, "Failed to submit feedback", Toast.LENGTH_SHORT).show() Toast.makeText(context, getString(R.string.feedback_submit_failed), Toast.LENGTH_SHORT).show()
} }
} }
} }

View File

@@ -19,7 +19,7 @@ import kotlin.math.abs
class GenderSelectSheet : BottomSheetDialogFragment() { class GenderSelectSheet : BottomSheetDialogFragment() {
private val values = listOf("Male", "Female", "The third gender") private lateinit var values: List<String>
private var selectedIndex = 0 private var selectedIndex = 0
private val itemHeightDp = 48f // 每行高度(和 Adapter 里一致) private val itemHeightDp = 48f // 每行高度(和 Adapter 里一致)
@@ -31,6 +31,7 @@ class GenderSelectSheet : BottomSheetDialogFragment() {
): View { ): View {
val view = inflater.inflate(R.layout.sheet_select_gender, container, false) val view = inflater.inflate(R.layout.sheet_select_gender, container, false)
values = listOf(getString(R.string.gender_male), getString(R.string.gender_female), getString(R.string.gender_third))
selectedIndex = (arguments?.getInt(ARG_INITIAL) ?: 0).coerceIn(0, values.lastIndex) selectedIndex = (arguments?.getInt(ARG_INITIAL) ?: 0).coerceIn(0, values.lastIndex)
val rv = view.findViewById<RecyclerView>(R.id.gender_wheel) val rv = view.findViewById<RecyclerView>(R.id.gender_wheel)

View File

@@ -0,0 +1,113 @@
package com.example.myapplication.ui.mine.myotherpages
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.RadioButton
import android.widget.RadioGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import com.example.myapplication.R
import com.example.myapplication.SplashActivity
import com.example.myapplication.utils.LocaleHelper
import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus
class LanguageFragment : Fragment() {
private var isSwitchingLanguage = false
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = inflater.inflate(R.layout.language_fragment, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
AuthEventBus.emit(AuthEvent.UserUpdated)
requireActivity().onBackPressedDispatcher.onBackPressed()
}
val radioGroup: RadioGroup = view.findViewById(R.id.rg_languages)
val options = LocaleHelper.getSupportedLanguages(requireContext())
val currentCode = normalizeCode(LocaleHelper.getCurrentLanguageCode(), options)
var lastAppliedCode = currentCode
val padding = (16 * resources.displayMetrics.density).toInt()
options.forEachIndexed { index, option ->
val radioButton = RadioButton(requireContext()).apply {
id = View.generateViewId()
text = option.displayName
tag = option.code
textSize = 16f
setTextColor(androidx.core.content.ContextCompat.getColor(requireContext(), R.color.main_text_color))
setPadding(padding, padding, padding, padding)
layoutParams = RadioGroup.LayoutParams(
RadioGroup.LayoutParams.MATCH_PARENT,
RadioGroup.LayoutParams.WRAP_CONTENT
)
}
radioGroup.addView(radioButton)
if (option.code == currentCode || (currentCode.startsWith(option.code) && currentCode != LocaleHelper.CODE_SYSTEM)) {
radioButton.isChecked = true
} else if (option.code == LocaleHelper.CODE_SYSTEM && currentCode == LocaleHelper.CODE_SYSTEM) {
radioButton.isChecked = true
}
if (index < options.lastIndex) {
View(requireContext()).apply {
layoutParams = RadioGroup.LayoutParams(
RadioGroup.LayoutParams.MATCH_PARENT,
1
)
setBackgroundColor(0xFFF0F0F0.toInt())
}.also { radioGroup.addView(it) }
}
}
radioGroup.setOnCheckedChangeListener { group, checkedId ->
if (!isAdded || isSwitchingLanguage) return@setOnCheckedChangeListener
val selected = group.findViewById<RadioButton>(checkedId) ?: return@setOnCheckedChangeListener
val code = selected.tag as? String ?: LocaleHelper.CODE_SYSTEM
if (code == lastAppliedCode) return@setOnCheckedChangeListener
lastAppliedCode = code
isSwitchingLanguage = true
// Allow the selection ripple to finish before switching
group.postDelayed({
if (!isAdded) {
isSwitchingLanguage = false
return@postDelayed
}
LocaleHelper.setLanguage(code)
Toast.makeText(requireContext(), getString(R.string.language_change_applied), Toast.LENGTH_SHORT).show()
val restartIntent = Intent(requireContext(), SplashActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
putExtra("skip_splash_delay", true)
}
runCatching {
startActivity(restartIntent)
activity?.overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
}.onFailure {
isSwitchingLanguage = false
lastAppliedCode = normalizeCode(LocaleHelper.getCurrentLanguageCode(), options)
}
}, 500L)
}
}
private fun normalizeCode(current: String, options: List<LocaleHelper.LanguageOption>): String {
if (current == LocaleHelper.CODE_SYSTEM) return current
val exact = options.firstOrNull { it.code.equals(current, ignoreCase = true) }?.code
if (exact != null) return exact
val byPrefix = options.firstOrNull { current.startsWith(it.code, ignoreCase = true) }?.code
return byPrefix ?: LocaleHelper.CODE_SYSTEM
}
}

View File

@@ -11,6 +11,8 @@ import android.widget.FrameLayout
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus
import java.util.* import java.util.*
class NotificationFragment : Fragment() { class NotificationFragment : Fragment() {
@@ -28,7 +30,8 @@ class NotificationFragment : Fragment() {
// 设置关闭按钮点击事件 // 设置关闭按钮点击事件
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener { view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
parentFragmentManager.popBackStack() AuthEventBus.emit(AuthEvent.UserUpdated)
requireActivity().onBackPressedDispatcher.onBackPressed()
} }
} }
} }

View File

@@ -173,7 +173,7 @@ class PersonalSettings : BottomSheetDialogFragment() {
val uid = user?.uid?.toString() ?: tvUserId.text?.toString().orEmpty() val uid = user?.uid?.toString() ?: tvUserId.text?.toString().orEmpty()
if (uid.isBlank()) return@setOnClickListener if (uid.isBlank()) return@setOnClickListener
copyToClipboard(uid) copyToClipboard(uid)
Toast.makeText(requireContext(), "Copy successfully", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), getString(R.string.personal_settings_copy), Toast.LENGTH_SHORT).show()
} }
// ===================== load & render ===================== // ===================== load & render =====================
@@ -189,7 +189,7 @@ class PersonalSettings : BottomSheetDialogFragment() {
val resp = getUserdata() val resp = getUserdata()
val u = resp?.data // ???????????? ApiResponse ???????????? data?????????????????????????????? val u = resp?.data // ???????????? ApiResponse ???????????? data??????????????????????????????
if (u == null) { if (u == null) {
Toast.makeText(requireContext(), "Load failed", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), getString(R.string.Pop_up_window_my_keyboard_3), Toast.LENGTH_SHORT).show()
return@launch return@launch
} }
user = u user = u
@@ -213,9 +213,9 @@ class PersonalSettings : BottomSheetDialogFragment() {
} }
private fun genderText(gender: Int): String = when (gender) { private fun genderText(gender: Int): String = when (gender) {
1 -> "Female" 1 -> getString(R.string.gender_female)
2 -> "The third gender" 2 -> getString(R.string.gender_third)
0 -> "Male" 0 -> getString(R.string.gender_male)
else -> "" else -> ""
} }
@@ -239,7 +239,7 @@ class PersonalSettings : BottomSheetDialogFragment() {
} else { } else {
Toast.makeText( Toast.makeText(
requireContext(), requireContext(),
"Camera permission is required to take photos", getString(R.string.Pop_up_window_PersonalSettings_2),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
} }
@@ -247,12 +247,12 @@ class PersonalSettings : BottomSheetDialogFragment() {
private fun showImagePickerDialog() { private fun showImagePickerDialog() {
val options = arrayOf( val options = arrayOf(
getString(R.string.choose_from_gallery), getString(R.string.personal_choose_from_gallery),
getString(R.string.take_photo) getString(R.string.personal_take_photo)
) )
androidx.appcompat.app.AlertDialog.Builder(requireContext()) androidx.appcompat.app.AlertDialog.Builder(requireContext())
.setTitle(R.string.change_avatar) .setTitle(R.string.personal_change_avatar)
.setItems(options) { _, which -> .setItems(options) { _, which ->
when (which) { when (which) {
0 -> { 0 -> {
@@ -345,7 +345,7 @@ class PersonalSettings : BottomSheetDialogFragment() {
} }
if (bitmap == null) { if (bitmap == null) {
Toast.makeText(requireContext(), "Failed to decode image", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(),getString(R.string.Pop_up_window_PersonalSettings_3), Toast.LENGTH_SHORT).show()
return return
} }
@@ -367,7 +367,7 @@ class PersonalSettings : BottomSheetDialogFragment() {
} }
if (tempFile.length() > maxSizeBytes) { if (tempFile.length() > maxSizeBytes) {
Toast.makeText(requireContext(), "Image is too large after compression", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), getString(R.string.Pop_up_window_PersonalSettings_4), Toast.LENGTH_SHORT).show()
bitmap.recycle() bitmap.recycle()
tempFile.delete() tempFile.delete()
return return
@@ -385,13 +385,13 @@ class PersonalSettings : BottomSheetDialogFragment() {
if (response?.code == 0) { if (response?.code == 0) {
setupdateUserInfo(updateInfoRequest(avatarUrl = response.data)) setupdateUserInfo(updateInfoRequest(avatarUrl = response.data))
Toast.makeText(requireContext(), R.string.avatar_updated, Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), R.string.personal_avatar_updated, Toast.LENGTH_SHORT).show()
user = user?.copy(avatarUrl = response.data) user = user?.copy(avatarUrl = response.data)
} else { } else {
Toast.makeText(requireContext(), R.string.upload_failed, Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), R.string.personal_upload_failed, Toast.LENGTH_SHORT).show()
} }
} catch (e: Exception) { } catch (e: Exception) {
Toast.makeText(requireContext(), R.string.upload_error, Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), R.string.personal_upload_failed, Toast.LENGTH_SHORT).show()
Log.e("PersonalSettings", "Upload avatar error", e) Log.e("PersonalSettings", "Upload avatar error", e)
} finally { } finally {
loadingOverlay.hide() loadingOverlay.hide()

View File

@@ -7,6 +7,8 @@ import android.view.ViewGroup
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.example.myapplication.R import com.example.myapplication.R
import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus
class GoldCoinRechargeFragment : Fragment() { class GoldCoinRechargeFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
@@ -22,7 +24,8 @@ class GoldCoinRechargeFragment : Fragment() {
// 设置关闭按钮点击事件 // 设置关闭按钮点击事件
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener { view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
parentFragmentManager.popBackStack() AuthEventBus.emit(AuthEvent.UserUpdated)
requireActivity().onBackPressedDispatcher.onBackPressed()
} }
} }
} }

View File

@@ -9,6 +9,8 @@ import android.widget.TextView
import android.widget.ImageView import android.widget.ImageView
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.example.myapplication.R import com.example.myapplication.R
import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus
class RechargeFragment : Fragment() { class RechargeFragment : Fragment() {
override fun onCreateView( override fun onCreateView(
@@ -29,7 +31,8 @@ class RechargeFragment : Fragment() {
// 设置关闭按钮点击事件 // 设置关闭按钮点击事件
view.findViewById<ImageView>(R.id.iv_close).setOnClickListener { view.findViewById<ImageView>(R.id.iv_close).setOnClickListener {
parentFragmentManager.popBackStack() AuthEventBus.emit(AuthEvent.UserUpdated)
requireActivity().onBackPressedDispatcher.onBackPressed()
} }
} }
} }

View File

@@ -30,6 +30,8 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
import com.example.myapplication.network.BehaviorReporter import com.example.myapplication.network.BehaviorReporter
import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus
class ShopFragment : Fragment(R.layout.fragment_shop) { class ShopFragment : Fragment(R.layout.fragment_shop) {
@@ -102,6 +104,19 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
} }
} }
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
NetworkEventBus.events.collect { event ->
if (event is NetworkEvent.NetworkAvailable) {
if (refreshing.compareAndSet(false, true)) {
swipeRefreshLayout.isRefreshing = true
refreshData()
}
}
}
}
}
bindViews(view) bindViews(view)
bindClicks(view) bindClicks(view)
setupSwipe() setupSwipe()
@@ -130,6 +145,9 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
tabTitles = themeResp?.data ?: emptyList() tabTitles = themeResp?.data ?: emptyList()
styleIds = tabTitles.map { it.id } styleIds = tabTitles.map { it.id }
// Fragment 可能在语言切换重建时被销毁/未附着,避免在未附着状态下创建子 Fragment
if (!isAdded) return@launch
setupViewPagerOnce() setupViewPagerOnce()
setupTagsOnce() setupTagsOnce()
@@ -150,6 +168,7 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
updateBalance(getwalletBalance()) updateBalance(getwalletBalance())
val newThemes = getThemeList()?.data ?: emptyList() val newThemes = getThemeList()?.data ?: emptyList()
if (!isAdded) return@launch
if (newThemes != tabTitles) { if (newThemes != tabTitles) {
tabTitles = newThemes tabTitles = newThemes
styleIds = tabTitles.map { it.id } styleIds = tabTitles.map { it.id }
@@ -175,6 +194,7 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
// ========================== ViewPager ========================== // ========================== ViewPager ==========================
private fun setupViewPagerOnce(force: Boolean = false) { private fun setupViewPagerOnce(force: Boolean = false) {
if (!isAdded) return
if (viewPager.adapter != null && !force) return if (viewPager.adapter != null && !force) return
pageCallback?.let { viewPager.unregisterOnPageChangeCallback(it) } pageCallback?.let { viewPager.unregisterOnPageChangeCallback(it) }
@@ -406,7 +426,7 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
} }
view.findViewById<View>(R.id.skinButton).setOnClickListener { view.findViewById<View>(R.id.skinButton).setOnClickListener {
// 使用事件总线打开我的皮肤页面 // 使用事件总线打开我的皮肤页面
findNavController().navigate(R.id.action_shopfragment_to_myskin) AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.MySkin))
BehaviorReporter.report( BehaviorReporter.report(
isNewUser = false, isNewUser = false,
"page_id" to "shop", "page_id" to "shop",
@@ -415,7 +435,7 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
} }
view.findViewById<View>(R.id.searchButton).setOnClickListener { view.findViewById<View>(R.id.searchButton).setOnClickListener {
// 使用事件总线打开搜索页面 // 使用事件总线打开搜索页面
findNavController().navigate(R.id.action_shopfragment_to_searchfragment) AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.searchFragment))
BehaviorReporter.report( BehaviorReporter.report(
isNewUser = false, isNewUser = false,
"page_id" to "shop", "page_id" to "shop",
@@ -425,4 +445,3 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
} }
} }

View File

@@ -20,6 +20,8 @@ import com.example.myapplication.network.themeStyle
import com.example.myapplication.network.deleteThemeRequest import com.example.myapplication.network.deleteThemeRequest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import com.example.myapplication.network.BehaviorReporter import com.example.myapplication.network.BehaviorReporter
import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus
class MySkin : Fragment() { class MySkin : Fragment() {
@@ -57,7 +59,8 @@ class MySkin : Fragment() {
// 返回 // 返回
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener { view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
parentFragmentManager.popBackStack() AuthEventBus.emit(AuthEvent.UserUpdated)
requireActivity().onBackPressedDispatcher.onBackPressed()
} }
val rv = view.findViewById<RecyclerView>(R.id.rvThemes) val rv = view.findViewById<RecyclerView>(R.id.rvThemes)
@@ -66,7 +69,7 @@ class MySkin : Fragment() {
adapter = MySkinAdapter( adapter = MySkinAdapter(
onItemClick = { /* 非编辑模式点击:进详情等 */ }, onItemClick = { /* 非编辑模式点击:进详情等 */ },
onSelectionChanged = { count -> onSelectionChanged = { count ->
tvSelectedCount.text = "$count themes selected" tvSelectedCount.text = "$count"+ getString(R.string.skin_select_all)
btnDelete.isEnabled = count > 0 btnDelete.isEnabled = count > 0
btnDelete.alpha = if (count > 0) 1f else 0.4f btnDelete.alpha = if (count > 0) 1f else 0.4f
} }
@@ -91,7 +94,7 @@ class MySkin : Fragment() {
tvEditor.setOnClickListener { tvEditor.setOnClickListener {
if (!adapter.editMode) { if (!adapter.editMode) {
adapter.enterEditMode() adapter.enterEditMode()
tvEditor.text = "Exit editing" tvEditor.text = getString(R.string.skin_exit_editing)
bottomBar.post { showBottomBar() } // post 确保有 height bottomBar.post { showBottomBar() } // post 确保有 height
BehaviorReporter.report( BehaviorReporter.report(
isNewUser = false, isNewUser = false,
@@ -101,7 +104,7 @@ class MySkin : Fragment() {
) )
} else { } else {
adapter.exitEditMode() adapter.exitEditMode()
tvEditor.text = "Editor" tvEditor.text = getString(R.string.skin_editor)
hideBottomBar() hideBottomBar()
BehaviorReporter.report( BehaviorReporter.report(
isNewUser = false, isNewUser = false,

View File

@@ -11,7 +11,6 @@ import android.widget.*
import androidx.cardview.widget.CardView import androidx.cardview.widget.CardView
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@@ -24,6 +23,8 @@ import com.google.android.flexbox.FlexboxLayout
import com.google.android.flexbox.FlexboxLayout.LayoutParams import com.google.android.flexbox.FlexboxLayout.LayoutParams
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import com.example.myapplication.network.BehaviorReporter import com.example.myapplication.network.BehaviorReporter
import com.example.myapplication.network.AuthEvent
import com.example.myapplication.network.AuthEventBus
@@ -60,13 +61,12 @@ class SearchFragment : Fragment() {
} }
} }
// 返回
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener { view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
parentFragmentManager.popBackStack() AuthEventBus.emit(AuthEvent.UserUpdated)
requireActivity().onBackPressedDispatcher.onBackPressed()
} }
historySection = view.findViewById(R.id.layout_history_section) historySection = view.findViewById(R.id.layout_history_section)
historyLayout = view.findViewById(R.id.layout_history_list) historyLayout = view.findViewById(R.id.layout_history_list)
etInput = view.findViewById(R.id.et_input) etInput = view.findViewById(R.id.et_input)
@@ -92,17 +92,14 @@ class SearchFragment : Fragment() {
isNewUser = false, isNewUser = false,
"page_id" to "search", "page_id" to "search",
"element_id" to "search_submit", "element_id" to "search_submit",
"keyword" to bundle, "keyword" to keyword,
)
// 跳转时带上 bundle
findNavController().navigate(
R.id.action_searchFragment_to_searchResultFragment,
bundle
) )
// open search result via event bus with bundle
AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.searchResultFragment, bundle))
etInput.setText("") etInput.setText("")
} else { } else {
Toast.makeText(requireContext(), "请输入搜索内容", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(),getString(R.string.Pop_up_window_SearchFragment_1), Toast.LENGTH_SHORT).show()
} }
} }

View File

@@ -5,7 +5,6 @@ import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText import android.widget.EditText
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.LinearLayout import android.widget.LinearLayout
@@ -43,7 +42,7 @@ class SearchResultFragment : Fragment() {
// 返回按钮 // 返回按钮
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener { view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
parentFragmentManager.popBackStack() requireActivity().onBackPressedDispatcher.onBackPressed()
} }
etInput = view.findViewById(R.id.et_input) etInput = view.findViewById(R.id.et_input)
@@ -55,28 +54,26 @@ class SearchResultFragment : Fragment() {
// 设置搜索按钮点击事件 // 设置搜索按钮点击事件
tvSearch.setOnClickListener { tvSearch.setOnClickListener {
val keyword = etInput.text.toString() val keyword = etInput.text.toString().trim()
if (keyword.isEmpty()) { if (keyword.isEmpty()) {
Toast.makeText(requireContext(), "请输入搜索词", Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(),getString(R.string.Pop_up_window_SearchFragment_1), Toast.LENGTH_SHORT).show()
return@setOnClickListener return@setOnClickListener
} }
viewLifecycleOwner.lifecycleScope.launch { performSearch(keyword)
try {
val searchResults = getSearchTheme(keyword)?.data
// 渲染搜索结果列表
handleSearchResults(searchResults)
} catch (e: Exception) {
Log.e("SearchResultFragment", "搜索主题失败", e)
}
}
} }
// 接收从上一个页面传来的搜索词 // 接收从上一个页面传来的搜索词
val keyword = arguments?.getString("search_keyword") ?: "" val keyword = arguments?.getString("search_keyword").orEmpty()
etInput.setText(keyword) etInput.setText(keyword)
etInput.setSelection(keyword.length) etInput.setSelection(keyword.length)
if (keyword.isNotEmpty()) {
performSearch(keyword)
}
}
private fun performSearch(keyword: String) {
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
try { try {
val searchResults = getSearchTheme(keyword)?.data val searchResults = getSearchTheme(keyword)?.data

View File

@@ -0,0 +1,33 @@
package com.example.myapplication.utils
import android.content.Context
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.os.LocaleListCompat
object LocaleHelper {
const val CODE_SYSTEM = "system"
data class LanguageOption(val code: String, val displayName: String)
fun getSupportedLanguages(context: Context): List<LanguageOption> {
val codes = context.resources.getStringArray(com.example.myapplication.R.array.language_codes)
val names = context.resources.getStringArray(com.example.myapplication.R.array.language_display_names)
return codes.zip(names).map { (code, name) -> LanguageOption(code, name) }
}
fun getCurrentLanguageCode(): String {
val localeList = AppCompatDelegate.getApplicationLocales()
if (localeList.isEmpty) return CODE_SYSTEM
val locale = localeList[0] ?: return CODE_SYSTEM
return locale.toLanguageTag()
}
fun setLanguage(code: String) {
val localeList = if (code == CODE_SYSTEM) {
LocaleListCompat.getEmptyLocaleList()
} else {
LocaleListCompat.forLanguageTags(code)
}
AppCompatDelegate.setApplicationLocales(localeList)
}
}

View File

@@ -126,7 +126,7 @@ class ThemeDownloadWorker(
private fun notifySuccess(context: Context) { private fun notifySuccess(context: Context) {
mainHandler.post { mainHandler.post {
Toast.makeText(context, "主题应用成功", Toast.LENGTH_SHORT).show() Toast.makeText(context, context.getString(com.example.myapplication.R.string.Pop_up_window_ThemeDownloadWorker_1), Toast.LENGTH_SHORT).show()
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#02BEAC" />
<corners android:radius="10dp" />
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/white" />
<corners android:radius="10dp" />
</shape>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 选中状态 -->
<item android:state_checked="true">
<layer-list>
<!-- 透明背景 -->
<item android:drawable="@android:color/transparent" />
<!-- 图标 -->
<item android:drawable="@drawable/selected_circle" />
</layer-list>
</item>
<!-- 未选中状态 -->
<item>
<layer-list>
<!-- 透明背景 -->
<item android:drawable="@android:color/transparent" />
<!-- 图标 -->
<item android:drawable="@drawable/circle" />
</layer-list>
</item>
</selector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#1B1F1A"
android:pathData="M11.99 2c-5.52 0-10 4.48-10 10s4.48 10 10 10 10-4.48 10-10-4.48-10-10-10zm6.93 6h-2.95c-.19-1.26-.54-2.45-1.03-3.5 1.84.74 3.27 2.27 3.98 4.1zm-6.93-4.9c.86 1.25 1.45 2.7 1.73 4.28h-3.46c.28-1.57.87-3.02 1.73-4.28zm-7.46 9.4c-.2-.63-.33-1.3-.33-2 0-.7.12-1.37.33-2h2.71c-.06.66-.1 1.32-.1 2 0 .68.04 1.34.1 2h-2.71zm.53 2h2.95c.19 1.26.54 2.45 1.03 3.5-1.84-.74-3.27-2.27-3.98-4.1zm2.95-6h-2.95c.71-1.83 2.14-3.36 3.98-4.1-.49 1.05-.84 2.24-1.03 3.5zm4.98 9.9c-.86-1.25-1.45-2.7-1.73-4.28h3.46c-.28 1.57-.87 3.02-1.73 4.28zm2.1-6.28h-4.2c-.07-.66-.11-1.32-.11-2 0-.68.04-1.34.11-2h4.19c.07.66.11 1.32.11 2 0 .68-.04 1.34-.1 2zm.26 2h2.95c-.71 1.83-2.14 3.36-3.98 4.1.49-1.05.84-2.24 1.03-3.5zm0-4h2.95c.2.63.33 1.3.33 2 0 .7-.12 1.37-.33 2h-2.95c.06-.66.1-1.32.1-2 0-.68-.04-1.34-.1-2z" />
</vector>

View File

@@ -88,7 +88,7 @@
android:id="@+id/tv_title" android:id="@+id/tv_title"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Welcome to use the [key of love] keyboard" android:text="@string/guide_chat_1"
android:textColor="#929292" android:textColor="#929292"
android:textSize="10sp" /> android:textSize="10sp" />
@@ -98,7 +98,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:maxWidth="179dp" android:maxWidth="179dp"
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:text="Click &quot;Copy any conversation&quot;, &quot;Paste&quot; and try replying using the keyboard [Persona] method" android:text="@string/guide_chat_2"
android:textColor="#929292" android:textColor="#929292"
android:textSize="10sp" android:textSize="10sp"
android:lineHeight="20dp" /> android:lineHeight="20dp" />
@@ -183,9 +183,9 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="12dp" android:layout_marginStart="12dp"
android:text="Please enter your content" android:text="@string/guide_input"
android:textSize="12sp" android:textSize="12sp"
android:textColor="#CBCBCB"/> android:textColor="#ABABAB"/>
</LinearLayout> </LinearLayout>
</FrameLayout> </FrameLayout>
<ImageView <ImageView

View File

@@ -56,7 +56,7 @@
<TextView <TextView
android:id="@+id/btnEnabledText" android:id="@+id/btnEnabledText"
android:text="Enable it in Settings" android:text="@string/imguide_btn_1"
android:textSize="13sp" android:textSize="13sp"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_weight="1" android:layout_weight="1"
@@ -81,7 +81,7 @@
<TextView <TextView
android:id="@+id/btnSelectText" android:id="@+id/btnSelectText"
android:text="Select an input method" android:text="@string/imguide_btn_2"
android:textSize="13sp" android:textSize="13sp"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_weight="1" android:layout_weight="1"

View File

@@ -5,6 +5,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/window_background"
tools:context=".MainActivity"> tools:context=".MainActivity">
<FrameLayout <FrameLayout
@@ -28,14 +29,22 @@
</FrameLayout> </FrameLayout>
<eightbitlab.com.blurview.BlurView
android:id="@+id/bottom_nav_blur"
android:layout_width="match_parent"
android:layout_height="@dimen/design_bottom_navigation_height"
android:layout_gravity="bottom"
android:visibility="gone"/>
<com.google.android.material.bottomnavigation.BottomNavigationView <com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav" android:id="@+id/bottom_nav"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:background="@android:color/white" android:background="@android:color/transparent"
app:menu="@menu/menu_bottom_nav" app:menu="@menu/menu_bottom_nav"
app:itemIconTint="@null" app:itemIconTint="@null"
app:itemTextColor="@color/nav_text_color"/> app:itemTextColor="@color/nav_text_color"
app:itemBackground="@android:color/transparent"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -32,7 +32,7 @@
android:layout_gravity="center" android:layout_gravity="center"
android:background="@drawable/tv_skip_bg" android:background="@drawable/tv_skip_bg"
android:gravity="center" android:gravity="center"
android:text="Skip" android:text="@string/skip"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="12sp" android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@@ -48,7 +48,7 @@
android:layout_marginTop="30dp" android:layout_marginTop="30dp"
android:elevation="2dp" android:elevation="2dp"
android:gravity="center" android:gravity="center"
android:text="Please select your gender" android:text="@string/gender_hint"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="24sp" android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@@ -94,7 +94,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginEnd="60dp" android:layout_marginEnd="60dp"
android:text="Male" android:text="@string/gender_male"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="20sp" /> android:textSize="20sp" />
</LinearLayout> </LinearLayout>
@@ -131,7 +131,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginStart="60dp" android:layout_marginStart="60dp"
android:text="Female" android:text="@string/gender_female"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="20sp" /> android:textSize="20sp" />
</LinearLayout> </LinearLayout>
@@ -175,7 +175,7 @@
android:id="@+id/tv_male" android:id="@+id/tv_male"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="The third gender" android:text="@string/gender_third"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="20sp" /> android:textSize="20sp" />
</LinearLayout> </LinearLayout>
@@ -190,7 +190,7 @@
android:id="@+id/tv_description" android:id="@+id/tv_description"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="59dp" android:layout_height="59dp"
android:text="Turn on the keyboard" android:text="@string/gender_btn"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:gravity="center" android:gravity="center"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"

View File

@@ -10,7 +10,7 @@
android:id="@+id/tv_title" android:id="@+id/tv_title"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Delete character design?" android:text="@string/keyboard_delete_hint"
android:textStyle="bold" android:textStyle="bold"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="16sp" /> android:textSize="16sp" />
@@ -20,7 +20,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:text="Are you sure you want to delete this character profile?" android:text="@string/keyboard_delete_hint_text"
android:textColor="#6B7280" android:textColor="#6B7280"
android:textSize="13sp" /> android:textSize="13sp" />
@@ -45,7 +45,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_weight="1" android:layout_weight="1"
android:text="Prof." android:text=""
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="14sp" /> android:textSize="14sp" />
</LinearLayout> </LinearLayout>
@@ -62,7 +62,7 @@
android:layout_height="42dp" android:layout_height="42dp"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center" android:gravity="center"
android:text="Cancel" android:text="@string/cancel"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="14sp" android:textSize="14sp"
android:background="@drawable/my_keyboard_cancel" /> android:background="@drawable/my_keyboard_cancel" />
@@ -74,7 +74,7 @@
android:layout_weight="1" android:layout_weight="1"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:gravity="center" android:gravity="center"
android:text="Delete" android:text="@string/delete"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:textSize="14sp" android:textSize="14sp"
android:background="@drawable/my_keyboard_delete" /> android:background="@drawable/my_keyboard_delete" />

View File

@@ -9,7 +9,7 @@
<!-- 标题 --> <!-- 标题 -->
<TextView <TextView
android:text="Confirm logging out?" android:text="@string/Logout_confirm_title"
android:textSize="18sp" android:textSize="18sp"
android:textStyle="bold" android:textStyle="bold"
android:textColor="#222222" android:textColor="#222222"
@@ -19,7 +19,7 @@
<!-- 描述 --> <!-- 描述 -->
<TextView <TextView
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:text="You will need to log in again after logging out" android:text="@string/Logout_confirm_msg"
android:textSize="14sp" android:textSize="14sp"
android:textColor="#666666" android:textColor="#666666"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@@ -35,7 +35,7 @@
<TextView <TextView
android:id="@+id/btn_cancel" android:id="@+id/btn_cancel"
android:text="Cancel" android:text="@string/cancel"
android:textSize="14sp" android:textSize="14sp"
android:textColor="#666666" android:textColor="#666666"
android:padding="12dp" android:padding="12dp"
@@ -44,7 +44,7 @@
<TextView <TextView
android:id="@+id/btn_logout" android:id="@+id/btn_logout"
android:text="Log out" android:text="@string/Logout_confirm_btn"
android:textSize="14sp" android:textSize="14sp"
android:textColor="#F44336" android:textColor="#F44336"
android:padding="12dp" android:padding="12dp"

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp"
android:minWidth="280dp"
android:layout_gravity="center"
android:background="@drawable/bg_dialog_no_network">
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Network is unavailable"
android:textAppearance="?attr/textAppearanceHeadline6"
android:textColor="?attr/colorOnBackground" />
<TextView
android:id="@+id/tvMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Please check the network connection and try again."
android:textAppearance="?attr/textAppearanceBody2"
android:textColor="?attr/colorOnBackground" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnDismiss"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="16dp"
android:text="Understand"
android:textColor="#FFFFFF"
android:background="@drawable/bg_dialog_button"
android:insetLeft="0dp"
android:insetRight="0dp"
android:insetTop="0dp"
android:insetBottom="0dp"
app:cornerRadius="5dp"
app:backgroundTint="#02BEAC" />
</LinearLayout>

View File

@@ -19,7 +19,7 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Purchase Confirmation" android:text="@string/detail_purchase_confirm"
android:textSize="18sp" android:textSize="18sp"
android:textStyle="bold" android:textStyle="bold"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
@@ -31,7 +31,7 @@
android:id="@+id/tv_message" android:id="@+id/tv_message"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Have you confirmed your purchase of this theme" android:text="@string/detail_purchase_confirm_msg"
android:textSize="14sp" android:textSize="14sp"
android:textColor="#666666" android:textColor="#666666"
android:gravity="center" android:gravity="center"
@@ -52,7 +52,7 @@
android:layout_height="48dp" android:layout_height="48dp"
android:layout_weight="1" android:layout_weight="1"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:text="Cancel" android:text="@string/cancel"
android:textSize="14sp" android:textSize="14sp"
android:textColor="#999999" android:textColor="#999999"
android:gravity="center" android:gravity="center"
@@ -66,7 +66,7 @@
android:layout_height="48dp" android:layout_height="48dp"
android:layout_weight="1" android:layout_weight="1"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:text="Confirm" android:text="@string/confirm"
android:textSize="14sp" android:textSize="14sp"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:gravity="center" android:gravity="center"

View File

@@ -45,7 +45,7 @@
android:layout_marginEnd="49dp" android:layout_marginEnd="49dp"
android:gravity="center" android:gravity="center"
android:textStyle="bold" android:textStyle="bold"
android:text="Feedback" android:text="@string/feedback_title"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="16sp" /> android:textSize="16sp" />
</LinearLayout> </LinearLayout>
@@ -64,14 +64,14 @@
app:boxCornerRadiusBottomStart="8dp" app:boxCornerRadiusBottomStart="8dp"
app:boxCornerRadiusBottomEnd="8dp" app:boxCornerRadiusBottomEnd="8dp"
app:hintTextColor="#02BEAC" app:hintTextColor="#02BEAC"
app:placeholderText="Your Feedback"> app:placeholderText="@string/feedback_input_hint_text">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_feedback" android:id="@+id/et_feedback"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="200dp" android:layout_height="200dp"
android:gravity="top|start" android:gravity="top|start"
android:hint="Please enter your feedback..." android:hint="@string/feedback_input_hint"
android:padding="12dp" android:padding="12dp"
android:inputType="textMultiLine" android:inputType="textMultiLine"
android:minLines="4" android:minLines="4"
@@ -94,7 +94,7 @@
android:layout_height="45dp" android:layout_height="45dp"
android:gravity="center" android:gravity="center"
android:layout_marginBottom="20dp" android:layout_marginBottom="20dp"
android:text="Save" android:text="@string/save"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:textSize="16sp" android:textSize="16sp"
android:background="@drawable/my_keyboard_delete" android:background="@drawable/my_keyboard_delete"

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rootCoordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.circle.CircleFragment">
<!-- 背景图片 -->
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/a123123123"
android:scaleType="fitXY"
android:adjustViewBounds="true" />
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="24sp"
android:text="布局"
android:gravity="center"
android:padding="16dp"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -49,7 +49,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="18sp" android:textSize="18sp"
android:textStyle="bold" android:textStyle="bold"
android:text="Reset password" android:text="@string/forgot_password_title"
android:textColor="#1B1F1A"/> android:textColor="#1B1F1A"/>
<EditText <EditText
@@ -59,7 +59,7 @@
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
android:background="@drawable/input_box_bg" android:background="@drawable/input_box_bg"
android:padding="15dp" android:padding="15dp"
android:hint="Enter email address" android:hint="@string/register_input_email_hint"
android:textColorHint="#CBCBCB" android:textColorHint="#CBCBCB"
android:textSize="14sp" android:textSize="14sp"
android:textColor="#CBCBCB" /> android:textColor="#CBCBCB" />
@@ -74,7 +74,7 @@
android:textStyle="bold" android:textStyle="bold"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:textSize="18sp" android:textSize="18sp"
android:text="Next step" /> android:text="@string/next" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>

View File

@@ -49,7 +49,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="18sp" android:textSize="18sp"
android:textStyle="bold" android:textStyle="bold"
android:text="Reset password" android:text="@string/forgot_password_title"
android:textColor="#1B1F1A"/> android:textColor="#1B1F1A"/>
<RelativeLayout <RelativeLayout
@@ -64,7 +64,7 @@
android:textSize="14sp" android:textSize="14sp"
android:padding="15dp" android:padding="15dp"
android:textColor="#000000" android:textColor="#000000"
android:hint="Enter password" android:hint="@string/register_input_password_hint"
android:textColorHint="#CBCBCB" android:textColorHint="#CBCBCB"
android:background="@null" android:background="@null"
android:inputType="textPassword" /> android:inputType="textPassword" />
@@ -90,7 +90,7 @@
android:textSize="14sp" android:textSize="14sp"
android:padding="15dp" android:padding="15dp"
android:textColor="#000000" android:textColor="#000000"
android:hint="Enter repeat password" android:hint="@string/register_input_repeat_password_hint"
android:textColorHint="#CBCBCB" android:textColorHint="#CBCBCB"
android:background="@null" android:background="@null"
android:inputType="textPassword" /> android:inputType="textPassword" />
@@ -114,7 +114,7 @@
android:textStyle="bold" android:textStyle="bold"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:textSize="18sp" android:textSize="18sp"
android:text="Next step" /> android:text="@string/next" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>

View File

@@ -48,7 +48,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="18sp" android:textSize="18sp"
android:textStyle="bold" android:textStyle="bold"
android:text="Reset password" android:text="@string/forgot_password_title"
android:textColor="#1B1F1A"/> android:textColor="#1B1F1A"/>
<TextView <TextView
@@ -56,7 +56,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="13sp" android:textSize="13sp"
android:textStyle="bold" android:textStyle="bold"
android:text="Enter email verification code" android:text="@string/register_verification"
android:textColor="#1B1F1A"/> android:textColor="#1B1F1A"/>
@@ -115,7 +115,7 @@
android:textStyle="bold" android:textStyle="bold"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:textSize="18sp" android:textSize="18sp"
android:text="Next step" /> android:text="@string/next" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>

View File

@@ -48,7 +48,8 @@
android:textStyle="bold" android:textStyle="bold"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:text="Become A Member Of LOVE KEY" /> android:gravity="center"
android:text="@string/home_member" />
<TextView <TextView
android:id="@+id/Unlock" android:id="@+id/Unlock"
@@ -58,7 +59,7 @@
android:textSize="14sp" android:textSize="14sp"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:text="Unlock all functions" /> android:text="@string/home_unlock" />
<!-- 权益 --> <!-- 权益 -->
<LinearLayout <LinearLayout
@@ -90,7 +91,7 @@
android:textSize="12sp" android:textSize="12sp"
android:gravity="center" android:gravity="center"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:text="Wireless sub-AI dialogue" /> android:text="@string/home_ai_dialogue" />
</LinearLayout> </LinearLayout>
<!-- 权益2 --> <!-- 权益2 -->
@@ -114,7 +115,7 @@
android:textSize="12sp" android:textSize="12sp"
android:gravity="center" android:gravity="center"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:text="Personalized keyboard" /> android:text="@string/home_ai_keyboard" />
</LinearLayout> </LinearLayout>
<!-- 权益3 --> <!-- 权益3 -->
@@ -138,7 +139,7 @@
android:textSize="12sp" android:textSize="12sp"
android:gravity="center" android:gravity="center"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:text="Chat persona" /> android:text="@string/home_ai_persona" />
</LinearLayout> </LinearLayout>
<!-- 权益4 --> <!-- 权益4 -->
@@ -162,7 +163,7 @@
android:textSize="12sp" android:textSize="12sp"
android:gravity="center" android:gravity="center"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:text="Emotional counseling" /> android:text="@string/home_ai_counseling" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
@@ -185,7 +186,7 @@
android:textStyle="bold" android:textStyle="bold"
android:gravity="center" android:gravity="center"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:text="Recharge now" /> android:text="@string/home_recharge" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
@@ -260,7 +261,7 @@
android:layout_weight="1" android:layout_weight="1"
android:layout_marginEnd="20dp" android:layout_marginEnd="20dp"
android:gravity="center" android:gravity="center"
android:text="Ranking List" android:text="@string/home_tab1"
android:textSize="14sp" android:textSize="14sp"
android:textStyle="bold" android:textStyle="bold"
android:textColor="#1B1F1A" /> android:textColor="#1B1F1A" />
@@ -272,7 +273,7 @@
android:layout_weight="1" android:layout_weight="1"
android:layout_marginStart="20dp" android:layout_marginStart="20dp"
android:gravity="center" android:gravity="center"
android:text="Persona circle" android:text="@string/home_tab2"
android:textSize="14sp" android:textSize="14sp"
android:textColor="#801B1F1A" /> android:textColor="#801B1F1A" />
</LinearLayout> </LinearLayout>

View File

@@ -57,7 +57,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="30sp" android:textSize="30sp"
android:text="Hello" android:text="@string/login_hello"
android:textStyle="bold" android:textStyle="bold"
android:textColor="#403B5A" /> android:textColor="#403B5A" />
@@ -65,7 +65,7 @@
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="14sp" android:textSize="14sp"
android:text="Welcome to key of love keyboard" android:text="@string/login_hello_hint"
android:textColor="#554F70" /> android:textColor="#554F70" />
</LinearLayout> </LinearLayout>
@@ -94,7 +94,7 @@
android:textSize="18sp" android:textSize="18sp"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:textStyle="bold" android:textStyle="bold"
android:text="Log in to key of love" android:text="@string/login_input_title"
android:textColor="#1B1F1A" /> android:textColor="#1B1F1A" />
<!-- 输入框 --> <!-- 输入框 -->
@@ -105,7 +105,7 @@
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
android:background="@drawable/input_box_bg" android:background="@drawable/input_box_bg"
android:padding="15dp" android:padding="15dp"
android:hint="Please enter your email address" android:hint="@string/login_input_Email_hint"
android:textColorHint="#CBCBCB" android:textColorHint="#CBCBCB"
android:textSize="14sp" android:textSize="14sp"
android:textColor="#000000" /> android:textColor="#000000" />
@@ -122,7 +122,7 @@
android:textSize="14sp" android:textSize="14sp"
android:padding="15dp" android:padding="15dp"
android:textColor="#000000" android:textColor="#000000"
android:hint="Please enter the password" android:hint="@string/login_input_Password_hint"
android:textColorHint="#CBCBCB" android:textColorHint="#CBCBCB"
android:background="@null" android:background="@null"
android:inputType="textPassword" /> android:inputType="textPassword" />
@@ -146,7 +146,7 @@
android:textStyle="bold" android:textStyle="bold"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:textSize="18sp" android:textSize="18sp"
android:text="Login" /> android:text="@string/login_input_btn" />
<com.google.android.flexbox.FlexboxLayout <com.google.android.flexbox.FlexboxLayout
android:id="@+id/agreement_container" android:id="@+id/agreement_container"
@@ -163,14 +163,14 @@
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="By Continuing, You Agree To Our " android:text="@string/terms_and_privacy_1"
android:textSize="10sp" android:textSize="10sp"
android:textColor="#554F70"/> android:textColor="#554F70"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Terms Of Service " android:text="@string/terms_and_privacy_2"
android:textStyle="bold" android:textStyle="bold"
android:textSize="10sp" android:textSize="10sp"
android:textColor="#554F70"/> android:textColor="#554F70"/>
@@ -178,21 +178,21 @@
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="And Confirm" android:text="@string/terms_and_privacy_3"
android:textSize="10sp" android:textSize="10sp"
android:textColor="#554F70"/> android:textColor="#554F70"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="That You Have Read Our " android:text="@string/terms_and_privacy_4"
android:textSize="10sp" android:textSize="10sp"
android:textColor="#554F70"/> android:textColor="#554F70"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Privacy Policy" android:text="@string/terms_and_privacy_5"
android:textStyle="bold" android:textStyle="bold"
android:textSize="10sp" android:textSize="10sp"
android:textColor="#554F70"/> android:textColor="#554F70"/>
@@ -214,7 +214,7 @@
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Don't have an account?" android:text="@string/login_register_btn_hint_text"
android:textSize="12sp" android:textSize="12sp"
android:textColor="#554F70"/> android:textColor="#554F70"/>
@@ -223,7 +223,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:text="Sign up" android:text="@string/login_register_btn"
android:textStyle="bold" android:textStyle="bold"
android:textSize="12sp" android:textSize="12sp"
android:textColor="#02BEAC"/> android:textColor="#02BEAC"/>
@@ -232,7 +232,7 @@
android:id="@+id/tv_forgot_password" android:id="@+id/tv_forgot_password"
android:layout_width="300dp" android:layout_width="300dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Forgot password?" android:text="@string/login_forgot_password_btn"
android:layout_marginTop="6dp" android:layout_marginTop="6dp"
android:gravity="center" android:gravity="center"
android:textStyle="bold" android:textStyle="bold"

View File

@@ -37,7 +37,7 @@
<TextView <TextView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Personal" android:text="@string/mine_title_personal"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textStyle="bold" android:textStyle="bold"
android:layout_weight="1" android:layout_weight="1"
@@ -63,7 +63,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:text="My keyboard" android:text="@string/mine_my_keyboard"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:textSize="10sp" /> android:textSize="10sp" />
</LinearLayout> </LinearLayout>
@@ -105,7 +105,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/nickname" android:id="@+id/nickname"
android:text="Username" android:text="@string/mine_username"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textStyle="bold" android:textStyle="bold"
android:ellipsize="end" android:ellipsize="end"
@@ -118,7 +118,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/time" android:id="@+id/time"
android:text="Time" android:text="@string/mine_time"
android:textColor="#A4A4A4" android:textColor="#A4A4A4"
android:ellipsize="end" android:ellipsize="end"
android:singleLine="true" android:singleLine="true"
@@ -181,7 +181,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:text="Consumption Record" android:text="@string/mine_consumption_record"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textStyle="bold" android:textStyle="bold"
android:layout_weight="1" android:layout_weight="1"
@@ -223,7 +223,49 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:text="Notice" android:text="@string/mine_notice"
android:textColor="#1B1F1A"
android:textStyle="bold"
android:layout_weight="1"
android:textSize="20sp" />
</LinearLayout>
<ImageView
android:layout_width="9dp"
android:layout_height="13dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:src="@drawable/more_icons" />
</LinearLayout>
<!-- 语言 -->
<LinearLayout
android:id="@+id/click_Language"
android:layout_width="match_parent"
android:layout_height="64dp"
android:layout_marginTop="20dp"
android:background="@drawable/settings"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="20dp"
android:layout_height="24dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:src="@drawable/ic_language" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="@string/mine_language"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textStyle="bold" android:textStyle="bold"
android:layout_weight="1" android:layout_weight="1"
@@ -265,7 +307,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:text="Share app" android:text="@string/mine_share_app"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textStyle="bold" android:textStyle="bold"
android:layout_weight="1" android:layout_weight="1"
@@ -312,7 +354,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:text="Feedback" android:text="@string/mine_feedback"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textStyle="bold" android:textStyle="bold"
android:layout_weight="1" android:layout_weight="1"
@@ -351,7 +393,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:text="E-mail" android:text="@string/mine_email"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textStyle="bold" android:textStyle="bold"
android:layout_weight="1" android:layout_weight="1"
@@ -390,7 +432,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:text="Agreement" android:text="@string/mine_agreement"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textStyle="bold" android:textStyle="bold"
android:layout_weight="1" android:layout_weight="1"
@@ -430,7 +472,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:text="Privacy Policy" android:text="@string/mine_privacy_policy"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textStyle="bold" android:textStyle="bold"
android:layout_weight="1" android:layout_weight="1"
@@ -453,7 +495,7 @@
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
android:layout_marginBottom="20dp" android:layout_marginBottom="20dp"
android:gravity="center" android:gravity="center"
android:text="Log Out" android:text="@string/mine_logout"
android:textColor="#FF0000" android:textColor="#FF0000"
android:textSize="16sp" android:textSize="16sp"
android:textStyle="bold" android:textStyle="bold"

View File

@@ -57,7 +57,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="30sp" android:textSize="30sp"
android:text="Hello" android:text="@string/login_hello"
android:textStyle="bold" android:textStyle="bold"
android:textColor="#403B5A" /> android:textColor="#403B5A" />
@@ -65,7 +65,7 @@
android:layout_width="130dp" android:layout_width="130dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="14sp" android:textSize="14sp"
android:text="Welcome to key of love keyboard" android:text="@string/login_hello_hint"
android:textColor="#554F70" /> android:textColor="#554F70" />
</LinearLayout> </LinearLayout>
@@ -94,7 +94,7 @@
android:textSize="18sp" android:textSize="18sp"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:textStyle="bold" android:textStyle="bold"
android:text="Log in to key of love" android:text="@string/register_title"
android:textColor="#1B1F1A" /> android:textColor="#1B1F1A" />
<!-- 输入框 --> <!-- 输入框 -->
@@ -104,7 +104,7 @@
android:layout_height="52dp" android:layout_height="52dp"
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
android:background="@drawable/input_box_bg" android:background="@drawable/input_box_bg"
android:hint="Enter email address" android:hint="@string/register_input_email_hint"
android:textColorHint="#CBCBCB" android:textColorHint="#CBCBCB"
android:padding="15dp" android:padding="15dp"
android:textSize="14sp" android:textSize="14sp"
@@ -122,7 +122,7 @@
android:textSize="14sp" android:textSize="14sp"
android:padding="15dp" android:padding="15dp"
android:textColor="#000000" android:textColor="#000000"
android:hint="Enter password" android:hint="@string/register_input_password_hint"
android:textColorHint="#CBCBCB" android:textColorHint="#CBCBCB"
android:background="@null" android:background="@null"
android:inputType="textPassword" /> android:inputType="textPassword" />
@@ -149,7 +149,7 @@
android:padding="15dp" android:padding="15dp"
android:textColor="#000000" android:textColor="#000000"
android:background="@null" android:background="@null"
android:hint="Enter Repeat password" android:hint="@string/register_input_repeat_password_hint"
android:textColorHint="#CBCBCB" android:textColorHint="#CBCBCB"
android:inputType="textPassword" /> android:inputType="textPassword" />
<ImageView <ImageView
@@ -172,7 +172,7 @@
android:textStyle="bold" android:textStyle="bold"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:textSize="18sp" android:textSize="18sp"
android:text="Next step" /> android:text="@string/next" />
<com.google.android.flexbox.FlexboxLayout <com.google.android.flexbox.FlexboxLayout
android:id="@+id/agreement_container" android:id="@+id/agreement_container"
@@ -189,14 +189,14 @@
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="By Continuing, You Agree To Our " android:text="@string/terms_and_privacy_1"
android:textSize="10sp" android:textSize="10sp"
android:textColor="#554F70"/> android:textColor="#554F70"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Terms Of Service " android:text="@string/terms_and_privacy_2"
android:textStyle="bold" android:textStyle="bold"
android:textSize="10sp" android:textSize="10sp"
android:textColor="#554F70"/> android:textColor="#554F70"/>
@@ -204,21 +204,21 @@
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="And Confirm" android:text="@string/terms_and_privacy_3"
android:textSize="10sp" android:textSize="10sp"
android:textColor="#554F70"/> android:textColor="#554F70"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="That You Have Read Our " android:text="@string/terms_and_privacy_4"
android:textSize="10sp" android:textSize="10sp"
android:textColor="#554F70"/> android:textColor="#554F70"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Privacy Policy" android:text="@string/terms_and_privacy_5"
android:textStyle="bold" android:textStyle="bold"
android:textSize="10sp" android:textSize="10sp"
android:textColor="#554F70"/> android:textColor="#554F70"/>

View File

@@ -48,7 +48,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="18sp" android:textSize="18sp"
android:textStyle="bold" android:textStyle="bold"
android:text="Register" android:text="@string/register_register"
android:textColor="#1B1F1A"/> android:textColor="#1B1F1A"/>
<TextView <TextView
@@ -56,7 +56,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="13sp" android:textSize="13sp"
android:textStyle="bold" android:textStyle="bold"
android:text="Enter email verification code" android:text="@string/register_verification"
android:textColor="#1B1F1A"/> android:textColor="#1B1F1A"/>
<TextView <TextView
@@ -65,7 +65,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="13sp" android:textSize="13sp"
android:textStyle="bold" android:textStyle="bold"
android:text="Please enter the verification code sent to your email" android:text="@string/register_verification_hint"
android:textColor="#02BEAC"/> android:textColor="#02BEAC"/>
<!-- 验证码输入框 --> <!-- 验证码输入框 -->
@@ -113,7 +113,7 @@
android:textStyle="bold" android:textStyle="bold"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:textSize="18sp" android:textSize="18sp"
android:text="Next step" /> android:text="@string/next" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>

View File

@@ -57,14 +57,14 @@
android:layout_gravity="center" android:layout_gravity="center"
android:textSize="13sp" android:textSize="13sp"
android:background="@null" android:background="@null"
android:hint="Themes" /> android:hint="@string/search_hint" />
<TextView <TextView
android:id="@+id/tv_search" android:id="@+id/tv_search"
android:layout_width="76dp" android:layout_width="76dp"
android:layout_height="28dp" android:layout_height="28dp"
android:layout_gravity="center" android:layout_gravity="center"
android:text="Search" android:text="@string/search_search"
android:gravity="center" android:gravity="center"
android:background="@drawable/my_keyboard_delete" android:background="@drawable/my_keyboard_delete"
android:layout_marginEnd="4dp" android:layout_marginEnd="4dp"
@@ -91,7 +91,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:textStyle="bold" android:textStyle="bold"
android:text="Historical search" android:text="@string/search_historical"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="14sp" /> android:textSize="14sp" />
@@ -131,7 +131,7 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Recommended skins" android:text="@string/recommended"
android:textStyle="bold" android:textStyle="bold"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="14sp" /> android:textSize="14sp" />

View File

@@ -57,14 +57,14 @@
android:layout_gravity="center" android:layout_gravity="center"
android:textSize="13sp" android:textSize="13sp"
android:background="@null" android:background="@null"
android:hint="Themes" /> android:hint="@string/search_hint"/>
<TextView <TextView
android:id="@+id/tv_search" android:id="@+id/tv_search"
android:layout_width="76dp" android:layout_width="76dp"
android:layout_height="28dp" android:layout_height="28dp"
android:layout_gravity="center" android:layout_gravity="center"
android:text="Search" android:text="@string/search_search"
android:gravity="center" android:gravity="center"
android:background="@drawable/my_keyboard_delete" android:background="@drawable/my_keyboard_delete"
android:layout_marginEnd="4dp" android:layout_marginEnd="4dp"
@@ -96,7 +96,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:text="No data available for the time being" android:text="@string/search_not_data"
android:textColor="#999999" android:textColor="#999999"
android:textSize="14sp" /> android:textSize="14sp" />
</LinearLayout> </LinearLayout>

View File

@@ -78,7 +78,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="6dp" android:layout_marginTop="6dp"
android:layout_marginStart="6dp" android:layout_marginStart="6dp"
android:text="Points Mall" android:text="@string/shop_mall"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textStyle="bold" android:textStyle="bold"
android:textSize="22sp" /> android:textSize="22sp" />
@@ -142,7 +142,7 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="My points" android:text="@string/shop_points"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="14sp" android:textSize="14sp"
android:padding="20dp" /> android:padding="20dp" />
@@ -187,7 +187,7 @@
android:textStyle="bold" android:textStyle="bold"
android:gravity="center" android:gravity="center"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:text="Recharge" /> android:text="@string/shop_recharge" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@@ -107,7 +107,7 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Recommended skins" android:text="@string/recommended"
android:textStyle="bold" android:textStyle="bold"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="14sp" /> android:textSize="14sp" />
@@ -145,7 +145,7 @@
android:textStyle="bold" android:textStyle="bold"
android:gravity="center" android:gravity="center"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:text="Download" /> android:text="@string/detail_download_btn" />
<ImageView <ImageView
android:layout_width="17dp" android:layout_width="17dp"
@@ -196,7 +196,7 @@
android:textStyle="bold" android:textStyle="bold"
android:gravity="center" android:gravity="center"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:text="Enabled" /> android:text="@string/detail_enabled" />
</LinearLayout> </LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -0,0 +1,77 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rootCoordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F6F7FB"
tools:context=".ui.mine.myotherpages.LanguageFragment">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<FrameLayout
android:id="@+id/iv_close"
android:layout_width="46dp"
android:layout_height="46dp">
<ImageView
android:layout_width="13dp"
android:layout_height="13dp"
android:layout_gravity="center"
android:src="@drawable/more_icons"
android:rotation="180"
android:scaleType="fitCenter" />
</FrameLayout>
<TextView
android:id="@+id/tv_language_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="49dp"
android:gravity="center"
android:textStyle="bold"
android:text="@string/language_title"
android:textColor="#1B1F1A"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/language_options_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="vertical"
android:background="@drawable/settings"
android:paddingTop="4dp"
android:paddingBottom="4dp">
<RadioGroup
android:id="@+id/rg_languages"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="4dp"
android:paddingBottom="4dp" />
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -36,7 +36,7 @@
android:layout_marginEnd="49dp" android:layout_marginEnd="49dp"
android:gravity="center" android:gravity="center"
android:textStyle="bold" android:textStyle="bold"
android:text="Consumption record" android:text="@string/consumption_title"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="16sp" /> android:textSize="16sp" />
</LinearLayout> </LinearLayout>
@@ -58,7 +58,7 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="My points" android:text="@string/shop_points"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="14sp" android:textSize="14sp"
android:padding="20dp" /> android:padding="20dp" />
@@ -103,7 +103,7 @@
android:textStyle="bold" android:textStyle="bold"
android:gravity="center" android:gravity="center"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:text="Recharge" /> android:text="@string/shop_recharge" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
@@ -127,7 +127,7 @@
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Consumption Details" android:text="@string/consumption_details"
android:textStyle="bold" android:textStyle="bold"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="14sp" /> android:textSize="14sp" />

View File

@@ -55,7 +55,7 @@
android:layout_marginEnd="49dp" android:layout_marginEnd="49dp"
android:gravity="center" android:gravity="center"
android:textStyle="bold" android:textStyle="bold"
android:text="My keyboard" android:text="@string/keyboard_title"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="16sp" /> android:textSize="16sp" />
</LinearLayout> </LinearLayout>
@@ -88,7 +88,7 @@
android:layout_marginBottom="16dp" android:layout_marginBottom="16dp"
android:layout_gravity="bottom|center_horizontal" android:layout_gravity="bottom|center_horizontal"
android:gravity="center" android:gravity="center"
android:text="Save" android:text="@string/save"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:textSize="16sp" android:textSize="16sp"
android:background="@drawable/my_keyboard_delete" android:background="@drawable/my_keyboard_delete"

View File

@@ -50,7 +50,7 @@
android:layout_weight="1" android:layout_weight="1"
android:gravity="center" android:gravity="center"
android:textStyle="bold" android:textStyle="bold"
android:text="MySkin" android:text="@string/skin_title"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="16sp" /> android:textSize="16sp" />
@@ -61,7 +61,7 @@
android:layout_marginEnd="4dp" android:layout_marginEnd="4dp"
android:gravity="center" android:gravity="center"
android:textStyle="bold" android:textStyle="bold"
android:text="Editor" android:text="@string/skin_editor"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="13sp" /> android:textSize="13sp" />
</LinearLayout> </LinearLayout>
@@ -94,7 +94,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:text="0 themes selected" android:text="@string/skin_select"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="14sp" android:textSize="14sp"
android:textStyle="bold"/> android:textStyle="bold"/>
@@ -106,7 +106,7 @@
android:gravity="center" android:gravity="center"
android:paddingStart="14dp" android:paddingStart="14dp"
android:paddingEnd="14dp" android:paddingEnd="14dp"
android:text="Delete" android:text="@string/delete"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:textStyle="bold" android:textStyle="bold"
android:background="@drawable/bg_delete_btn"/> android:background="@drawable/bg_delete_btn"/>

View File

@@ -45,7 +45,7 @@
android:layout_marginEnd="49dp" android:layout_marginEnd="49dp"
android:gravity="center" android:gravity="center"
android:textStyle="bold" android:textStyle="bold"
android:text="Notice" android:text="@string/mine_notice"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="16sp" /> android:textSize="16sp" />
</LinearLayout> </LinearLayout>
@@ -70,7 +70,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:text="Notifycation Setting" android:text="@string/notification_settings"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textStyle="bold" android:textStyle="bold"
android:layout_weight="1" android:layout_weight="1"

View File

@@ -50,7 +50,7 @@
android:layout_marginEnd="49dp" android:layout_marginEnd="49dp"
android:gravity="center" android:gravity="center"
android:textStyle="bold" android:textStyle="bold"
android:text="Settings" android:text="@string/personal_settings_title"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textSize="16sp" /> android:textSize="16sp" />
</LinearLayout> </LinearLayout>
@@ -109,7 +109,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:text="Nickname" android:text="@string/personal_settings_nickname"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textStyle="bold" android:textStyle="bold"
android:textSize="16sp" /> android:textSize="16sp" />
@@ -153,7 +153,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:text="Gender" android:text="@string/personal_settings_gender"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textStyle="bold" android:textStyle="bold"
android:textSize="16sp" /> android:textSize="16sp" />
@@ -197,7 +197,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:text="User ID" android:text="UID"
android:textColor="#1B1F1A" android:textColor="#1B1F1A"
android:textStyle="bold" android:textStyle="bold"
android:textSize="16sp" /> android:textSize="16sp" />

View File

@@ -19,7 +19,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_weight="1" android:layout_weight="1"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Change the nickname" android:text="@string/personal_settings_nickname_input"
android:textSize="16sp" android:textSize="16sp"
android:textStyle="bold" android:textStyle="bold"
android:textColor="#1B1F1A"/> android:textColor="#1B1F1A"/>
@@ -55,7 +55,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="45dp" android:layout_height="45dp"
android:gravity="center" android:gravity="center"
android:text="Save" android:text="@string/save"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:background="@drawable/keyboard_ettings"/> android:background="@drawable/keyboard_ettings"/>
</LinearLayout> </LinearLayout>

View File

@@ -17,7 +17,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_weight="1" android:layout_weight="1"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Modify gender" android:text="@string/personal_settings_gender_input"
android:textSize="16sp" android:textSize="16sp"
android:textStyle="bold" android:textStyle="bold"
android:textColor="#1B1F1A"/> android:textColor="#1B1F1A"/>
@@ -70,7 +70,7 @@
android:layout_height="45dp" android:layout_height="45dp"
android:layout_marginTop="43dp" android:layout_marginTop="43dp"
android:gravity="center" android:gravity="center"
android:text="Save" android:text="@string/save"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:background="@drawable/keyboard_ettings"/> android:background="@drawable/keyboard_ettings"/>
</LinearLayout> </LinearLayout>

View File

@@ -9,6 +9,10 @@
android:id="@+id/shop_graph" android:id="@+id/shop_graph"
android:icon="@drawable/ic_shop_selector"/> android:icon="@drawable/ic_shop_selector"/>
<item
android:id="@+id/circle_graph"
android:icon="@drawable/ic_circle_selector" />
<item <item
android:id="@+id/mine_graph" android:id="@+id/mine_graph"
android:icon="@drawable/ic_mine_selector" /> android:icon="@drawable/ic_mine_selector" />

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/circle_graph"
app:startDestination="@id/circleFragment">
<fragment
android:id="@+id/circleFragment"
android:name="com.example.myapplication.ui.circle.CircleFragment"
android:label="Circle"
tools:layout="@layout/fragment_circle" />
</navigation>

View File

@@ -114,6 +114,31 @@
android:label="Notification" android:label="Notification"
tools:layout="@layout/notification_fragment" /> tools:layout="@layout/notification_fragment" />
<fragment
android:id="@+id/languageFragment"
android:name="com.example.myapplication.ui.mine.myotherpages.LanguageFragment"
android:label="Language"
tools:layout="@layout/language_fragment" />
<fragment
android:id="@+id/searchFragment"
android:name="com.example.myapplication.ui.shop.search.SearchFragment"
android:label="Search"
tools:layout="@layout/fragment_search">
</fragment>
<fragment
android:id="@+id/searchResultFragment"
android:name="com.example.myapplication.ui.shop.search.SearchResultFragment"
android:label="Search Result"
tools:layout="@layout/fragment_search_result" />
<fragment
android:id="@+id/MySkin"
android:name="com.example.myapplication.ui.shop.myskin.MySkin"
android:label="My Skin"
tools:layout="@layout/my_skin" />
<!-- 消费记录跳转 --> <!-- 消费记录跳转 -->
<action <action
android:id="@+id/action_global_consumptionRecordFragment" android:id="@+id/action_global_consumptionRecordFragment"

View File

@@ -42,6 +42,14 @@
app:exitAnim="@anim/fade_out" app:exitAnim="@anim/fade_out"
app:popEnterAnim="@anim/fade_in_fast" app:popEnterAnim="@anim/fade_in_fast"
app:popExitAnim="@anim/fade_out_fast" /> app:popExitAnim="@anim/fade_out_fast" />
<action
android:id="@+id/action_mineFragment_to_languageFragment"
app:destination="@id/languageFragment"
app:enterAnim="@anim/fade_in"
app:exitAnim="@anim/fade_out"
app:popEnterAnim="@anim/fade_in_fast"
app:popExitAnim="@anim/fade_out_fast" />
</fragment> </fragment>
<!-- 个人设置页面 --> <!-- 个人设置页面 -->
@@ -69,4 +77,10 @@
android:label="Notification" android:label="Notification"
tools:layout="@layout/notification_fragment" /> tools:layout="@layout/notification_fragment" />
<fragment
android:id="@+id/languageFragment"
android:name="com.example.myapplication.ui.mine.myotherpages.LanguageFragment"
android:label="Language"
tools:layout="@layout/language_fragment" />
</navigation> </navigation>

View File

@@ -8,6 +8,7 @@
<!-- 三个 Tab独立 back stack --> <!-- 三个 Tab独立 back stack -->
<include app:graph="@navigation/home_graph" /> <include app:graph="@navigation/home_graph" />
<include app:graph="@navigation/shop_graph" /> <include app:graph="@navigation/shop_graph" />
<include app:graph="@navigation/circle_graph" />
<include app:graph="@navigation/mine_graph" /> <include app:graph="@navigation/mine_graph" />
</navigation> </navigation>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="mine_title_personal">Personal</string>
<string name="mine_my_keyboard">My keyboard</string>
<string name="mine_username">Username</string>
<string name="mine_time">Time</string>
<string name="mine_consumption_record">Consumption Record</string>
<string name="mine_notice">Notice</string>
<string name="mine_share_app">Share app</string>
<string name="mine_feedback">Feedback</string>
<string name="mine_email">E-mail</string>
<string name="mine_agreement">Agreement</string>
<string name="mine_privacy_policy">Privacy Policy</string>
<string name="mine_logout">Log Out</string>
<string name="mine_language">Language</string>
<string name="mine_vip_due_on">Maturity Date: %1$s</string>
<string name="copy_invite_link_success">The sharing link has been copied to the clipboard.</string>
<string name="not_logged_in_toast">Not logged in</string>
<string name="refresh_success">Refreshed</string>
<string name="refresh_failed">Refresh failed</string>
<string name="language_title">Language</string>
<string name="language_system_default">Follow system</string>
<string name="language_english">English</string>
<string name="language_chinese_simplified">Simplified Chinese</string>
<string name="language_change_applied">Language updated</string>
<string name="language_switching_loading">Switching language...</string>
<string name="notification_settings">Notification Settings</string>
<!-- Home -->
<string name="home_member">Become A Member Of LOVE KEY</string>
<string name="home_unlock">Unlock all functions</string>
</resources>

View File

@@ -2,4 +2,5 @@
<resources> <resources>
<color name="keyboard_button_bg">#707070</color> <color name="keyboard_button_bg">#707070</color>
<color name="ai_keyboard_button_text_color">#FFFFFF</color> <color name="ai_keyboard_button_text_color">#FFFFFF</color>
<color name="window_background">#F6F7FB</color>
</resources> </resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Android 12+ splash uses this background during Activity recreate (e.g., language switch) -->
<style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="android:windowSplashScreenBackground">@color/window_background</item>
<item name="android:windowBackground">@color/window_background</item>
<item name="android:forceDarkAllowed">false</item>
</style>
</resources>

View File

@@ -0,0 +1,12 @@
<resources>
<string-array name="language_codes">
<item>system</item>
<item>en</item>
<item>zh</item>
</string-array>
<string-array name="language_display_names">
<item>@string/language_system_default</item>
<item>@string/language_english</item>
<item>@string/language_chinese_simplified</item>
</string-array>
</resources>

View File

@@ -0,0 +1,4 @@
<resources>
<string name="app_name">Key of Love</string>
<!-- moved to strings_i18n.xml -->
</resources>

View File

@@ -0,0 +1,183 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 性别选择页 -->
<string name="gender_btn">打开键盘</string>
<string name="gender_hint">请选择您的性别</string>
<!-- 登录 -->
<string name="login_hello">Hello</string>
<string name="login_hello_hint">欢迎来到 “KEY OF LOVE”</string>
<string name="login_input_title">登录 “KEY OF LOVE”</string>
<string name="login_input_Email_hint">请输入您的电子邮件地址</string>
<string name="login_input_Password_hint">请输入您的密码</string>
<string name="login_input_btn">登录</string>
<string name="login_register_btn_hint_text">还没有账号吗?</string>
<string name="login_register_btn">注册</string>
<string name="login_forgot_password_btn">忘记密码?</string>
<!-- 注册 -->
<string name="register_title">注册 “KEY OF LOVE”</string>
<string name="register_input_email_hint">请输入您的电子邮件地址</string>
<string name="register_input_password_hint">请输入您的密码</string>
<string name="register_input_repeat_password_hint">请再次输入您的密码</string>
<string name="register_email_verification_message_1">一封验证邮件已发送至</string>
<string name="register_email_verification_message_2">。请查看您的收件箱以完成验证。</string>
<string name="register_register">注册</string>
<string name="register_verification">输入电子邮件验证码</string>
<string name="register_verification_hint">请输入发送至您电子邮箱的验证码。</string>
<!-- 忘记密码 -->
<string name="forgot_password_title">重置密码</string>
<!-- 我的 -->
<string name="mine_title_personal">我的</string>
<string name="mine_my_keyboard">我的键盘</string>
<string name="mine_username">用户名</string>
<string name="mine_time">时间</string>
<string name="mine_consumption_record">消费记录</string>
<string name="mine_notice">通知</string>
<string name="mine_share_app">分享应用</string>
<string name="mine_feedback">反馈</string>
<string name="mine_email">电子邮件</string>
<string name="mine_agreement">协议</string>
<string name="mine_privacy_policy">隐私政策</string>
<string name="mine_logout">退出登录</string>
<string name="mine_language">语言</string>
<string name="mine_vip_due_on">到期时间:%1$s</string>
<string name="copy_invite_link_success">分享链接已复制到剪贴板。</string>
<string name="not_logged_in_toast">未登录</string>
<string name="refresh_success">已刷新</string>
<string name="refresh_failed">刷新失败</string>
<string name="language_title">语言</string>
<string name="language_system_default">跟随系统</string>
<string name="language_english">英语</string>
<string name="language_chinese_simplified">简体中文</string>
<string name="language_change_applied">语言已更新</string>
<string name="language_switching_loading">正在切换语言...</string>
<string name="notification_settings">通知设置</string>
<string name="Logout_confirm_title">确认退出登录</string>
<string name="Logout_confirm_msg">您确认退出登录吗?</string>
<string name="Logout_confirm_btn">退出登录</string>
<!-- 个人设置页面 -->
<string name="personal_settings_title">个人设置</string>
<string name="personal_settings_nickname">昵称</string>
<string name="personal_settings_gender">性别</string>
<string name="personal_settings_nickname_input">更改昵称</string>
<string name="personal_settings_gender_input">更改性别</string>
<string name="personal_settings_copy">复制成功</string>
<string name="personal_change_avatar">更换头像</string>
<string name="personal_avatar_updated">头像已更新</string>
<string name="personal_choose_from_gallery">从相册选择</string>
<string name="personal_take_photo">拍照</string>
<string name="personal_upload_failed">上传失败</string>
<!-- 键盘人设 -->
<string name="keyboard_title">我的人设</string>
<string name="keyboard_delete_hint">删除人设</string>
<string name="keyboard_delete_hint_text">您确定要删除这个人设吗?</string>
<string name="keyboard_delete_delete_success">删除成功</string>
<string name="keyboard_delete_delete_failed">删除失败</string>
<!-- 消费记录 -->
<string name="consumption_title">消费记录</string>
<string name="consumption_details">消费详情</string>
<!-- 反馈 -->
<string name="feedback_title">反馈</string>
<string name="feedback_input_hint">请输入您的反馈内容......</string>
<string name="feedback_input_hint_text">您的反馈</string>
<string name="feedback_submit_btn">反馈提交成功</string>
<string name="feedback_submit_failed">反馈提交失败</string>
<string name="feedback_submit_hint">请输入您的反馈意见。</string>
<!-- 首页 -->
<string name="home_member">成为 LOVE OF KEY 会员</string>
<string name="home_unlock">解锁专属福利</string>
<string name="home_ai_dialogue">在线AI对话</string>
<string name="home_ai_keyboard">个性化键盘</string>
<string name="home_ai_persona">个性化形象</string>
<string name="home_ai_counseling">恋爱辅导</string>
<string name="home_recharge">成为会员</string>
<string name="home_tab1">排行榜</string>
<string name="home_tab2">人物圈</string>
<string name="added">已添加</string>
<string name="add">添加</string>
<!-- 商城 -->
<string name="shop_mall">积分商城</string>
<string name="shop_points">我的积分</string>
<string name="shop_recharge">充值</string>
<!-- 我的皮肤 -->
<string name="skin_title">我的皮肤</string>
<string name="skin_select">0 个被选中</string>
<string name="skin_editor">编辑</string>
<string name="skin_exit_editing">退出编辑</string>
<string name="skin_select_all">个被选中</string>
<!-- 搜索 -->
<string name="search_hint">请输入你要搜索的内容</string>
<string name="search_search">搜索</string>
<string name="search_not_data">目前暂无相关数据。</string>
<string name="search_historical">历史搜索</string>
<!-- 详情 -->
<string name="detail_enabled">启用</string>
<string name="detail_download">下载次数:</string>
<string name="detail_download_btn">下载</string>
<string name="detail_purchase_confirm">确认购买</string>
<string name="detail_purchase_confirm_msg">您是否确认购买这个皮肤?</string>
<!-- 商城其他 -->
<string name="recommended">推荐皮肤</string>
<!-- 输入法权限和体验页 -->
<string name="guide_chat_1">欢迎使用【key of love】键盘</string>
<string name="guide_chat_2">点击“复制”任意对话内容,然后“粘贴”并尝试使用键盘[人物角色]方式回复。</string>
<string name="guide_input">请输入您的内容</string>
<string name="imguide_text1_step1">第一步</string>
<string name="imguide_text2_step1">勾选“love of key”键盘</string>
<string name="imguide_text1_step2">第二步</string>
<string name="imguide_text2_step2">切换到“love of key”键盘</string>
<string name="imguide_text1_step3">已完成</string>
<string name="imguide_text2_step3">您已完成了相关设置。</string>
<string name="imguide_text2_step3_hint">输入方法已全部设置完毕!</string>
<string name="imguide_btn_1">去勾选</string>
<string name="imguide_btn_2">去切换</string>
<!-- 其他 -->
<string name="loading">正在加载...</string>
<string name="cancel">取消</string>
<string name="confirm">确定</string>
<string name="save">保存</string>
<string name="gender_male">男性</string>
<string name="gender_female">女性</string>
<string name="gender_third">第三性别</string>
<string name="skip">跳过</string>
<string name="delete">删除</string>
<string name="next">下一步</string>
<!-- 服务条款与隐私政策(小字提醒区) -->
<string name="terms_and_privacy_1">继续操作即表示您已经阅读并同意我们的</string>
<string name="terms_and_privacy_2"> “ 服务条款 ” </string>
<string name="terms_and_privacy_3">并确认</string>
<string name="terms_and_privacy_4">您已阅读我们的 </string>
<string name="terms_and_privacy_5"> “ 隐私政策 ” </string>
<!-- 部分弹窗显示 -->
<string name="Pop_up_window_ai_1">您需要先登录才能使用此功能。</string><!-- AiKeyboard -->
<string name="Pop_up_window_my_keyboard_1">排序修改成功</string><!-- MyKeyboard -->
<string name="Pop_up_window_my_keyboard_2">保存失败</string><!-- MyKeyboard -->
<string name="Pop_up_window_my_keyboard_3">加载失败</string><!-- MyKeyboard --><!-- PersonalSettings -->
<string name="Pop_up_window_MForgetPasswordEmailFragmentyKeyboard_1">请输入您的电子邮件地址</string><!-- MForgetPasswordEmailFragmentyKeyboard -->
<string name="Pop_up_window_MForgetPasswordEmailFragmentyKeyboard_2">电子邮件地址格式不正确</string><!-- MForgetPasswordEmailFragmentyKeyboard --><!-- ForgetPasswordResetFragment --><!-- RegisterFragment -->
<string name="Pop_up_window_ForgetPasswordResetFragment_1">两个密码输入不一致</string><!-- ForgetPasswordResetFragment --><!-- RegisterFragment -->
<string name="Pop_up_window_ForgetPasswordResetFragment_2">密码重置成功。请再次登录。</string><!-- ForgetPasswordResetFragment -->
<string name="Pop_up_window_ForgetPasswordVerifyFragment_1">验证码格式有误</string><!-- ForgetPasswordVerifyFragment --><!-- RegisterVerifyFragment -->
<string name="Pop_up_window_ForgetPasswordVerifyFragment_2">验证码已成功验证。</string><!-- ForgetPasswordVerifyFragment -->
<string name="Pop_up_window_LoginFragment_1">密码和电子邮件地址不能为空!</string><!-- LoginFragment -->
<string name="Pop_up_window_LoginFragment_2">登录失败:</string><!-- LoginFragment -->
<string name="Pop_up_window_RegisterFragment_1">请填写完整的信息。</string><!-- RegisterFragment -->
<string name="Pop_up_window_RegisterVerifyFragment_2">注册成功,请登录。</string><!-- RegisterVerifyFragment -->
<string name="Pop_up_window_PersonalSettings_2">需要开启相机权限才能进行拍照操作。</string><!-- PersonalSettings -->
<string name="Pop_up_window_PersonalSettings_3">图片上传失败,请稍后再试。</string><!-- PersonalSettings -->
<string name="Pop_up_window_PersonalSettings_4">选择图片不要超过5M</string><!-- PersonalSettings -->
<string name="Pop_up_window_SearchFragment_1">请输入搜索关键词。</string><!-- SearchFragment --><!-- SearchResultFragment -->
<string name="Pop_up_window_ThemeDownloadWorker_1">皮肤应用成功</string><!-- ThemeDownloadWorker -->
</resources>

View File

@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="purple_200">#FFBB86FC</color> <color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color> <color name="purple_500">#FF6200EE</color>
@@ -13,4 +12,13 @@
<color name="gray_9F">#FF9F9F9F</color> <color name="gray_9F">#FF9F9F9F</color>
<color name="keyboard_button_bg">#FFFFFFFF</color> <color name="keyboard_button_bg">#FFFFFFFF</color>
<color name="ai_keyboard_button_text_color">#1B1F1A</color> <color name="ai_keyboard_button_text_color">#1B1F1A</color>
<!-- 新增透明效果颜色 -->
<!-- Frosted overlay; now fully transparent -->
<color name="frosted_glass_bg">#00FFFFFF</color>
<color name="black_30_percent">#4D000000</color>
<color name="language_loading_scrim">#F2F6F7FB</color>
<!-- Base window background to avoid black flash on Activity recreate -->
<color name="window_background">#F6F7FB</color>
</resources> </resources>

View File

@@ -0,0 +1,13 @@
<resources>
<!-- Language code and display name mapping for the language selector -->
<string-array name="language_codes">
<item>system</item>
<item>en</item>
<item>zh</item>
</string-array>
<string-array name="language_display_names">
<item>@string/language_system_default</item>
<item>@string/language_english</item>
<item>@string/language_chinese_simplified</item>
</string-array>
</resources>

View File

@@ -17,11 +17,4 @@
<string name="key_comma">,</string> <string name="key_comma">,</string>
<string name="key_period">.</string> <string name="key_period">.</string>
<string name="key_enter">Enter</string> <string name="key_enter">Enter</string>
<string name="choose_from_gallery">从相册选择</string>
<string name="take_photo">拍照</string>
<string name="change_avatar">更换头像</string>
<string name="cancel">取消</string>
<string name="avatar_updated">头像更新成功</string>
<string name="upload_failed">上传失败</string>
<string name="upload_error">上传出错</string>
</resources> </resources>

View File

@@ -0,0 +1,188 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 性别选择页 -->
<string name="gender_btn">Turn on the keyboard</string>
<string name="gender_hint">Please select your gender</string><!-- OnboardingActivity-->
<!-- 登录 -->
<string name="login_hello">Hello</string>
<string name="login_hello_hint">Welcome to key of love keyboard</string>
<string name="login_input_title">Log in to key of love</string>
<string name="login_input_Email_hint">Please enter your email address</string>
<string name="login_input_Password_hint">Please enter the password</string>
<string name="login_input_btn">Login</string>
<string name="login_register_btn_hint_text">Don\'t have an account?</string>
<string name="login_register_btn">Sign up</string>
<string name="login_forgot_password_btn">Forgot password?</string>
<!-- 注册 -->
<string name="register_title">Registration “KEY OF LOVE”</string>
<string name="register_input_email_hint">Enter email address</string>
<string name="register_input_password_hint">Enter password</string>
<string name="register_input_repeat_password_hint">Enter Repeat password</string>
<string name="register_email_verification_message_1">A verification email has been sent to</string>
<string name="register_email_verification_message_2">. Please check your inbox to complete the verification.</string>
<string name="register_register">Register</string>
<string name="register_verification">Enter email verification code</string>
<string name="register_verification_hint">Please enter the verification code sent to your email</string>
<!-- 忘记密码 -->
<string name="forgot_password_title">Reset password</string>
<!-- 我的 -->
<string name="mine_title_personal">Personal</string>
<string name="mine_my_keyboard">My keyboard</string>
<string name="mine_username">Username</string>
<string name="mine_time">Time</string>
<string name="mine_consumption_record">Consumption Record</string>
<string name="mine_notice">Notice</string>
<string name="mine_share_app">Share app</string>
<string name="mine_feedback">Feedback</string>
<string name="mine_email">E-mail</string>
<string name="mine_agreement">Agreement</string>
<string name="mine_privacy_policy">Privacy Policy</string>
<string name="mine_logout">Log Out</string>
<string name="mine_language">Language</string>
<string name="mine_vip_due_on">Maturity Date: %1$s</string>
<string name="copy_invite_link_success">The sharing link has been copied to the clipboard.</string>
<string name="not_logged_in_toast">Not logged in</string>
<string name="refresh_success">Refreshed</string>
<string name="refresh_failed">Refresh failed</string>
<string name="language_title">Language</string>
<string name="language_system_default">Follow system</string>
<string name="language_english">English</string>
<string name="language_chinese_simplified">Simplified Chinese</string>
<string name="language_change_applied">Language updated</string>
<string name="language_switching_loading">Switching language...</string>
<string name="notification_settings">Notification Settings</string>
<string name="Logout_confirm_title">Confirm logging out</string>
<string name="Logout_confirm_msg">Are you sure you want to log out?</string>
<string name="Logout_confirm_btn">Log out</string>
<!-- 个人设置页面 -->
<string name="personal_settings_title">Settings</string>
<string name="personal_settings_nickname">Nickname</string>
<string name="personal_settings_gender">Gender</string>
<string name="personal_settings_nickname_input">Change the nickname</string>
<string name="personal_settings_gender_input">Modify gender</string>
<string name="personal_settings_copy">Copy successfully</string><!-- GuideActivity -->
<string name="personal_change_avatar">Change profile picture</string>
<string name="personal_avatar_updated">Profile picture updated successfully</string>
<string name="personal_choose_from_gallery">Select from the photo album</string>
<string name="personal_take_photo">Take a photo</string>
<string name="personal_upload_failed">Upload failed</string>
<!-- 键盘人设 -->
<string name="keyboard_title">My keyboard</string>
<string name="keyboard_delete_hint">Delete character design</string>
<string name="keyboard_delete_hint_text">Are you sure you want to delete this character profile?</string>
<string name="keyboard_delete_delete_success">Deleted successfully</string>
<string name="keyboard_delete_delete_failed">Delete failed</string>
<!-- 消费记录 -->
<string name="consumption_title">Consumption record</string>
<string name="consumption_details">Consumption Details</string>
<!-- 反馈 -->
<string name="feedback_title">Feedback</string>
<string name="feedback_input_hint">Please enter your feedback...</string>
<string name="feedback_input_hint_text">Your Feedback</string>
<string name="feedback_submit_btn">Feedback submitted successfully</string>
<string name="feedback_submit_failed">Feedback submission failed</string>
<string name="feedback_submit_hint">Please enter your feedback</string>
<!-- 首页 -->
<string name="home_member">Become A Member Of LOVE KEY</string>
<string name="home_unlock">Unlock all functions</string>
<string name="home_ai_dialogue">Wireless sub-AI dialogue</string>
<string name="home_ai_keyboard">Personalized keyboard</string>
<string name="home_ai_persona">Chat persona</string>
<string name="home_ai_counseling">Emotional counseling</string>
<string name="home_recharge">Recharge now</string>
<string name="home_tab1">Ranking List</string>
<string name="home_tab2">Persona circle</string>
<string name="added">Added</string>
<string name="add">Add</string>
<!-- 商城 -->
<string name="shop_mall">Points Mall</string>
<string name="shop_points">My points</string>
<string name="shop_recharge">Recharge</string>
<!-- 我的皮肤 -->
<string name="skin_title">My Skin</string>
<string name="skin_select">0 items selected</string>
<string name="skin_editor">Editor</string>
<string name="skin_exit_editing">Exit editing</string>
<string name="skin_select_all">items selected</string>
<!-- 搜索 -->
<string name="search_hint">Please enter the content you want to search for.</string>
<string name="search_search">Search</string>
<string name="search_not_data">No data available for the time being</string>
<string name="search_historical">Historical search</string>
<!-- 详情 -->
<string name="detail_enabled">Enabled</string>
<string name="detail_download">Download:</string>
<string name="detail_download_btn">Download</string>
<string name="detail_purchase_confirm">Purchase Confirmation</string>
<string name="detail_purchase_confirm_msg">Are you sure you want to purchase this skin?</string>
<!-- 商城其他 -->
<string name="recommended">Recommended skins</string>
<!-- 输入法权限和体验页 -->
<string name="guide_chat_1">Welcome to use the [key of love] keyboard!</string>
<string name="guide_chat_2">Click &quot;Copy any conversation&quot;, &quot;Paste&quot; and try replying using the keyboard [Persona] method</string>
<string name="guide_input">Please enter your content</string>
<string name="imguide_text1_step1">Step one</string>
<string name="imguide_text2_step1">Check to enable key of love</string>
<string name="imguide_text1_step2">Step two</string>
<string name="imguide_text2_step2">Select key of love as your default input method</string>
<string name="imguide_text1_step3">Completed</string>
<string name="imguide_text2_step3">You have completed the relevant Settings</string>
<string name="imguide_text2_step3_hint">The input method is all set!</string>
<string name="imguide_btn_1">Enable it in Settings</string>
<string name="imguide_btn_2">Select an input method</string>
<!-- 其他 -->
<string name="loading">Loading...</string>
<string name="cancel">Cancel</string>
<string name="confirm">Confirm</string>
<string name="save">Save</string>
<string name="gender_male">Male</string>
<string name="gender_female">Female</string>
<string name="gender_third">The third gender</string>
<string name="skip">Skip</string>
<string name="delete">Delete</string>
<string name="next">Next step</string>
<!-- 服务条款与隐私政策(小字提醒区) -->
<string name="terms_and_privacy_1">By Continuing, You Agree To Our </string>
<string name="terms_and_privacy_2">Terms Of Service </string>
<string name="terms_and_privacy_3">And Confirm</string>
<string name="terms_and_privacy_4">That You Have Read Our </string>
<string name="terms_and_privacy_5">Privacy Policy </string>
<!-- 部分弹窗显示 -->
<string name="Pop_up_window_ai_1">You need to log in to use this function.</string><!-- AiKeyboard -->
<string name="Pop_up_window_my_keyboard_1">Sorting has been successfully modified.</string><!-- MyKeyboard -->
<string name="Pop_up_window_my_keyboard_2">Save failed</string><!-- MyKeyboard -->
<string name="Pop_up_window_my_keyboard_3">Load failed</string><!-- MyKeyboard --><!-- PersonalSettings -->
<string name="Pop_up_window_MForgetPasswordEmailFragmentyKeyboard_1">Please enter your email address</string><!-- MForgetPasswordEmailFragmentyKeyboard -->
<string name="Pop_up_window_MForgetPasswordEmailFragmentyKeyboard_2">The email address format is incorrect</string><!-- MForgetPasswordEmailFragmentyKeyboard --><!-- ForgetPasswordResetFragment --><!-- RegisterFragment -->
<string name="Pop_up_window_ForgetPasswordResetFragment_1">The two password entries are inconsistent</string><!-- ForgetPasswordResetFragment --><!-- RegisterFragment -->
<string name="Pop_up_window_ForgetPasswordResetFragment_2">Password reset successful. Please log in again.</string><!-- ForgetPasswordResetFragment -->
<string name="Pop_up_window_ForgetPasswordVerifyFragment_1">The verification code format is incorrect</string><!-- ForgetPasswordVerifyFragment --><!-- RegisterVerifyFragment -->
<string name="Pop_up_window_ForgetPasswordVerifyFragment_2">The verification code has been verified successfully</string><!-- ForgetPasswordVerifyFragment -->
<string name="Pop_up_window_LoginFragment_1">The password and email address cannot be left empty!</string><!-- LoginFragment -->
<string name="Pop_up_window_LoginFragment_2">Login failed:</string><!-- LoginFragment -->
<string name="Pop_up_window_RegisterFragment_1">Please fill in the complete information</string><!-- RegisterFragment -->
<string name="Pop_up_window_RegisterVerifyFragment_2">Registration successful</string><!-- RegisterVerifyFragment -->
<string name="Pop_up_window_PersonalSettings_2">Camera permission is required to take photos</string><!-- PersonalSettings -->
<string name="Pop_up_window_PersonalSettings_3">Failed to decode image</string><!-- PersonalSettings -->
<string name="Pop_up_window_PersonalSettings_4">The size of the uploaded image should not exceed 5MB.</string><!-- PersonalSettings -->
<string name="Pop_up_window_SearchFragment_1">Please enter the search term.</string><!-- SearchFragment --><!-- SearchResultFragment -->
<string name="Pop_up_window_ThemeDownloadWorker_1">Skin application was successful.</string><!-- ThemeDownloadWorker -->
</resources>

View File

@@ -29,5 +29,21 @@
<item name="android:windowBackground">#00000000</item> <item name="android:windowBackground">#00000000</item>
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
</style> </style>
<!-- 透明磨砂样式Android 12+ -->
<style name="BottomNavFrostedGlass" parent="Widget.MaterialComponents.BottomNavigationView">
<item name="backgroundTint">@color/frosted_glass_bg</item>
<item name="android:elevation">8dp</item>
<item name="android:outlineAmbientShadowColor">#1A000000</item>
<item name="android:outlineSpotShadowColor">#1A000000</item>
</style>
<!-- 黑色30%透明样式Android 12以下 -->
<style name="BottomNavBlackTransparent" parent="Widget.MaterialComponents.BottomNavigationView">
<item name="backgroundTint">@color/black_30_percent</item>
<item name="android:elevation">8dp</item>
<item name="android:outlineAmbientShadowColor">#1A000000</item>
<item name="android:outlineSpotShadowColor">#1A000000</item>
</style>
</resources> </resources>

View File

@@ -9,6 +9,9 @@
<item name="colorPrimaryVariant">@color/xxx</item> <item name="colorPrimaryVariant">@color/xxx</item>
<item name="colorOnPrimary">@color/xxx</item> <item name="colorOnPrimary">@color/xxx</item>
--> -->
<!-- Avoid black flash when recreating after language switch -->
<item name="android:windowBackground">@color/window_background</item>
<item name="android:forceDarkAllowed">false</item>
</style> </style>
<style name="Theme.MyApp.Splash" parent="Theme.MaterialComponents.DayNight.NoActionBar"> <style name="Theme.MyApp.Splash" parent="Theme.MaterialComponents.DayNight.NoActionBar">

View File

@@ -16,6 +16,7 @@ dependencyResolutionManagement {
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
maven("https://jitpack.io")
} }
} }