国际化
This commit is contained in:
4
.idea/deploymentTargetSelector.xml
generated
4
.idea/deploymentTargetSelector.xml
generated
@@ -4,10 +4,10 @@
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<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">
|
||||
<handle>
|
||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=7PRDU19930003674" />
|
||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=3B15A70100N00000" />
|
||||
</handle>
|
||||
</Target>
|
||||
</DropdownSelection>
|
||||
|
||||
@@ -55,6 +55,7 @@ dependencies {
|
||||
implementation("com.google.android.material:material:1.12.0")
|
||||
implementation("de.hdodenhof:circleimageview:3.1.0")
|
||||
implementation("com.google.android.flexbox:flexbox:3.0.0")
|
||||
implementation("com.github.Dimezis:BlurView:version-2.0.2")
|
||||
|
||||
// Jetpack Compose
|
||||
implementation("androidx.activity:activity-compose:1.8.0")
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<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.CAMERA" />
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ class GuideActivity : AppCompatActivity() {
|
||||
val text = it as TextView
|
||||
val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
||||
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 {
|
||||
BehaviorReporter.report(
|
||||
@@ -111,7 +111,7 @@ class GuideActivity : AppCompatActivity() {
|
||||
val text = it as TextView
|
||||
val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
||||
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 {
|
||||
|
||||
@@ -145,7 +145,6 @@ class ImeGuideActivity : AppCompatActivity() {
|
||||
enableText == null || selectText == null ||
|
||||
enableImg == null || selectImg == null
|
||||
) {
|
||||
Log.e(TAG, "有 View 为 null,检查 activity_ime_guide.xml 的 id 是否匹配")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -178,22 +177,24 @@ class ImeGuideActivity : AppCompatActivity() {
|
||||
|
||||
if (!enabled && !selected) {
|
||||
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"))
|
||||
selectText.setTextColor(Color.parseColor("#FFFFFF"))
|
||||
selectText.setTextColor(Color.parseColor("#A1A1A1"))
|
||||
enableImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img)
|
||||
selectImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img)
|
||||
step1.text = "Step one"
|
||||
step2.text = "Check to enable key of love"
|
||||
step1.text = getString(R.string.imguide_text1_step1)
|
||||
step2.text = getString(R.string.imguide_text2_step1)
|
||||
selectLayout.setOnClickListener(null)
|
||||
} else if (!enabled && selected) {
|
||||
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)
|
||||
selectImg.setImageResource(R.drawable.ime_guide_activity_btn_unfinished_img)
|
||||
enableText.setTextColor(Color.parseColor("#FFFFFF"))
|
||||
selectText.setTextColor(Color.parseColor("#FFFFFF"))
|
||||
step1.text = "Step one"
|
||||
step2.text = "Check to enable key of love"
|
||||
selectText.setTextColor(Color.parseColor("#A1A1A1"))
|
||||
step1.text = getString(R.string.imguide_text1_step1)
|
||||
step2.text = getString(R.string.imguide_text2_step1)
|
||||
selectLayout.setOnClickListener(null)
|
||||
} else if (enabled && !selected) {
|
||||
enableLayout.background = getDrawable(R.drawable.ime_guide_activity_btn_completed)
|
||||
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)
|
||||
enableText.setTextColor(Color.parseColor("#A1A1A1"))
|
||||
selectText.setTextColor(Color.parseColor("#FFFFFF"))
|
||||
step1.text = "Step two"
|
||||
step2.text = "Select key of love as your default input method"
|
||||
step1.text =getString(R.string.imguide_text1_step2)
|
||||
step2.text = getString(R.string.imguide_text2_step2)
|
||||
} else if (enabled && selected) {
|
||||
enableLayout.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)
|
||||
enableText.setTextColor(Color.parseColor("#A1A1A1"))
|
||||
selectText.setTextColor(Color.parseColor("#A1A1A1"))
|
||||
step1.text = "Completed"
|
||||
step2.text = "You have completed the relevant Settings"
|
||||
step1.text =getString(R.string.imguide_text1_step3)
|
||||
step2.text = getString(R.string.imguide_text2_step3)
|
||||
BehaviorReporter.report(
|
||||
isNewUser = false,
|
||||
"page_id" to "keyboard_permission_guide",
|
||||
"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 {
|
||||
startActivity(Intent(this, GuideActivity::class.java))
|
||||
} catch (e: Exception) {
|
||||
|
||||
@@ -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.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
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.lifecycleScope
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.navigation.navOptions
|
||||
import com.example.myapplication.network.AuthEvent
|
||||
import com.example.myapplication.network.AuthEventBus
|
||||
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.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -25,6 +42,7 @@ class MainActivity : AppCompatActivity() {
|
||||
private val TAB_HOME = "tab_home"
|
||||
private val TAB_SHOP = "tab_shop"
|
||||
private val TAB_MINE = "tab_mine"
|
||||
private val TAB_CIRCLE = "tab_circle"
|
||||
private val GLOBAL_HOST = "global_host"
|
||||
|
||||
private var currentTabTag = TAB_HOME
|
||||
@@ -41,20 +59,29 @@ class MainActivity : AppCompatActivity() {
|
||||
mapOf(
|
||||
R.id.home_graph to TAB_HOME,
|
||||
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 shopHost: NavHostFragment
|
||||
private lateinit var circleHost: NavHostFragment
|
||||
private lateinit var mineHost: NavHostFragment
|
||||
private lateinit var globalHost: NavHostFragment
|
||||
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
|
||||
get() = when (currentTabTag) {
|
||||
TAB_SHOP -> shopHost
|
||||
TAB_MINE -> mineHost
|
||||
TAB_CIRCLE -> circleHost
|
||||
else -> homeHost
|
||||
}
|
||||
|
||||
@@ -71,6 +98,7 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
private var lastHomeDestIdForReport: Int? = null
|
||||
private var lastShopDestIdForReport: Int? = null
|
||||
private var lastCircleDestIdForReport: Int? = null
|
||||
private var lastMineDestIdForReport: Int? = null
|
||||
private var lastGlobalDestIdForReport: Int? = null
|
||||
|
||||
@@ -89,6 +117,13 @@ class MainActivity : AppCompatActivity() {
|
||||
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 =
|
||||
NavController.OnDestinationChangedListener { _, dest, _ ->
|
||||
if (lastMineDestIdForReport == dest.id) return@OnDestinationChangedListener
|
||||
@@ -108,8 +143,10 @@ class MainActivity : AppCompatActivity() {
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
bottomNav = findViewById(R.id.bottom_nav)
|
||||
bottomNavBlur = findViewById(R.id.bottom_nav_blur)
|
||||
bottomNav.itemIconTintList = null
|
||||
bottomNav.setOnItemReselectedListener { /* ignore */ }
|
||||
setupBottomNavBlur()
|
||||
|
||||
// 1) 恢复当前tab
|
||||
currentTabTag = savedInstanceState?.getString("current_tab_tag") ?: TAB_HOME
|
||||
@@ -125,9 +162,10 @@ class MainActivity : AppCompatActivity() {
|
||||
if (!isLoggedIn() && item.itemId in protectedTabs) {
|
||||
// 强制回到当前tab的选中状态,避免底栏短暂闪一下
|
||||
bottomNav.selectedItemId = when (currentTabTag) {
|
||||
TAB_SHOP -> R.id.shop_graph
|
||||
TAB_MINE -> R.id.mine_graph
|
||||
else -> R.id.home_graph
|
||||
TAB_SHOP -> R.id.shop_graph
|
||||
TAB_MINE -> R.id.mine_graph
|
||||
TAB_CIRCLE -> R.id.circle_graph
|
||||
else -> R.id.home_graph
|
||||
}
|
||||
pendingTabAfterLogin = tabTag // 记录目标tab
|
||||
openGlobal(R.id.loginFragment)
|
||||
@@ -164,6 +202,7 @@ class MainActivity : AppCompatActivity() {
|
||||
switchTab(tag)
|
||||
bottomNav.selectedItemId = when (tag) {
|
||||
TAB_SHOP -> R.id.shop_graph
|
||||
TAB_CIRCLE -> R.id.circle_graph
|
||||
TAB_MINE -> R.id.mine_graph
|
||||
else -> R.id.home_graph
|
||||
}
|
||||
@@ -195,7 +234,7 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
// 打开全局页面事件处理
|
||||
is AuthEvent.OpenGlobalPage -> {
|
||||
openGlobal(event.destinationId, event.bundle)
|
||||
openGlobal(event.destinationId, event.bundle, event.clearGlobalBackStack)
|
||||
}
|
||||
|
||||
is AuthEvent.UserUpdated -> {
|
||||
@@ -221,13 +260,16 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
// 7) 初始选中正确tab(不会触发二次创建)
|
||||
bottomNav.post {
|
||||
bottomNav.selectedItemId = when (currentTabTag) {
|
||||
TAB_SHOP -> R.id.shop_graph
|
||||
TAB_MINE -> R.id.mine_graph
|
||||
else -> R.id.home_graph
|
||||
bottomNav.selectedItemId = when (currentTabTag) {
|
||||
TAB_SHOP -> R.id.shop_graph
|
||||
TAB_MINE -> R.id.mine_graph
|
||||
TAB_CIRCLE -> R.id.circle_graph
|
||||
else -> R.id.home_graph
|
||||
}
|
||||
updateBottomNavVisibility()
|
||||
}
|
||||
|
||||
setupNetworkMonitor()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@@ -241,9 +283,16 @@ class MainActivity : AppCompatActivity() {
|
||||
runCatching {
|
||||
homeHost.navController.removeOnDestinationChangedListener(homeRouteListener)
|
||||
shopHost.navController.removeOnDestinationChangedListener(shopRouteListener)
|
||||
circleHost.navController.removeOnDestinationChangedListener(circleRouteListener)
|
||||
mineHost.navController.removeOnDestinationChangedListener(mineRouteListener)
|
||||
globalHost.navController.removeOnDestinationChangedListener(globalRouteListener)
|
||||
}
|
||||
connectivityManager?.let { cm ->
|
||||
networkCallback?.let { cm.unregisterNetworkCallback(it) }
|
||||
}
|
||||
networkCallback = null
|
||||
noNetworkDialog?.dismiss()
|
||||
noNetworkDialog = null
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
@@ -254,6 +303,8 @@ class MainActivity : AppCompatActivity() {
|
||||
?: NavHostFragment.create(R.navigation.home_graph)
|
||||
shopHost = fm.findFragmentByTag(TAB_SHOP) as? NavHostFragment
|
||||
?: 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
|
||||
?: NavHostFragment.create(R.navigation.mine_graph)
|
||||
|
||||
@@ -266,6 +317,7 @@ class MainActivity : AppCompatActivity() {
|
||||
.setReorderingAllowed(true)
|
||||
.add(R.id.tab_container, homeHost, TAB_HOME)
|
||||
.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)
|
||||
.commitNow()
|
||||
}
|
||||
@@ -293,7 +345,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 这些页面需要隐藏底部导航栏:你按需加/减
|
||||
* 需要隐藏底部导航栏的页面
|
||||
*/
|
||||
private fun shouldHideBottomNav(destId: Int): Boolean {
|
||||
return destId in setOf(
|
||||
@@ -301,6 +353,7 @@ class MainActivity : AppCompatActivity() {
|
||||
R.id.searchResultFragment,
|
||||
R.id.MySkin,
|
||||
R.id.notificationFragment,
|
||||
R.id.languageFragment,
|
||||
R.id.feedbackFragment,
|
||||
R.id.MyKeyboard,
|
||||
R.id.PersonalSettings,
|
||||
@@ -308,19 +361,19 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
/**
|
||||
* ✅ 统一底栏显隐逻辑:任何地方状态变化都调用它
|
||||
* 统一底栏显隐逻辑:任何地方状态变化都调用它
|
||||
*/
|
||||
private fun updateBottomNavVisibility() {
|
||||
// ✅ 只要 global overlay 不在 empty,底栏必须隐藏(用 NavController 判断,别用 View.visibility)
|
||||
if (isGlobalVisible()) {
|
||||
bottomNav.visibility = View.GONE
|
||||
bottomNavBlur.visibility = View.GONE
|
||||
return
|
||||
}
|
||||
|
||||
// 否则按“当前可见 tab 的当前目的地”判断
|
||||
val destId = currentTabNavController.currentDestination?.id
|
||||
bottomNav.visibility =
|
||||
if (destId != null && shouldHideBottomNav(destId)) View.GONE else View.VISIBLE
|
||||
val shouldShow = destId == null || !shouldHideBottomNav(destId)
|
||||
bottomNav.visibility = if (shouldShow) View.VISIBLE else View.GONE
|
||||
bottomNavBlur.visibility = if (shouldShow && blurReady) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
private fun bindGlobalVisibility() {
|
||||
@@ -371,6 +424,7 @@ class MainActivity : AppCompatActivity() {
|
||||
val targetHost = when (targetTag) {
|
||||
TAB_SHOP -> shopHost
|
||||
TAB_MINE -> mineHost
|
||||
TAB_CIRCLE -> circleHost
|
||||
else -> homeHost
|
||||
}
|
||||
val currentHost = currentTabHost
|
||||
@@ -386,6 +440,7 @@ class MainActivity : AppCompatActivity() {
|
||||
.hide(homeHost)
|
||||
.hide(shopHost)
|
||||
.hide(mineHost)
|
||||
.hide(circleHost)
|
||||
.show(targetHost)
|
||||
} else if (currentHost != targetHost) {
|
||||
transaction
|
||||
@@ -397,9 +452,11 @@ class MainActivity : AppCompatActivity() {
|
||||
.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(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)
|
||||
.runOnCommit {
|
||||
isSwitchingTab = false
|
||||
if (targetTag == TAB_CIRCLE) applyCircleTabBackground() else resetBottomNavBackground()
|
||||
updateBottomNavVisibility()
|
||||
|
||||
if (!force) {
|
||||
@@ -417,14 +474,72 @@ class MainActivity : AppCompatActivity() {
|
||||
.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等) */
|
||||
private fun openGlobal(destId: Int, bundle: Bundle? = null) {
|
||||
private fun openGlobal(destId: Int, bundle: Bundle? = null, clearBackStack: Boolean = false) {
|
||||
val fm = supportFragmentManager
|
||||
if (fm.isStateSaved) return
|
||||
|
||||
val navOptions = if (clearBackStack) {
|
||||
navOptions {
|
||||
// 清理 global overlay 栈,但不短暂显示 empty,避免闪屏
|
||||
popUpTo(R.id.globalEmptyFragment) { inclusive = false }
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
try {
|
||||
if (bundle != null) globalNavController.navigate(destId, bundle)
|
||||
else globalNavController.navigate(destId)
|
||||
if (bundle != null) globalNavController.navigate(destId, bundle, navOptions)
|
||||
else globalNavController.navigate(destId, null, navOptions)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
@@ -441,6 +556,7 @@ class MainActivity : AppCompatActivity() {
|
||||
homeHost.navController.addOnDestinationChangedListener(listener)
|
||||
shopHost.navController.addOnDestinationChangedListener(listener)
|
||||
mineHost.navController.addOnDestinationChangedListener(listener)
|
||||
circleHost.navController.addOnDestinationChangedListener(listener)
|
||||
BehaviorReporter.report(
|
||||
isNewUser = false,
|
||||
"page_id" to "home",
|
||||
@@ -452,6 +568,7 @@ class MainActivity : AppCompatActivity() {
|
||||
homeHost.navController.addOnDestinationChangedListener(homeRouteListener)
|
||||
shopHost.navController.addOnDestinationChangedListener(shopRouteListener)
|
||||
mineHost.navController.addOnDestinationChangedListener(mineRouteListener)
|
||||
circleHost.navController.addOnDestinationChangedListener(circleRouteListener)
|
||||
globalHost.navController.addOnDestinationChangedListener(globalRouteListener)
|
||||
|
||||
// ✅ 删除:初始化手动上报(否则启动时会重复上报)
|
||||
@@ -559,6 +676,7 @@ class MainActivity : AppCompatActivity() {
|
||||
R.id.notificationFragment -> "notice" // 消息通知
|
||||
R.id.feedbackFragment -> "feedback" // 意见反馈
|
||||
R.id.consumptionRecordFragment -> "consumption_record" // 消费记录
|
||||
R.id.languageFragment -> "language_settings" // 语言切换页
|
||||
|
||||
/** ==================== 登录 & 注册 ==================== */
|
||||
R.id.loginFragment -> "login" // 登录页
|
||||
@@ -598,4 +716,97 @@ class MainActivity : AppCompatActivity() {
|
||||
"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()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ class MyApp : Application() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
AppContext.init(this) // ✅ 新增:全局 Application Context
|
||||
AppContext.init(this) // ?? Application Context
|
||||
|
||||
RetrofitClient.init(this)
|
||||
NetworkClient.init(this) // ✅ SSE 用(带 token/签名拦截器)
|
||||
NetworkClient.init(this) // SSE ???token/??????
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ class OnboardingActivity : AppCompatActivity() {
|
||||
startActivity(Intent(this, MainActivity::class.java))
|
||||
finish()
|
||||
}else{
|
||||
Toast.makeText(this, "Please select your gender.", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this, getString(R.string.gender_hint), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ import com.example.myapplication.network.BehaviorReporter
|
||||
class SplashActivity : AppCompatActivity() {
|
||||
|
||||
// private lateinit var progressBar: ProgressBar
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
private var pendingNavigation: Runnable? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -18,38 +20,43 @@ class SplashActivity : AppCompatActivity() {
|
||||
|
||||
// progressBar = findViewById(R.id.progressBar)
|
||||
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
val prefs = getSharedPreferences("app_prefs", MODE_PRIVATE)
|
||||
val isFirstLaunch = prefs.getBoolean("is_first_launch", true)
|
||||
if(isFirstLaunch){
|
||||
BehaviorReporter.report(
|
||||
isNewUser = false,
|
||||
"page_id" to "sex_select",
|
||||
)
|
||||
BehaviorReporter.report(
|
||||
isNewUser = false,
|
||||
"page_id" to "guide",
|
||||
)
|
||||
}
|
||||
val prefs = getSharedPreferences("app_prefs", MODE_PRIVATE)
|
||||
val isFirstLaunch = prefs.getBoolean("is_first_launch", true)
|
||||
if (isFirstLaunch) {
|
||||
BehaviorReporter.report(
|
||||
isNewUser = false,
|
||||
"page_id" to "sex_select",
|
||||
)
|
||||
BehaviorReporter.report(
|
||||
isNewUser = false,
|
||||
"page_id" to "guide",
|
||||
)
|
||||
}
|
||||
|
||||
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()
|
||||
Intent(this, OnboardingActivity::class.java)
|
||||
} else {
|
||||
// 不是第一次 → 进入主界面,携带原始intent的参数
|
||||
Intent(this, MainActivity::class.java).apply {
|
||||
intent.extras?.let { putExtras(it) }
|
||||
}
|
||||
}
|
||||
startActivity(targetIntent)
|
||||
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() {
|
||||
pendingNavigation?.let { handler.removeCallbacks(it) }
|
||||
pendingNavigation = null
|
||||
// progressBar.clearAnimation()
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -629,7 +629,7 @@ class AiKeyboard(
|
||||
val list = resp.data ?: emptyList()
|
||||
renderPersonaCards(container, list)
|
||||
} 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 {
|
||||
Toast.makeText(env.ctx, resp.message, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
@@ -25,7 +25,11 @@ sealed class AuthEvent {
|
||||
data class GenericError(val message: String) : AuthEvent()
|
||||
object LoginSuccess : AuthEvent()
|
||||
data class Logout(val returnTabTag: String) : AuthEvent()
|
||||
data class OpenGlobalPage(val destinationId: Int, val bundle: Bundle? = null) : AuthEvent()
|
||||
object UserUpdated : AuthEvent()
|
||||
data class CharacterDeleted(val characterId: Int) : AuthEvent()
|
||||
}
|
||||
data class OpenGlobalPage(
|
||||
val destinationId: Int,
|
||||
val bundle: Bundle? = null,
|
||||
val clearGlobalBackStack: Boolean = false
|
||||
) : AuthEvent()
|
||||
object UserUpdated : AuthEvent()
|
||||
data class CharacterDeleted(val characterId: Int) : AuthEvent()
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,8 @@ import com.example.myapplication.network.AddPersonaClick
|
||||
import com.example.myapplication.network.AuthEvent
|
||||
import com.example.myapplication.network.AuthEventBus
|
||||
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.listByTagWithNotLogin
|
||||
import com.example.myapplication.utils.EncryptedSharedPreferencesUtil
|
||||
@@ -58,6 +60,7 @@ class HomeFragment : Fragment() {
|
||||
private lateinit var loadingOverlay: LoadingOverlay
|
||||
|
||||
private var preloadJob: Job? = null
|
||||
private var networkRefreshJob: Job? = null
|
||||
private var allPersonaCache: List<listByTagWithNotLogin> = emptyList()
|
||||
private val personaCache = mutableMapOf<Int, List<listByTagWithNotLogin>>()
|
||||
|
||||
@@ -79,6 +82,7 @@ class HomeFragment : Fragment() {
|
||||
|
||||
override fun onDestroyView() {
|
||||
preloadJob?.cancel()
|
||||
networkRefreshJob?.cancel()
|
||||
pageChangeCallback?.let { viewPager.unregisterOnPageChangeCallback(it) }
|
||||
pageChangeCallback = null
|
||||
sheetAdapter = null
|
||||
@@ -238,6 +242,16 @@ class HomeFragment : Fragment() {
|
||||
loadingOverlay = LoadingOverlay.attach(root)
|
||||
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 {
|
||||
if (!isAdded) return@post
|
||||
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 ----------------
|
||||
|
||||
private fun startPreloadAllTagsFillCacheOnly() {
|
||||
|
||||
@@ -62,7 +62,7 @@ class PersonaDetailDialogFragment : DialogFragment() {
|
||||
tvName.text = data.characterName ?: ""
|
||||
download.text = data.download ?: ""
|
||||
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)
|
||||
val newAdded = !(data.added ?: false)
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ import com.example.myapplication.work.ThemeDownloadWorker
|
||||
import com.example.myapplication.ui.shop.ShopEvent
|
||||
import com.example.myapplication.ui.shop.ShopEventBus
|
||||
import com.example.myapplication.network.BehaviorReporter
|
||||
import com.example.myapplication.network.AuthEvent
|
||||
import com.example.myapplication.network.AuthEventBus
|
||||
|
||||
class KeyboardDetailFragment : Fragment() {
|
||||
|
||||
@@ -103,7 +105,8 @@ class KeyboardDetailFragment : Fragment() {
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
tvKeyboardName.text = themeDetailResp?.themeName
|
||||
tvDownloadCount.text = "Download:${themeDetailResp?.themeDownload}"
|
||||
tvDownloadCount.text = getString(R.string.detail_download)+"${themeDetailResp?.themeDownload}"
|
||||
tvPrice.text = "${themeDetailResp?.themePrice}"
|
||||
|
||||
if (themeDetailResp?.isPurchased ?: false) {
|
||||
@@ -417,7 +420,7 @@ class KeyboardDetailFragment : Fragment() {
|
||||
// 在主线程中更新UI
|
||||
view?.post {
|
||||
progressBar.visibility = View.VISIBLE
|
||||
enabledButtonText.text = "Loading..."
|
||||
enabledButtonText.text = getString(R.string.loading)
|
||||
// 完全禁用按钮交互
|
||||
enabledButton.isEnabled = false
|
||||
enabledButton.isClickable = false
|
||||
@@ -436,7 +439,7 @@ class KeyboardDetailFragment : Fragment() {
|
||||
// 在主线程中更新UI
|
||||
view?.post {
|
||||
progressBar.visibility = View.GONE
|
||||
enabledButtonText.text = "Enabled"
|
||||
enabledButtonText.text = getString(R.string.detail_enabled)
|
||||
// 恢复按钮交互
|
||||
enabledButton.isEnabled = true
|
||||
enabledButton.isClickable = true
|
||||
|
||||
@@ -60,11 +60,11 @@ class MyKeyboard : Fragment() {
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
val resp = setdelUserCharacter(item.id)
|
||||
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))
|
||||
loadList()
|
||||
} 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)
|
||||
if (resp?.code == 0 && resp.data == true) {
|
||||
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 {
|
||||
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) {
|
||||
Toast.makeText(requireContext(), "Network error: ${e.message}", Toast.LENGTH_SHORT).show()
|
||||
@@ -124,10 +124,10 @@ class MyKeyboard : Fragment() {
|
||||
adapter.submitList(resp.data)
|
||||
Log.d("1314520-list", resp.data.toString())
|
||||
} 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) {
|
||||
Toast.makeText(requireContext(), "Load failed: ${e.message}", Toast.LENGTH_SHORT).show()
|
||||
Log.d("MyKeyboard-loadList", e.message.toString())
|
||||
} finally {
|
||||
swipeRefresh.isRefreshing = false
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ import com.example.myapplication.network.RetrofitClient
|
||||
import com.example.myapplication.utils.EncryptedSharedPreferencesUtil
|
||||
import android.util.Log
|
||||
import com.example.myapplication.network.BehaviorReporter
|
||||
import com.example.myapplication.network.AuthEvent
|
||||
import com.example.myapplication.network.AuthEventBus
|
||||
|
||||
class ForgetPasswordEmailFragment : Fragment() {
|
||||
|
||||
@@ -42,9 +44,9 @@ class ForgetPasswordEmailFragment : Fragment() {
|
||||
emailEditText = view.findViewById<EditText>(R.id.et_email)
|
||||
|
||||
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
|
||||
parentFragmentManager.popBackStack()
|
||||
AuthEventBus.emit(AuthEvent.UserUpdated)
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
|
||||
// 下一步按钮点击事件
|
||||
view.findViewById<TextView>(R.id.nextstep).setOnClickListener {
|
||||
// 对输入框去除首尾空格
|
||||
@@ -52,9 +54,9 @@ class ForgetPasswordEmailFragment : Fragment() {
|
||||
|
||||
// 判断邮箱是否为空
|
||||
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)) {
|
||||
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 {
|
||||
BehaviorReporter.report(
|
||||
isNewUser = false,
|
||||
@@ -68,8 +70,8 @@ class ForgetPasswordEmailFragment : Fragment() {
|
||||
val response = RetrofitClient.apiService.sendVerifyCode(body)
|
||||
if (response.code == 0) {
|
||||
EncryptedSharedPreferencesUtil.save(requireContext(), "forget_email", email)
|
||||
findNavController().navigate(R.id.action_forgetPasswordEmailFragment_to_forgetPasswordVerifyFragment)
|
||||
Toast.makeText(activity, "A verification email has been sent to ${email}. Please check your inbox to complete the verification.", Toast.LENGTH_LONG).show()
|
||||
AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.forgetPasswordVerifyFragment))
|
||||
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) {
|
||||
Log.e("1314520-MineFragment", "发送验证码失败", e)
|
||||
|
||||
@@ -22,6 +22,8 @@ import com.example.myapplication.ui.common.LoadingOverlay
|
||||
import com.example.myapplication.utils.EncryptedSharedPreferencesUtil
|
||||
import kotlinx.coroutines.launch
|
||||
import com.example.myapplication.network.BehaviorReporter
|
||||
import com.example.myapplication.network.AuthEvent
|
||||
import com.example.myapplication.network.AuthEventBus
|
||||
|
||||
class ForgetPasswordResetFragment : Fragment() {
|
||||
|
||||
@@ -45,7 +47,8 @@ class ForgetPasswordResetFragment : Fragment() {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
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)
|
||||
@@ -107,9 +110,9 @@ class ForgetPasswordResetFragment : Fragment() {
|
||||
|
||||
//判断密码,邮箱,确认密码是否为空
|
||||
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) {
|
||||
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 {
|
||||
BehaviorReporter.report(
|
||||
isNewUser = false,
|
||||
@@ -127,7 +130,7 @@ class ForgetPasswordResetFragment : Fragment() {
|
||||
val response = RetrofitClient.apiService.resetPassword(body)
|
||||
if (response.code == 0) {
|
||||
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跳转到登录页面
|
||||
findNavController().navigate(R.id.action_global_loginFragment_from_forget_password)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import com.example.myapplication.network.RetrofitClient
|
||||
import com.example.myapplication.network.VerifyCodeRequest
|
||||
import android.util.Log
|
||||
import com.example.myapplication.network.BehaviorReporter
|
||||
import com.example.myapplication.network.AuthEvent
|
||||
import com.example.myapplication.network.AuthEventBus
|
||||
|
||||
class ForgetPasswordVerifyFragment : Fragment() {
|
||||
|
||||
@@ -42,18 +44,19 @@ class ForgetPasswordVerifyFragment : Fragment() {
|
||||
|
||||
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 {
|
||||
parentFragmentManager.popBackStack()
|
||||
AuthEventBus.emit(AuthEvent.UserUpdated)
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
|
||||
view.findViewById<TextView>(R.id.nextstep).setOnClickListener {
|
||||
// 验证验证码
|
||||
val verifyCode = getVerifyCode()
|
||||
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
|
||||
}
|
||||
|
||||
@@ -73,8 +76,8 @@ class ForgetPasswordVerifyFragment : Fragment() {
|
||||
)
|
||||
val response = RetrofitClient.apiService.verifyCode(body)
|
||||
if (response.code == 0 && response.data == true){
|
||||
Toast.makeText(activity, "The verification code has been verified successfully", Toast.LENGTH_SHORT).show()
|
||||
findNavController().navigate(R.id.action_forgetPasswordVerifyFragment_to_forgetPasswordResetFragment)
|
||||
Toast.makeText(activity, getString(R.string.Pop_up_window_ForgetPasswordVerifyFragment_2), Toast.LENGTH_SHORT).show()
|
||||
AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.forgetPasswordResetFragment))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("1314520-MineFragment", "验证码验证失败", e)
|
||||
|
||||
@@ -63,7 +63,7 @@ class LoginFragment : Fragment() {
|
||||
"page_id" to "login",
|
||||
"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 {
|
||||
@@ -72,11 +72,12 @@ class LoginFragment : Fragment() {
|
||||
"page_id" to "login",
|
||||
"element_id" to "forgot_btn",
|
||||
)
|
||||
findNavController().navigate(R.id.action_loginFragment_to_forgetPasswordEmailFragment)
|
||||
AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.forgetPasswordEmailFragment))
|
||||
}
|
||||
// 返回 - 在global_graph中,直接popBackStack回到globalEmptyFragment
|
||||
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
|
||||
findNavController().popBackStack()
|
||||
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
|
||||
AuthEventBus.emit(AuthEvent.UserUpdated)
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
// 绑定控件(id 必须和 xml 里的一样)
|
||||
passwordEditText = view.findViewById(R.id.et_password)
|
||||
@@ -119,7 +120,7 @@ class LoginFragment : Fragment() {
|
||||
val email = emailEditText.text?.toString().orEmpty()
|
||||
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 {
|
||||
BehaviorReporter.report(
|
||||
isNewUser = false,
|
||||
@@ -145,12 +146,12 @@ class LoginFragment : Fragment() {
|
||||
AuthEventBus.emit(AuthEvent.CharacterDeleted(0))
|
||||
// 不在这里popBackStack,让MainActivity的LoginSuccess事件处理关闭全局overlay
|
||||
} 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()
|
||||
} catch (e: Exception) {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import com.example.myapplication.utils.EncryptedSharedPreferencesUtil
|
||||
import com.example.myapplication.ui.common.LoadingOverlay
|
||||
import kotlinx.coroutines.launch
|
||||
import android.util.Log
|
||||
import com.example.myapplication.network.AuthEventBus
|
||||
import com.example.myapplication.network.AuthEvent
|
||||
import com.example.myapplication.network.BehaviorReporter
|
||||
|
||||
class RegisterFragment : Fragment() {
|
||||
@@ -108,11 +110,11 @@ class RegisterFragment : Fragment() {
|
||||
|
||||
//判断密码,邮箱,确认密码是否为空
|
||||
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) {
|
||||
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)) {
|
||||
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 {
|
||||
BehaviorReporter.report(
|
||||
isNewUser = false,
|
||||
@@ -128,8 +130,8 @@ class RegisterFragment : Fragment() {
|
||||
EncryptedSharedPreferencesUtil.save(requireContext(), "register_email", email)
|
||||
EncryptedSharedPreferencesUtil.save(requireContext(), "register_password", password)
|
||||
EncryptedSharedPreferencesUtil.save(requireContext(), "register_confirm_password", confirmPassword)
|
||||
findNavController().navigate(R.id.action_registerFragment_to_registerVerifyFragment)
|
||||
Toast.makeText(activity, "A verification email has been sent to ${email}. Please check your inbox to complete the verification.", Toast.LENGTH_LONG).show()
|
||||
AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.registerVerifyFragment))
|
||||
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) {
|
||||
Log.e("1314520-MineFragment", "获取失败", e)
|
||||
@@ -144,7 +146,8 @@ class RegisterFragment : Fragment() {
|
||||
|
||||
// 返回按钮
|
||||
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
|
||||
parentFragmentManager.popBackStack()
|
||||
AuthEventBus.emit(AuthEvent.UserUpdated)
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ import com.example.myapplication.ui.common.CodeEditText
|
||||
import com.example.myapplication.utils.EncryptedSharedPreferencesUtil
|
||||
import kotlinx.coroutines.launch
|
||||
import android.widget.TextView
|
||||
import com.example.myapplication.network.AuthEventBus
|
||||
import com.example.myapplication.network.AuthEvent
|
||||
import com.example.myapplication.network.BehaviorReporter
|
||||
|
||||
class RegisterVerifyFragment : Fragment() {
|
||||
@@ -42,7 +44,8 @@ class RegisterVerifyFragment : Fragment() {
|
||||
loadingOverlay = com.example.myapplication.ui.common.LoadingOverlay.attach(view as ViewGroup)
|
||||
|
||||
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
|
||||
parentFragmentManager.popBackStack()
|
||||
AuthEventBus.emit(AuthEvent.UserUpdated)
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
|
||||
// 注意:布局里的 6 个输入框需要是 CodeEditText
|
||||
@@ -63,13 +66,12 @@ class RegisterVerifyFragment : Fragment() {
|
||||
val savedGender = EncryptedSharedPreferencesUtil.get(requireContext(), "gender", String::class.java)
|
||||
val savedInviteCode = EncryptedSharedPreferencesUtil.get(requireContext(), "inviteCode", String::class.java)
|
||||
|
||||
view.findViewById<TextView>(R.id.tv_code_hint).text =
|
||||
"A verification email has been sent to ${savedEmail}. Please check your inbox to complete the verification."
|
||||
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)
|
||||
|
||||
view.findViewById<TextView>(R.id.nextstep).setOnClickListener {
|
||||
val verifyCode = getVerifyCode()
|
||||
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
|
||||
}
|
||||
|
||||
@@ -92,11 +94,11 @@ class RegisterVerifyFragment : Fragment() {
|
||||
|
||||
val response = RetrofitClient.apiService.register(body)
|
||||
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_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) {
|
||||
Log.e("1314520-MineFragment", "注册失败", e)
|
||||
|
||||
@@ -24,6 +24,8 @@ 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
|
||||
@@ -85,7 +87,7 @@ class MineFragment : Fragment() {
|
||||
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText("h5Link", link)
|
||||
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(
|
||||
isNewUser = false,
|
||||
"page_id" to "my",
|
||||
@@ -155,6 +157,17 @@ class MineFragment : Fragment() {
|
||||
"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 可靠)
|
||||
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() {
|
||||
@@ -192,7 +215,7 @@ class MineFragment : Fragment() {
|
||||
LoginResponse::class.java
|
||||
)
|
||||
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 ->
|
||||
Glide.with(requireContext())
|
||||
.load(url)
|
||||
@@ -207,7 +230,7 @@ class MineFragment : Fragment() {
|
||||
*/
|
||||
private fun refreshUser(force: Boolean, showToast: Boolean = false) {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -222,7 +245,7 @@ class MineFragment : Fragment() {
|
||||
|
||||
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 ->
|
||||
Glide.with(requireContext())
|
||||
@@ -232,11 +255,11 @@ class MineFragment : Fragment() {
|
||||
|
||||
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) {
|
||||
if (e is kotlinx.coroutines.CancellationException) return@launch
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import com.example.myapplication.network.BehaviorReporter
|
||||
import com.example.myapplication.network.AuthEvent
|
||||
import com.example.myapplication.network.AuthEventBus
|
||||
|
||||
class FeedbackFragment : Fragment() {
|
||||
|
||||
@@ -33,7 +35,8 @@ class FeedbackFragment : Fragment() {
|
||||
|
||||
// 关闭按钮
|
||||
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 {
|
||||
val feedbackText = etFeedback.text.toString().trim()
|
||||
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
|
||||
}
|
||||
BehaviorReporter.report(
|
||||
@@ -72,10 +75,11 @@ class FeedbackFragment : Fragment() {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
val response = submitFeedback(feedbackRequest(content = feedbackText))
|
||||
if (response?.code == 0) {
|
||||
Toast.makeText(context, "Feedback submitted successfully", Toast.LENGTH_SHORT).show()
|
||||
parentFragmentManager.popBackStack()
|
||||
Toast.makeText(context, getString(R.string.feedback_submit_btn), Toast.LENGTH_SHORT).show()
|
||||
AuthEventBus.emit(AuthEvent.UserUpdated)
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
} 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import kotlin.math.abs
|
||||
|
||||
class GenderSelectSheet : BottomSheetDialogFragment() {
|
||||
|
||||
private val values = listOf("Male", "Female", "The third gender")
|
||||
private lateinit var values: List<String>
|
||||
private var selectedIndex = 0
|
||||
|
||||
private val itemHeightDp = 48f // 每行高度(和 Adapter 里一致)
|
||||
@@ -31,6 +31,7 @@ class GenderSelectSheet : BottomSheetDialogFragment() {
|
||||
): View {
|
||||
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)
|
||||
|
||||
val rv = view.findViewById<RecyclerView>(R.id.gender_wheel)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ import android.widget.FrameLayout
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.example.myapplication.network.AuthEvent
|
||||
import com.example.myapplication.network.AuthEventBus
|
||||
import java.util.*
|
||||
|
||||
class NotificationFragment : Fragment() {
|
||||
@@ -28,7 +30,8 @@ class NotificationFragment : Fragment() {
|
||||
|
||||
// 设置关闭按钮点击事件
|
||||
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
|
||||
parentFragmentManager.popBackStack()
|
||||
AuthEventBus.emit(AuthEvent.UserUpdated)
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,7 +173,7 @@ class PersonalSettings : BottomSheetDialogFragment() {
|
||||
val uid = user?.uid?.toString() ?: tvUserId.text?.toString().orEmpty()
|
||||
if (uid.isBlank()) return@setOnClickListener
|
||||
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 =====================
|
||||
@@ -189,7 +189,7 @@ class PersonalSettings : BottomSheetDialogFragment() {
|
||||
val resp = getUserdata()
|
||||
val u = resp?.data // ???????????? ApiResponse ???????????? data??????????????????????????????
|
||||
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
|
||||
}
|
||||
user = u
|
||||
@@ -213,9 +213,9 @@ class PersonalSettings : BottomSheetDialogFragment() {
|
||||
}
|
||||
|
||||
private fun genderText(gender: Int): String = when (gender) {
|
||||
1 -> "Female"
|
||||
2 -> "The third gender"
|
||||
0 -> "Male"
|
||||
1 -> getString(R.string.gender_female)
|
||||
2 -> getString(R.string.gender_third)
|
||||
0 -> getString(R.string.gender_male)
|
||||
else -> ""
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ class PersonalSettings : BottomSheetDialogFragment() {
|
||||
} else {
|
||||
Toast.makeText(
|
||||
requireContext(),
|
||||
"Camera permission is required to take photos",
|
||||
getString(R.string.Pop_up_window_PersonalSettings_2),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
@@ -247,12 +247,12 @@ class PersonalSettings : BottomSheetDialogFragment() {
|
||||
|
||||
private fun showImagePickerDialog() {
|
||||
val options = arrayOf(
|
||||
getString(R.string.choose_from_gallery),
|
||||
getString(R.string.take_photo)
|
||||
getString(R.string.personal_choose_from_gallery),
|
||||
getString(R.string.personal_take_photo)
|
||||
)
|
||||
|
||||
androidx.appcompat.app.AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.change_avatar)
|
||||
.setTitle(R.string.personal_change_avatar)
|
||||
.setItems(options) { _, which ->
|
||||
when (which) {
|
||||
0 -> {
|
||||
@@ -345,7 +345,7 @@ class PersonalSettings : BottomSheetDialogFragment() {
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@ class PersonalSettings : BottomSheetDialogFragment() {
|
||||
}
|
||||
|
||||
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()
|
||||
tempFile.delete()
|
||||
return
|
||||
@@ -385,13 +385,13 @@ class PersonalSettings : BottomSheetDialogFragment() {
|
||||
|
||||
if (response?.code == 0) {
|
||||
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)
|
||||
} 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) {
|
||||
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)
|
||||
} finally {
|
||||
loadingOverlay.hide()
|
||||
|
||||
@@ -7,6 +7,8 @@ import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.example.myapplication.R
|
||||
import com.example.myapplication.network.AuthEvent
|
||||
import com.example.myapplication.network.AuthEventBus
|
||||
|
||||
class GoldCoinRechargeFragment : Fragment() {
|
||||
override fun onCreateView(
|
||||
@@ -22,7 +24,8 @@ class GoldCoinRechargeFragment : Fragment() {
|
||||
|
||||
// 设置关闭按钮点击事件
|
||||
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
|
||||
parentFragmentManager.popBackStack()
|
||||
AuthEventBus.emit(AuthEvent.UserUpdated)
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import android.widget.TextView
|
||||
import android.widget.ImageView
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.example.myapplication.R
|
||||
import com.example.myapplication.network.AuthEvent
|
||||
import com.example.myapplication.network.AuthEventBus
|
||||
|
||||
class RechargeFragment : Fragment() {
|
||||
override fun onCreateView(
|
||||
@@ -29,7 +31,8 @@ class RechargeFragment : Fragment() {
|
||||
|
||||
// 设置关闭按钮点击事件
|
||||
view.findViewById<ImageView>(R.id.iv_close).setOnClickListener {
|
||||
parentFragmentManager.popBackStack()
|
||||
AuthEventBus.emit(AuthEvent.UserUpdated)
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
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) {
|
||||
|
||||
@@ -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)
|
||||
bindClicks(view)
|
||||
setupSwipe()
|
||||
@@ -130,6 +145,9 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
|
||||
tabTitles = themeResp?.data ?: emptyList()
|
||||
styleIds = tabTitles.map { it.id }
|
||||
|
||||
// Fragment 可能在语言切换重建时被销毁/未附着,避免在未附着状态下创建子 Fragment
|
||||
if (!isAdded) return@launch
|
||||
|
||||
setupViewPagerOnce()
|
||||
setupTagsOnce()
|
||||
|
||||
@@ -150,6 +168,7 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
|
||||
updateBalance(getwalletBalance())
|
||||
|
||||
val newThemes = getThemeList()?.data ?: emptyList()
|
||||
if (!isAdded) return@launch
|
||||
if (newThemes != tabTitles) {
|
||||
tabTitles = newThemes
|
||||
styleIds = tabTitles.map { it.id }
|
||||
@@ -175,6 +194,7 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
|
||||
// ========================== ViewPager ==========================
|
||||
|
||||
private fun setupViewPagerOnce(force: Boolean = false) {
|
||||
if (!isAdded) return
|
||||
if (viewPager.adapter != null && !force) return
|
||||
|
||||
pageCallback?.let { viewPager.unregisterOnPageChangeCallback(it) }
|
||||
@@ -406,7 +426,7 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
|
||||
}
|
||||
view.findViewById<View>(R.id.skinButton).setOnClickListener {
|
||||
// 使用事件总线打开我的皮肤页面
|
||||
findNavController().navigate(R.id.action_shopfragment_to_myskin)
|
||||
AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.MySkin))
|
||||
BehaviorReporter.report(
|
||||
isNewUser = false,
|
||||
"page_id" to "shop",
|
||||
@@ -415,7 +435,7 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
|
||||
}
|
||||
view.findViewById<View>(R.id.searchButton).setOnClickListener {
|
||||
// 使用事件总线打开搜索页面
|
||||
findNavController().navigate(R.id.action_shopfragment_to_searchfragment)
|
||||
AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.searchFragment))
|
||||
BehaviorReporter.report(
|
||||
isNewUser = false,
|
||||
"page_id" to "shop",
|
||||
@@ -425,4 +445,3 @@ class ShopFragment : Fragment(R.layout.fragment_shop) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ import com.example.myapplication.network.themeStyle
|
||||
import com.example.myapplication.network.deleteThemeRequest
|
||||
import kotlinx.coroutines.launch
|
||||
import com.example.myapplication.network.BehaviorReporter
|
||||
import com.example.myapplication.network.AuthEvent
|
||||
import com.example.myapplication.network.AuthEventBus
|
||||
|
||||
class MySkin : Fragment() {
|
||||
|
||||
@@ -57,7 +59,8 @@ class MySkin : Fragment() {
|
||||
|
||||
// 返回
|
||||
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)
|
||||
@@ -66,7 +69,7 @@ class MySkin : Fragment() {
|
||||
adapter = MySkinAdapter(
|
||||
onItemClick = { /* 非编辑模式点击:进详情等 */ },
|
||||
onSelectionChanged = { count ->
|
||||
tvSelectedCount.text = "$count themes selected"
|
||||
tvSelectedCount.text = "$count"+ getString(R.string.skin_select_all)
|
||||
btnDelete.isEnabled = count > 0
|
||||
btnDelete.alpha = if (count > 0) 1f else 0.4f
|
||||
}
|
||||
@@ -91,7 +94,7 @@ class MySkin : Fragment() {
|
||||
tvEditor.setOnClickListener {
|
||||
if (!adapter.editMode) {
|
||||
adapter.enterEditMode()
|
||||
tvEditor.text = "Exit editing"
|
||||
tvEditor.text = getString(R.string.skin_exit_editing)
|
||||
bottomBar.post { showBottomBar() } // post 确保有 height
|
||||
BehaviorReporter.report(
|
||||
isNewUser = false,
|
||||
@@ -101,7 +104,7 @@ class MySkin : Fragment() {
|
||||
)
|
||||
} else {
|
||||
adapter.exitEditMode()
|
||||
tvEditor.text = "Editor"
|
||||
tvEditor.text = getString(R.string.skin_editor)
|
||||
hideBottomBar()
|
||||
BehaviorReporter.report(
|
||||
isNewUser = false,
|
||||
|
||||
@@ -11,7 +11,6 @@ import android.widget.*
|
||||
import androidx.cardview.widget.CardView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@@ -24,6 +23,8 @@ import com.google.android.flexbox.FlexboxLayout
|
||||
import com.google.android.flexbox.FlexboxLayout.LayoutParams
|
||||
import kotlinx.coroutines.launch
|
||||
import com.example.myapplication.network.BehaviorReporter
|
||||
import com.example.myapplication.network.AuthEvent
|
||||
import com.example.myapplication.network.AuthEventBus
|
||||
|
||||
|
||||
|
||||
@@ -60,12 +61,11 @@ class SearchFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
// 返回
|
||||
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)
|
||||
historyLayout = view.findViewById(R.id.layout_history_list)
|
||||
@@ -92,17 +92,14 @@ class SearchFragment : Fragment() {
|
||||
isNewUser = false,
|
||||
"page_id" to "search",
|
||||
"element_id" to "search_submit",
|
||||
"keyword" to bundle,
|
||||
)
|
||||
// 跳转时带上 bundle
|
||||
findNavController().navigate(
|
||||
R.id.action_searchFragment_to_searchResultFragment,
|
||||
bundle
|
||||
"keyword" to keyword,
|
||||
)
|
||||
// open search result via event bus with bundle
|
||||
AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.searchResultFragment, bundle))
|
||||
|
||||
etInput.setText("")
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "请输入搜索内容", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(requireContext(),getString(R.string.Pop_up_window_SearchFragment_1), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.LinearLayout
|
||||
@@ -43,7 +42,7 @@ class SearchResultFragment : Fragment() {
|
||||
|
||||
// 返回按钮
|
||||
view.findViewById<FrameLayout>(R.id.iv_close).setOnClickListener {
|
||||
parentFragmentManager.popBackStack()
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
|
||||
etInput = view.findViewById(R.id.et_input)
|
||||
@@ -55,28 +54,26 @@ class SearchResultFragment : Fragment() {
|
||||
|
||||
// 设置搜索按钮点击事件
|
||||
tvSearch.setOnClickListener {
|
||||
val keyword = etInput.text.toString()
|
||||
val keyword = etInput.text.toString().trim()
|
||||
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
|
||||
}
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
try {
|
||||
val searchResults = getSearchTheme(keyword)?.data
|
||||
// 渲染搜索结果列表
|
||||
handleSearchResults(searchResults)
|
||||
} catch (e: Exception) {
|
||||
Log.e("SearchResultFragment", "搜索主题失败", e)
|
||||
}
|
||||
}
|
||||
performSearch(keyword)
|
||||
}
|
||||
|
||||
|
||||
// 接收从上一个页面传来的搜索词
|
||||
val keyword = arguments?.getString("search_keyword") ?: ""
|
||||
val keyword = arguments?.getString("search_keyword").orEmpty()
|
||||
etInput.setText(keyword)
|
||||
etInput.setSelection(keyword.length)
|
||||
|
||||
if (keyword.isNotEmpty()) {
|
||||
performSearch(keyword)
|
||||
}
|
||||
}
|
||||
|
||||
private fun performSearch(keyword: String) {
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
try {
|
||||
val searchResults = getSearchTheme(keyword)?.data
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -126,7 +126,7 @@ class ThemeDownloadWorker(
|
||||
|
||||
private fun notifySuccess(context: Context) {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BIN
app/src/main/res/drawable/a123123123.jpg
Normal file
BIN
app/src/main/res/drawable/a123123123.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 MiB |
6
app/src/main/res/drawable/bg_dialog_button.xml
Normal file
6
app/src/main/res/drawable/bg_dialog_button.xml
Normal 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>
|
||||
6
app/src/main/res/drawable/bg_dialog_no_network.xml
Normal file
6
app/src/main/res/drawable/bg_dialog_no_network.xml
Normal 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>
|
||||
24
app/src/main/res/drawable/ic_circle_selector.xml
Normal file
24
app/src/main/res/drawable/ic_circle_selector.xml
Normal 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>
|
||||
9
app/src/main/res/drawable/ic_language.xml
Normal file
9
app/src/main/res/drawable/ic_language.xml
Normal 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>
|
||||
@@ -88,7 +88,7 @@
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="match_parent"
|
||||
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:textSize="10sp" />
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:maxWidth="179dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:text="Click "Copy any conversation", "Paste" and try replying using the keyboard [Persona] method"
|
||||
android:text="@string/guide_chat_2"
|
||||
android:textColor="#929292"
|
||||
android:textSize="10sp"
|
||||
android:lineHeight="20dp" />
|
||||
@@ -183,9 +183,9 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="Please enter your content"
|
||||
android:text="@string/guide_input"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#CBCBCB"/>
|
||||
android:textColor="#ABABAB"/>
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
<ImageView
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btnEnabledText"
|
||||
android:text="Enable it in Settings"
|
||||
android:text="@string/imguide_btn_1"
|
||||
android:textSize="13sp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btnSelectText"
|
||||
android:text="Select an input method"
|
||||
android:text="@string/imguide_btn_2"
|
||||
android:textSize="13sp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/window_background"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<FrameLayout
|
||||
@@ -28,14 +29,22 @@
|
||||
|
||||
</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
|
||||
android:id="@+id/bottom_nav"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="@android:color/white"
|
||||
android:background="@android:color/transparent"
|
||||
app:menu="@menu/menu_bottom_nav"
|
||||
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>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/tv_skip_bg"
|
||||
android:gravity="center"
|
||||
android:text="Skip"
|
||||
android:text="@string/skip"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
@@ -48,7 +48,7 @@
|
||||
android:layout_marginTop="30dp"
|
||||
android:elevation="2dp"
|
||||
android:gravity="center"
|
||||
android:text="Please select your gender"
|
||||
android:text="@string/gender_hint"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="24sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
@@ -94,7 +94,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="60dp"
|
||||
android:text="Male"
|
||||
android:text="@string/gender_male"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
||||
@@ -131,7 +131,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="60dp"
|
||||
android:text="Female"
|
||||
android:text="@string/gender_female"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
||||
@@ -175,7 +175,7 @@
|
||||
android:id="@+id/tv_male"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="The third gender"
|
||||
android:text="@string/gender_third"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
||||
@@ -190,7 +190,7 @@
|
||||
android:id="@+id/tv_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="59dp"
|
||||
android:text="Turn on the keyboard"
|
||||
android:text="@string/gender_btn"
|
||||
android:layout_gravity="bottom"
|
||||
android:gravity="center"
|
||||
android:textColor="#FFFFFF"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Delete character design?"
|
||||
android:text="@string/keyboard_delete_hint"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="16sp" />
|
||||
@@ -20,7 +20,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
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:textSize="13sp" />
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="Prof."
|
||||
android:text=""
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
@@ -62,7 +62,7 @@
|
||||
android:layout_height="42dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:text="Cancel"
|
||||
android:text="@string/cancel"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="14sp"
|
||||
android:background="@drawable/my_keyboard_cancel" />
|
||||
@@ -74,7 +74,7 @@
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="10dp"
|
||||
android:gravity="center"
|
||||
android:text="Delete"
|
||||
android:text="@string/delete"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="14sp"
|
||||
android:background="@drawable/my_keyboard_delete" />
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<!-- 标题 -->
|
||||
<TextView
|
||||
android:text="Confirm logging out?"
|
||||
android:text="@string/Logout_confirm_title"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#222222"
|
||||
@@ -19,7 +19,7 @@
|
||||
<!-- 描述 -->
|
||||
<TextView
|
||||
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:textColor="#666666"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn_cancel"
|
||||
android:text="Cancel"
|
||||
android:text="@string/cancel"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#666666"
|
||||
android:padding="12dp"
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn_logout"
|
||||
android:text="Log out"
|
||||
android:text="@string/Logout_confirm_btn"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#F44336"
|
||||
android:padding="12dp"
|
||||
|
||||
45
app/src/main/res/layout/dialog_no_network.xml
Normal file
45
app/src/main/res/layout/dialog_no_network.xml
Normal 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>
|
||||
@@ -19,7 +19,7 @@
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Purchase Confirmation"
|
||||
android:text="@string/detail_purchase_confirm"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#1B1F1A"
|
||||
@@ -31,7 +31,7 @@
|
||||
android:id="@+id/tv_message"
|
||||
android:layout_width="match_parent"
|
||||
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:textColor="#666666"
|
||||
android:gravity="center"
|
||||
@@ -52,7 +52,7 @@
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="Cancel"
|
||||
android:text="@string/cancel"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#999999"
|
||||
android:gravity="center"
|
||||
@@ -66,7 +66,7 @@
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="Confirm"
|
||||
android:text="@string/confirm"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#FFFFFF"
|
||||
android:gravity="center"
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
android:layout_marginEnd="49dp"
|
||||
android:gravity="center"
|
||||
android:textStyle="bold"
|
||||
android:text="Feedback"
|
||||
android:text="@string/feedback_title"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
@@ -64,14 +64,14 @@
|
||||
app:boxCornerRadiusBottomStart="8dp"
|
||||
app:boxCornerRadiusBottomEnd="8dp"
|
||||
app:hintTextColor="#02BEAC"
|
||||
app:placeholderText="Your Feedback">
|
||||
app:placeholderText="@string/feedback_input_hint_text">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/et_feedback"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:gravity="top|start"
|
||||
android:hint="Please enter your feedback..."
|
||||
android:hint="@string/feedback_input_hint"
|
||||
android:padding="12dp"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="4"
|
||||
@@ -94,7 +94,7 @@
|
||||
android:layout_height="45dp"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:text="Save"
|
||||
android:text="@string/save"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="16sp"
|
||||
android:background="@drawable/my_keyboard_delete"
|
||||
|
||||
41
app/src/main/res/layout/fragment_circle.xml
Normal file
41
app/src/main/res/layout/fragment_circle.xml
Normal 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>
|
||||
@@ -49,7 +49,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:text="Reset password"
|
||||
android:text="@string/forgot_password_title"
|
||||
android:textColor="#1B1F1A"/>
|
||||
|
||||
<EditText
|
||||
@@ -59,7 +59,7 @@
|
||||
android:layout_marginTop="20dp"
|
||||
android:background="@drawable/input_box_bg"
|
||||
android:padding="15dp"
|
||||
android:hint="Enter email address"
|
||||
android:hint="@string/register_input_email_hint"
|
||||
android:textColorHint="#CBCBCB"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#CBCBCB" />
|
||||
@@ -74,7 +74,7 @@
|
||||
android:textStyle="bold"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="18sp"
|
||||
android:text="Next step" />
|
||||
android:text="@string/next" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:text="Reset password"
|
||||
android:text="@string/forgot_password_title"
|
||||
android:textColor="#1B1F1A"/>
|
||||
|
||||
<RelativeLayout
|
||||
@@ -64,7 +64,7 @@
|
||||
android:textSize="14sp"
|
||||
android:padding="15dp"
|
||||
android:textColor="#000000"
|
||||
android:hint="Enter password"
|
||||
android:hint="@string/register_input_password_hint"
|
||||
android:textColorHint="#CBCBCB"
|
||||
android:background="@null"
|
||||
android:inputType="textPassword" />
|
||||
@@ -90,7 +90,7 @@
|
||||
android:textSize="14sp"
|
||||
android:padding="15dp"
|
||||
android:textColor="#000000"
|
||||
android:hint="Enter repeat password"
|
||||
android:hint="@string/register_input_repeat_password_hint"
|
||||
android:textColorHint="#CBCBCB"
|
||||
android:background="@null"
|
||||
android:inputType="textPassword" />
|
||||
@@ -114,7 +114,7 @@
|
||||
android:textStyle="bold"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="18sp"
|
||||
android:text="Next step" />
|
||||
android:text="@string/next" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:text="Reset password"
|
||||
android:text="@string/forgot_password_title"
|
||||
android:textColor="#1B1F1A"/>
|
||||
|
||||
<TextView
|
||||
@@ -56,7 +56,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="13sp"
|
||||
android:textStyle="bold"
|
||||
android:text="Enter email verification code"
|
||||
android:text="@string/register_verification"
|
||||
android:textColor="#1B1F1A"/>
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
android:textStyle="bold"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="18sp"
|
||||
android:text="Next step" />
|
||||
android:text="@string/next" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
@@ -48,7 +48,8 @@
|
||||
android:textStyle="bold"
|
||||
android:textColor="#1B1F1A"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:text="Become A Member Of LOVE KEY" />
|
||||
android:gravity="center"
|
||||
android:text="@string/home_member" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/Unlock"
|
||||
@@ -58,7 +59,7 @@
|
||||
android:textSize="14sp"
|
||||
android:textColor="#1B1F1A"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:text="Unlock all functions" />
|
||||
android:text="@string/home_unlock" />
|
||||
|
||||
<!-- 权益 -->
|
||||
<LinearLayout
|
||||
@@ -90,7 +91,7 @@
|
||||
android:textSize="12sp"
|
||||
android:gravity="center"
|
||||
android:textColor="#1B1F1A"
|
||||
android:text="Wireless sub-AI dialogue" />
|
||||
android:text="@string/home_ai_dialogue" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 权益2 -->
|
||||
@@ -114,7 +115,7 @@
|
||||
android:textSize="12sp"
|
||||
android:gravity="center"
|
||||
android:textColor="#1B1F1A"
|
||||
android:text="Personalized keyboard" />
|
||||
android:text="@string/home_ai_keyboard" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 权益3 -->
|
||||
@@ -138,7 +139,7 @@
|
||||
android:textSize="12sp"
|
||||
android:gravity="center"
|
||||
android:textColor="#1B1F1A"
|
||||
android:text="Chat persona" />
|
||||
android:text="@string/home_ai_persona" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 权益4 -->
|
||||
@@ -162,7 +163,7 @@
|
||||
android:textSize="12sp"
|
||||
android:gravity="center"
|
||||
android:textColor="#1B1F1A"
|
||||
android:text="Emotional counseling" />
|
||||
android:text="@string/home_ai_counseling" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -185,7 +186,7 @@
|
||||
android:textStyle="bold"
|
||||
android:gravity="center"
|
||||
android:textColor="#1B1F1A"
|
||||
android:text="Recharge now" />
|
||||
android:text="@string/home_recharge" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -260,7 +261,7 @@
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:gravity="center"
|
||||
android:text="Ranking List"
|
||||
android:text="@string/home_tab1"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#1B1F1A" />
|
||||
@@ -272,7 +273,7 @@
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="20dp"
|
||||
android:gravity="center"
|
||||
android:text="Persona circle"
|
||||
android:text="@string/home_tab2"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#801B1F1A" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="30sp"
|
||||
android:text="Hello!"
|
||||
android:text="@string/login_hello"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#403B5A" />
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
android:layout_width="130dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:text="Welcome to key of love keyboard"
|
||||
android:text="@string/login_hello_hint"
|
||||
android:textColor="#554F70" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
android:textSize="18sp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:textStyle="bold"
|
||||
android:text="Log in to key of love"
|
||||
android:text="@string/login_input_title"
|
||||
android:textColor="#1B1F1A" />
|
||||
|
||||
<!-- 输入框 -->
|
||||
@@ -105,7 +105,7 @@
|
||||
android:layout_marginTop="20dp"
|
||||
android:background="@drawable/input_box_bg"
|
||||
android:padding="15dp"
|
||||
android:hint="Please enter your email address"
|
||||
android:hint="@string/login_input_Email_hint"
|
||||
android:textColorHint="#CBCBCB"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#000000" />
|
||||
@@ -122,7 +122,7 @@
|
||||
android:textSize="14sp"
|
||||
android:padding="15dp"
|
||||
android:textColor="#000000"
|
||||
android:hint="Please enter the password"
|
||||
android:hint="@string/login_input_Password_hint"
|
||||
android:textColorHint="#CBCBCB"
|
||||
android:background="@null"
|
||||
android:inputType="textPassword" />
|
||||
@@ -146,7 +146,7 @@
|
||||
android:textStyle="bold"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="18sp"
|
||||
android:text="Login" />
|
||||
android:text="@string/login_input_btn" />
|
||||
|
||||
<com.google.android.flexbox.FlexboxLayout
|
||||
android:id="@+id/agreement_container"
|
||||
@@ -163,14 +163,14 @@
|
||||
<TextView
|
||||
android:layout_width="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:textColor="#554F70"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Terms Of Service "
|
||||
android:text="@string/terms_and_privacy_2"
|
||||
android:textStyle="bold"
|
||||
android:textSize="10sp"
|
||||
android:textColor="#554F70"/>
|
||||
@@ -178,21 +178,21 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="And Confirm"
|
||||
android:text="@string/terms_and_privacy_3"
|
||||
android:textSize="10sp"
|
||||
android:textColor="#554F70"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="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:textColor="#554F70"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Privacy Policy"
|
||||
android:text="@string/terms_and_privacy_5"
|
||||
android:textStyle="bold"
|
||||
android:textSize="10sp"
|
||||
android:textColor="#554F70"/>
|
||||
@@ -214,7 +214,7 @@
|
||||
<TextView
|
||||
android:layout_width="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:textColor="#554F70"/>
|
||||
|
||||
@@ -223,7 +223,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="Sign up"
|
||||
android:text="@string/login_register_btn"
|
||||
android:textStyle="bold"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#02BEAC"/>
|
||||
@@ -232,7 +232,7 @@
|
||||
android:id="@+id/tv_forgot_password"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Forgot password?"
|
||||
android:text="@string/login_forgot_password_btn"
|
||||
android:layout_marginTop="6dp"
|
||||
android:gravity="center"
|
||||
android:textStyle="bold"
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Personal"
|
||||
android:text="@string/mine_title_personal"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1"
|
||||
@@ -63,7 +63,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="My keyboard"
|
||||
android:text="@string/mine_my_keyboard"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="10sp" />
|
||||
</LinearLayout>
|
||||
@@ -105,7 +105,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/nickname"
|
||||
android:text="Username"
|
||||
android:text="@string/mine_username"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:ellipsize="end"
|
||||
@@ -118,7 +118,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/time"
|
||||
android:text="Time"
|
||||
android:text="@string/mine_time"
|
||||
android:textColor="#A4A4A4"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
@@ -181,7 +181,7 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="Consumption Record"
|
||||
android:text="@string/mine_consumption_record"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1"
|
||||
@@ -223,7 +223,49 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
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:textStyle="bold"
|
||||
android:layout_weight="1"
|
||||
@@ -265,7 +307,7 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="Share app"
|
||||
android:text="@string/mine_share_app"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1"
|
||||
@@ -309,14 +351,14 @@
|
||||
android:src="@drawable/feedback" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="Feedback"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1"
|
||||
android:textSize="20sp" />
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="@string/mine_feedback"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
@@ -348,14 +390,14 @@
|
||||
android:src="@drawable/e_mail" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="E-mail"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1"
|
||||
android:textSize="20sp" />
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="@string/mine_email"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
@@ -387,14 +429,14 @@
|
||||
android:src="@drawable/agreement" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="Agreement"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1"
|
||||
android:textSize="20sp" />
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="@string/mine_agreement"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
@@ -427,14 +469,14 @@
|
||||
android:src="@drawable/privacy_policy" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="Privacy Policy"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1"
|
||||
android:textSize="20sp" />
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="@string/mine_privacy_policy"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
@@ -453,7 +495,7 @@
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:gravity="center"
|
||||
android:text="Log Out"
|
||||
android:text="@string/mine_logout"
|
||||
android:textColor="#FF0000"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="30sp"
|
||||
android:text="Hello!"
|
||||
android:text="@string/login_hello"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#403B5A" />
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
android:layout_width="130dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:text="Welcome to key of love keyboard"
|
||||
android:text="@string/login_hello_hint"
|
||||
android:textColor="#554F70" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
android:textSize="18sp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:textStyle="bold"
|
||||
android:text="Log in to key of love"
|
||||
android:text="@string/register_title"
|
||||
android:textColor="#1B1F1A" />
|
||||
|
||||
<!-- 输入框 -->
|
||||
@@ -104,7 +104,7 @@
|
||||
android:layout_height="52dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:background="@drawable/input_box_bg"
|
||||
android:hint="Enter email address"
|
||||
android:hint="@string/register_input_email_hint"
|
||||
android:textColorHint="#CBCBCB"
|
||||
android:padding="15dp"
|
||||
android:textSize="14sp"
|
||||
@@ -122,7 +122,7 @@
|
||||
android:textSize="14sp"
|
||||
android:padding="15dp"
|
||||
android:textColor="#000000"
|
||||
android:hint="Enter password"
|
||||
android:hint="@string/register_input_password_hint"
|
||||
android:textColorHint="#CBCBCB"
|
||||
android:background="@null"
|
||||
android:inputType="textPassword" />
|
||||
@@ -149,7 +149,7 @@
|
||||
android:padding="15dp"
|
||||
android:textColor="#000000"
|
||||
android:background="@null"
|
||||
android:hint="Enter Repeat password"
|
||||
android:hint="@string/register_input_repeat_password_hint"
|
||||
android:textColorHint="#CBCBCB"
|
||||
android:inputType="textPassword" />
|
||||
<ImageView
|
||||
@@ -172,7 +172,7 @@
|
||||
android:textStyle="bold"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="18sp"
|
||||
android:text="Next step" />
|
||||
android:text="@string/next" />
|
||||
|
||||
<com.google.android.flexbox.FlexboxLayout
|
||||
android:id="@+id/agreement_container"
|
||||
@@ -186,17 +186,17 @@
|
||||
app:justifyContent="center"
|
||||
app:alignItems="center">
|
||||
|
||||
<TextView
|
||||
<TextView
|
||||
android:layout_width="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:textColor="#554F70"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Terms Of Service "
|
||||
android:text="@string/terms_and_privacy_2"
|
||||
android:textStyle="bold"
|
||||
android:textSize="10sp"
|
||||
android:textColor="#554F70"/>
|
||||
@@ -204,21 +204,21 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="And Confirm"
|
||||
android:text="@string/terms_and_privacy_3"
|
||||
android:textSize="10sp"
|
||||
android:textColor="#554F70"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="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:textColor="#554F70"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Privacy Policy"
|
||||
android:text="@string/terms_and_privacy_5"
|
||||
android:textStyle="bold"
|
||||
android:textSize="10sp"
|
||||
android:textColor="#554F70"/>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:text="Register"
|
||||
android:text="@string/register_register"
|
||||
android:textColor="#1B1F1A"/>
|
||||
|
||||
<TextView
|
||||
@@ -56,7 +56,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="13sp"
|
||||
android:textStyle="bold"
|
||||
android:text="Enter email verification code"
|
||||
android:text="@string/register_verification"
|
||||
android:textColor="#1B1F1A"/>
|
||||
|
||||
<TextView
|
||||
@@ -65,7 +65,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="13sp"
|
||||
android:textStyle="bold"
|
||||
android:text="Please enter the verification code sent to your email"
|
||||
android:text="@string/register_verification_hint"
|
||||
android:textColor="#02BEAC"/>
|
||||
|
||||
<!-- 验证码输入框 -->
|
||||
@@ -113,7 +113,7 @@
|
||||
android:textStyle="bold"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="18sp"
|
||||
android:text="Next step" />
|
||||
android:text="@string/next" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
@@ -57,14 +57,14 @@
|
||||
android:layout_gravity="center"
|
||||
android:textSize="13sp"
|
||||
android:background="@null"
|
||||
android:hint="Themes" />
|
||||
android:hint="@string/search_hint" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_search"
|
||||
android:layout_width="76dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_gravity="center"
|
||||
android:text="Search"
|
||||
android:text="@string/search_search"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/my_keyboard_delete"
|
||||
android:layout_marginEnd="4dp"
|
||||
@@ -91,7 +91,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textStyle="bold"
|
||||
android:text="Historical search"
|
||||
android:text="@string/search_historical"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="14sp" />
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Recommended skins"
|
||||
android:text="@string/recommended"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="14sp" />
|
||||
|
||||
@@ -57,14 +57,14 @@
|
||||
android:layout_gravity="center"
|
||||
android:textSize="13sp"
|
||||
android:background="@null"
|
||||
android:hint="Themes" />
|
||||
android:hint="@string/search_hint"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_search"
|
||||
android:layout_width="76dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_gravity="center"
|
||||
android:text="Search"
|
||||
android:text="@string/search_search"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/my_keyboard_delete"
|
||||
android:layout_marginEnd="4dp"
|
||||
@@ -96,7 +96,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="No data available for the time being"
|
||||
android:text="@string/search_not_data"
|
||||
android:textColor="#999999"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginStart="6dp"
|
||||
android:text="Points Mall"
|
||||
android:text="@string/shop_mall"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:textSize="22sp" />
|
||||
@@ -142,7 +142,7 @@
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="My points"
|
||||
android:text="@string/shop_points"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="14sp"
|
||||
android:padding="20dp" />
|
||||
@@ -187,7 +187,7 @@
|
||||
android:textStyle="bold"
|
||||
android:gravity="center"
|
||||
android:textColor="#1B1F1A"
|
||||
android:text="Recharge" />
|
||||
android:text="@string/shop_recharge" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Recommended skins"
|
||||
android:text="@string/recommended"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="14sp" />
|
||||
@@ -145,7 +145,7 @@
|
||||
android:textStyle="bold"
|
||||
android:gravity="center"
|
||||
android:textColor="#FFFFFF"
|
||||
android:text="Download" />
|
||||
android:text="@string/detail_download_btn" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="17dp"
|
||||
@@ -196,7 +196,7 @@
|
||||
android:textStyle="bold"
|
||||
android:gravity="center"
|
||||
android:textColor="#FFFFFF"
|
||||
android:text="Enabled" />
|
||||
android:text="@string/detail_enabled" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
77
app/src/main/res/layout/language_fragment.xml
Normal file
77
app/src/main/res/layout/language_fragment.xml
Normal 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>
|
||||
@@ -36,7 +36,7 @@
|
||||
android:layout_marginEnd="49dp"
|
||||
android:gravity="center"
|
||||
android:textStyle="bold"
|
||||
android:text="Consumption record"
|
||||
android:text="@string/consumption_title"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
@@ -58,7 +58,7 @@
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="My points"
|
||||
android:text="@string/shop_points"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="14sp"
|
||||
android:padding="20dp" />
|
||||
@@ -103,7 +103,7 @@
|
||||
android:textStyle="bold"
|
||||
android:gravity="center"
|
||||
android:textColor="#1B1F1A"
|
||||
android:text="Recharge" />
|
||||
android:text="@string/shop_recharge" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -127,7 +127,7 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Consumption Details"
|
||||
android:text="@string/consumption_details"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="14sp" />
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
android:layout_marginEnd="49dp"
|
||||
android:gravity="center"
|
||||
android:textStyle="bold"
|
||||
android:text="My keyboard"
|
||||
android:text="@string/keyboard_title"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
@@ -88,7 +88,7 @@
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:gravity="center"
|
||||
android:text="Save"
|
||||
android:text="@string/save"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="16sp"
|
||||
android:background="@drawable/my_keyboard_delete"
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:textStyle="bold"
|
||||
android:text="MySkin"
|
||||
android:text="@string/skin_title"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="16sp" />
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
android:layout_marginEnd="4dp"
|
||||
android:gravity="center"
|
||||
android:textStyle="bold"
|
||||
android:text="Editor"
|
||||
android:text="@string/skin_editor"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="13sp" />
|
||||
</LinearLayout>
|
||||
@@ -94,7 +94,7 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="0 themes selected"
|
||||
android:text="@string/skin_select"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"/>
|
||||
@@ -106,7 +106,7 @@
|
||||
android:gravity="center"
|
||||
android:paddingStart="14dp"
|
||||
android:paddingEnd="14dp"
|
||||
android:text="Delete"
|
||||
android:text="@string/delete"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textStyle="bold"
|
||||
android:background="@drawable/bg_delete_btn"/>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
android:layout_marginEnd="49dp"
|
||||
android:gravity="center"
|
||||
android:textStyle="bold"
|
||||
android:text="Notice"
|
||||
android:text="@string/mine_notice"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
@@ -67,15 +67,15 @@
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="Notifycation Setting"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:text="@string/notification_settings"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:layout_weight="1"
|
||||
android:textSize="20sp" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
@@ -91,4 +91,4 @@
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
android:layout_marginEnd="49dp"
|
||||
android:gravity="center"
|
||||
android:textStyle="bold"
|
||||
android:text="Settings"
|
||||
android:text="@string/personal_settings_title"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
@@ -109,7 +109,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="Nickname"
|
||||
android:text="@string/personal_settings_nickname"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:textSize="16sp" />
|
||||
@@ -153,7 +153,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="Gender"
|
||||
android:text="@string/personal_settings_gender"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:textSize="16sp" />
|
||||
@@ -197,7 +197,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="User ID"
|
||||
android:text="UID"
|
||||
android:textColor="#1B1F1A"
|
||||
android:textStyle="bold"
|
||||
android:textSize="16sp" />
|
||||
|
||||
@@ -19,7 +19,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Change the nickname"
|
||||
android:text="@string/personal_settings_nickname_input"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#1B1F1A"/>
|
||||
@@ -55,7 +55,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="45dp"
|
||||
android:gravity="center"
|
||||
android:text="Save"
|
||||
android:text="@string/save"
|
||||
android:textColor="#FFFFFF"
|
||||
android:background="@drawable/keyboard_ettings"/>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Modify gender"
|
||||
android:text="@string/personal_settings_gender_input"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#1B1F1A"/>
|
||||
@@ -70,7 +70,7 @@
|
||||
android:layout_height="45dp"
|
||||
android:layout_marginTop="43dp"
|
||||
android:gravity="center"
|
||||
android:text="Save"
|
||||
android:text="@string/save"
|
||||
android:textColor="#FFFFFF"
|
||||
android:background="@drawable/keyboard_ettings"/>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
android:id="@+id/shop_graph"
|
||||
android:icon="@drawable/ic_shop_selector"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/circle_graph"
|
||||
android:icon="@drawable/ic_circle_selector" />
|
||||
|
||||
<item
|
||||
android:id="@+id/mine_graph"
|
||||
android:icon="@drawable/ic_mine_selector" />
|
||||
|
||||
13
app/src/main/res/navigation/circle_graph.xml
Normal file
13
app/src/main/res/navigation/circle_graph.xml
Normal 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>
|
||||
@@ -114,6 +114,31 @@
|
||||
android:label="Notification"
|
||||
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
|
||||
android:id="@+id/action_global_consumptionRecordFragment"
|
||||
@@ -215,4 +240,4 @@
|
||||
app:popEnterAnim="@anim/fade_in_fast"
|
||||
app:popExitAnim="@anim/fade_out_fast" />
|
||||
|
||||
</navigation>
|
||||
</navigation>
|
||||
|
||||
@@ -42,6 +42,14 @@
|
||||
app:exitAnim="@anim/fade_out"
|
||||
app:popEnterAnim="@anim/fade_in_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>
|
||||
|
||||
<!-- 个人设置页面 -->
|
||||
@@ -69,4 +77,10 @@
|
||||
android:label="Notification"
|
||||
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>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<!-- 三个 Tab:独立 back stack -->
|
||||
<include app:graph="@navigation/home_graph" />
|
||||
<include app:graph="@navigation/shop_graph" />
|
||||
<include app:graph="@navigation/circle_graph" />
|
||||
<include app:graph="@navigation/mine_graph" />
|
||||
|
||||
</navigation>
|
||||
33
app/src/main/res/values-en-rUS/strings_i18n.xml
Normal file
33
app/src/main/res/values-en-rUS/strings_i18n.xml
Normal 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>
|
||||
@@ -2,4 +2,5 @@
|
||||
<resources>
|
||||
<color name="keyboard_button_bg">#707070</color>
|
||||
<color name="ai_keyboard_button_text_color">#FFFFFF</color>
|
||||
<color name="window_background">#F6F7FB</color>
|
||||
</resources>
|
||||
|
||||
9
app/src/main/res/values-v31/themes.xml
Normal file
9
app/src/main/res/values-v31/themes.xml
Normal 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>
|
||||
12
app/src/main/res/values-zh-rCN/language_config.xml
Normal file
12
app/src/main/res/values-zh-rCN/language_config.xml
Normal 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>
|
||||
4
app/src/main/res/values-zh-rCN/strings.xml
Normal file
4
app/src/main/res/values-zh-rCN/strings.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<resources>
|
||||
<string name="app_name">Key of Love</string>
|
||||
<!-- moved to strings_i18n.xml -->
|
||||
</resources>
|
||||
183
app/src/main/res/values-zh-rCN/strings_i18n.xml
Normal file
183
app/src/main/res/values-zh-rCN/strings_i18n.xml
Normal 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>
|
||||
@@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="purple_200">#FFBB86FC</color>
|
||||
<color name="purple_500">#FF6200EE</color>
|
||||
@@ -13,4 +12,13 @@
|
||||
<color name="gray_9F">#FF9F9F9F</color>
|
||||
<color name="keyboard_button_bg">#FFFFFFFF</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>
|
||||
|
||||
13
app/src/main/res/values/language_config.xml
Normal file
13
app/src/main/res/values/language_config.xml
Normal 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>
|
||||
@@ -17,11 +17,4 @@
|
||||
<string name="key_comma">,</string>
|
||||
<string name="key_period">.</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>
|
||||
|
||||
188
app/src/main/res/values/strings_i18n.xml
Normal file
188
app/src/main/res/values/strings_i18n.xml
Normal 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 "Copy any conversation", "Paste" 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>
|
||||
@@ -29,5 +29,21 @@
|
||||
<item name="android:windowBackground">#00000000</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
</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>
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
<item name="colorPrimaryVariant">@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 name="Theme.MyApp.Splash" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
|
||||
@@ -16,6 +16,7 @@ dependencyResolutionManagement {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven("https://jitpack.io")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user