From c1a80dd4cf2e0892494cc27eb32d36b4b29674aa Mon Sep 17 00:00:00 2001 From: pengxiaolong <15716207+pengxiaolong711@user.noreply.gitee.com> Date: Wed, 31 Dec 2025 18:36:55 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/myapplication/MainActivity.kt | 366 +++++++-- .../myapplication/MyInputMethodService.kt | 125 ++- .../myapplication/network/ApiService.kt | 29 + .../myapplication/network/AuthEventBus.kt | 4 + .../myapplication/network/HttpInterceptors.kt | 40 +- .../example/myapplication/network/Models.kt | 28 + .../example/myapplication/ui/EmptyFragment.kt | 16 + .../myapplication/ui/home/HomeFragment.kt | 570 +++++++------- .../ui/keyboard/KeyboardDetailFragment.kt | 4 + .../myapplication/ui/login/CodeEditText.kt | 43 + .../ui/login/ForgetPasswordEmailFragment.kt | 74 +- .../ui/login/ForgetPasswordResetFragment.kt | 116 +++ .../ui/login/ForgetPasswordVerifyFragment.kt | 55 +- .../myapplication/ui/login/LoginFragment.kt | 23 +- .../ui/login/RegisterFragment.kt | 136 +++- .../ui/login/RegisterVerifyFragment.kt | 175 +++++ .../myapplication/ui/mine/MineFragment.kt | 279 ++++--- .../myapplication/ui/shop/ShopEvent.kt | 20 + .../myapplication/ui/shop/ShopFragment.kt | 732 +++++++++--------- .../myapplication/ui/shop/ThemeCardAdapter.kt | 5 +- .../ui/shop/myskin/MySkinAdapter.kt | 5 +- app/src/main/res/drawable/ai_dialogue.png | Bin 3072 -> 28398 bytes app/src/main/res/drawable/chat_persona.png | Bin 2762 -> 23802 bytes app/src/main/res/drawable/circle.png | Bin 1324 -> 3180 bytes .../res/drawable/emotional_counseling.png | Bin 3054 -> 26572 bytes app/src/main/res/drawable/home.png | Bin 766 -> 1840 bytes .../main/res/drawable/ic_home_selector.xml | 13 + .../main/res/drawable/ic_mine_selector.xml | 13 + .../main/res/drawable/ic_shop_selector.xml | 13 + app/src/main/res/drawable/mine.png | Bin 1192 -> 2917 bytes .../res/drawable/personalized_keyboard.png | Bin 3726 -> 36841 bytes app/src/main/res/drawable/selected_circle.png | Bin 1557 -> 5327 bytes app/src/main/res/drawable/selected_home.png | Bin 1147 -> 3771 bytes app/src/main/res/drawable/selected_mine.png | Bin 1510 -> 5591 bytes app/src/main/res/drawable/selected_shop.png | Bin 1277 -> 4231 bytes app/src/main/res/drawable/shop.png | Bin 933 -> 2177 bytes app/src/main/res/layout/activity_main.xml | 29 +- app/src/main/res/layout/fragment_empty.xml | 5 + .../layout/fragment_forget_password_email.xml | 2 +- .../layout/fragment_forget_password_reset.xml | 6 +- .../fragment_forget_password_verify.xml | 13 +- app/src/main/res/layout/fragment_home.xml | 16 +- app/src/main/res/layout/fragment_register.xml | 12 +- .../res/layout/fragment_register_verify.xml | 120 +++ app/src/main/res/menu/menu_bottom_nav.xml | 21 +- app/src/main/res/navigation/global_graph.xml | 181 +++++ app/src/main/res/navigation/home_graph.xml | 14 + app/src/main/res/navigation/mine_graph.xml | 71 ++ app/src/main/res/navigation/nav_graph.xml | 286 +------ app/src/main/res/navigation/shop_graph.xml | 58 ++ app/src/main/res/values/styles.xml | 1 + 51 files changed, 2560 insertions(+), 1159 deletions(-) create mode 100644 app/src/main/java/com/example/myapplication/ui/EmptyFragment.kt create mode 100644 app/src/main/java/com/example/myapplication/ui/login/CodeEditText.kt create mode 100644 app/src/main/java/com/example/myapplication/ui/login/RegisterVerifyFragment.kt create mode 100644 app/src/main/java/com/example/myapplication/ui/shop/ShopEvent.kt create mode 100644 app/src/main/res/drawable/ic_home_selector.xml create mode 100644 app/src/main/res/drawable/ic_mine_selector.xml create mode 100644 app/src/main/res/drawable/ic_shop_selector.xml create mode 100644 app/src/main/res/layout/fragment_empty.xml create mode 100644 app/src/main/res/layout/fragment_register_verify.xml create mode 100644 app/src/main/res/navigation/global_graph.xml create mode 100644 app/src/main/res/navigation/home_graph.xml create mode 100644 app/src/main/res/navigation/mine_graph.xml create mode 100644 app/src/main/res/navigation/shop_graph.xml diff --git a/app/src/main/java/com/example/myapplication/MainActivity.kt b/app/src/main/java/com/example/myapplication/MainActivity.kt index 6d27984..9afd912 100644 --- a/app/src/main/java/com/example/myapplication/MainActivity.kt +++ b/app/src/main/java/com/example/myapplication/MainActivity.kt @@ -2,92 +2,354 @@ package com.example.myapplication import android.os.Bundle import android.view.View +import android.widget.Toast +import androidx.activity.OnBackPressedCallback import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope -import androidx.navigation.fragment.NavHostFragment -import androidx.navigation.ui.setupWithNavController -import com.google.android.material.bottomnavigation.BottomNavigationView import androidx.navigation.NavController -import androidx.navigation.NavDestination -import com.example.myapplication.network.AuthEventBus +import androidx.navigation.fragment.NavHostFragment import com.example.myapplication.network.AuthEvent +import com.example.myapplication.network.AuthEventBus +import com.example.myapplication.utils.EncryptedSharedPreferencesUtil +import com.google.android.material.bottomnavigation.BottomNavigationView import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch class MainActivity : AppCompatActivity() { private lateinit var bottomNav: BottomNavigationView - private lateinit var navController: NavController + + private val TAB_HOME = "tab_home" + private val TAB_SHOP = "tab_shop" + private val TAB_MINE = "tab_mine" + private val GLOBAL_HOST = "global_host" + + private var currentTabTag = TAB_HOME + private var pendingTabAfterLogin: String? = null + + private val protectedTabs = setOf( + R.id.shop_graph, + R.id.mine_graph + ) + + private val tabMap by lazy { + mapOf( + R.id.home_graph to TAB_HOME, + R.id.shop_graph to TAB_SHOP, + R.id.mine_graph to TAB_MINE + ) + } + + private lateinit var homeHost: NavHostFragment + private lateinit var shopHost: NavHostFragment + private lateinit var mineHost: NavHostFragment + private lateinit var globalHost: NavHostFragment + private var lastGlobalDestId: Int = R.id.globalEmptyFragment + + private val currentTabHost: NavHostFragment + get() = when (currentTabTag) { + TAB_SHOP -> shopHost + TAB_MINE -> mineHost + else -> homeHost + } + + private val currentTabNavController: NavController + get() = currentTabHost.navController + + private val globalNavController: NavController + get() = globalHost.navController override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + bottomNav = findViewById(R.id.bottom_nav) + bottomNav.itemIconTintList = null + bottomNav.setOnItemReselectedListener { /* ignore */ } + + // 1) 恢复当前tab + currentTabTag = savedInstanceState?.getString("current_tab_tag") ?: TAB_HOME + + // 2) 初始化/找回 3个Tab host + global host + initHosts() + + // 3) 底栏点击:show/hide 切 tab(带登录拦截 + 防 stateSaved) + bottomNav.setOnItemSelectedListener { item -> + val tabTag = tabMap[item.itemId] ?: return@setOnItemSelectedListener false + + // 登录拦截:未登录点受保护tab => 打开全局login + 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 + } + pendingTabAfterLogin = tabTag // 记录目标tab + openGlobal(R.id.loginFragment) + return@setOnItemSelectedListener false + } + + switchTab(tabTag) + true + } + + // 4) token过期:走全局 overlay,且避免重复打开 lifecycleScope.launch { AuthEventBus.events.collectLatest { event -> - if (event is AuthEvent.TokenExpired) { - val navController = (supportFragmentManager - .findFragmentById(R.id.nav_host_fragment) as NavHostFragment) - .navController - - // 避免重复跳转(比如已经在登录页) - if (navController.currentDestination?.id != R.id.loginFragment) { - navController.navigate(R.id.action_global_loginFragment) + when (event) { + is AuthEvent.TokenExpired -> { + pendingTabAfterLogin = null + // 已经在login就别重复 + if (!isGlobalVisible() || globalNavController.currentDestination?.id != R.id.loginFragment) { + openGlobal(R.id.loginFragment) + } + } + is AuthEvent.GenericError -> { + Toast.makeText(this@MainActivity, event.message, Toast.LENGTH_SHORT).show() + } + // 登录成功事件处理 + is AuthEvent.LoginSuccess -> { + // 关闭 global overlay:回到 empty + globalNavController.popBackStack(R.id.globalEmptyFragment, false) + + // 如果之前想去商城/我的,登录成功后自动切过去 + pendingTabAfterLogin?.let { tag -> + switchTab(tag) + bottomNav.selectedItemId = when (tag) { + TAB_SHOP -> R.id.shop_graph + TAB_MINE -> R.id.mine_graph + else -> R.id.home_graph + } + } + pendingTabAfterLogin = null + } + // 登出事件处理 + is AuthEvent.Logout -> { + pendingTabAfterLogin = event.returnTabTag + + // ✅ 用户没登录按返回,应回首页,所以先切到首页 + switchTab(TAB_HOME, force = true) + + bottomNav.post { + bottomNav.selectedItemId = R.id.home_graph + openGlobal(R.id.loginFragment) // ✅ 退出登录后立刻打开登录页 + } + } + // 打开全局页面事件处理 + is AuthEvent.OpenGlobalPage -> { + // 打开指定的全局页面 + openGlobal(event.destinationId, event.bundle) } - } else if (event is AuthEvent.GenericError) { - android.widget.Toast.makeText(this@MainActivity, "${event.message}", android.widget.Toast.LENGTH_SHORT).show() } } } - // 1. 找到 NavHostFragment - val navHostFragment = - supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment - navController = navHostFragment.navController + // 5) intent跳转(充值等)统一走全局 overlay + handleNavigationFromIntent() - // 2. 找到 BottomNavigationView - bottomNav = findViewById(R.id.bottom_nav) + // 6) 返回键规则:优先关闭global,其次pop当前tab + setupBackPress() - // 3. 绑定导航控制器(负责切换 Fragment、保持选中状态) - bottomNav.setupWithNavController(navController) - - // 4. 取消图标颜色 tint —— 使用原图标颜色 - bottomNav.itemIconTintList = null - - // 5. 添加导航监听(用于某些 Fragment 隐藏底部导航栏) - navController.addOnDestinationChangedListener { _, destination, _ -> - - // 只有这些页面显示 BottomNav - val pagesWithBottomNav = setOf( - R.id.mineFragment, - R.id.homeFragment, - R.id.shopFragment - ) - - if (destination.id in pagesWithBottomNav) { - bottomNav.visibility = View.VISIBLE - } else { - bottomNav.visibility = View.GONE + // 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 } } - + } - // 6. 检查是否有导航参数,处理从键盘跳转过来的请求 - handleNavigationFromIntent() + private fun initHosts() { + val fm = supportFragmentManager + + homeHost = fm.findFragmentByTag(TAB_HOME) as? NavHostFragment + ?: NavHostFragment.create(R.navigation.home_graph) + shopHost = fm.findFragmentByTag(TAB_SHOP) as? NavHostFragment + ?: NavHostFragment.create(R.navigation.shop_graph) + mineHost = fm.findFragmentByTag(TAB_MINE) as? NavHostFragment + ?: NavHostFragment.create(R.navigation.mine_graph) + + globalHost = fm.findFragmentByTag(GLOBAL_HOST) as? NavHostFragment + ?: NavHostFragment.create(R.navigation.global_graph) + + // 第一次创建时 add;后续进程重建会自动恢复,无需重复 add + if (fm.findFragmentByTag(TAB_HOME) == null) { + fm.beginTransaction() + .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, mineHost, TAB_MINE).hide(mineHost) + .commitNow() + } + + if (fm.findFragmentByTag(GLOBAL_HOST) == null) { + fm.beginTransaction() + .setReorderingAllowed(true) + .add(R.id.global_container, globalHost, GLOBAL_HOST) + .commitNow() + } + + // 确保当前tab可见 + switchTab(currentTabTag, force = true) + + // 绑定全局导航可见性监听 + bindGlobalVisibility() + + // 绑定底部导航栏可见性监听 + bindBottomNavVisibilityForTabs() + } + + private fun bindGlobalVisibility() { + globalNavController.addOnDestinationChangedListener { _, dest, _ -> + val isEmpty = dest.id == R.id.globalEmptyFragment + + findViewById(R.id.global_container).visibility = + if (isEmpty) View.GONE else View.VISIBLE + bottomNav.visibility = + if (isEmpty) View.VISIBLE else View.GONE + + // ✅ 只在"刚从某个全局页关闭回 empty"时触发回退逻辑 + val justClosedOverlay = (dest.id == R.id.globalEmptyFragment && lastGlobalDestId != R.id.globalEmptyFragment) + lastGlobalDestId = dest.id + + if (justClosedOverlay) { + val currentTabGraphId = when (currentTabTag) { + TAB_SHOP -> R.id.shop_graph + TAB_MINE -> R.id.mine_graph + else -> R.id.home_graph + } + // 未登录且当前处在受保护tab:强制回首页 + if (!isLoggedIn() && currentTabGraphId in protectedTabs) { + switchTab(TAB_HOME, force = true) + bottomNav.selectedItemId = R.id.home_graph + } + + // ✅ 只有"没登录就关闭登录页"才清 pending + if (!isLoggedIn()) { + pendingTabAfterLogin = null + } + } + } + } + + private fun switchTab(targetTag: String, force: Boolean = false) { + if (!force && targetTag == currentTabTag) return + + val fm = supportFragmentManager + if (fm.isStateSaved) return // ✅ 防崩:stateSaved 时不做事务 + + currentTabTag = targetTag + + fm.beginTransaction() + .setReorderingAllowed(true) + .hide(homeHost) + .hide(shopHost) + .hide(mineHost) + .also { ft -> + when (targetTag) { + TAB_SHOP -> ft.show(shopHost) + TAB_MINE -> ft.show(mineHost) + else -> ft.show(homeHost) + } + } + .commit() + } + + /** 打开全局页(login/recharge等) */ + private fun openGlobal(destId: Int, bundle: Bundle? = null) { + val fm = supportFragmentManager + if (fm.isStateSaved) return // ✅ 防崩 + + try { + if (bundle != null) { + globalNavController.navigate(destId, bundle) + } else { + globalNavController.navigate(destId) + } + } catch (e: IllegalArgumentException) { + // 可选:防止偶发重复 navigate 崩溃 + e.printStackTrace() + } + } + + /** 关闭全局页:pop到 empty */ + private fun bindBottomNavVisibilityForTabs() { + fun shouldHideBottomNav(destId: Int): Boolean { + return destId in setOf( + R.id.searchFragment, + R.id.searchResultFragment, + R.id.MySkin + // 你还有其他需要全屏的页,也加在这里 + ) + } + + val listener = NavController.OnDestinationChangedListener { _, dest, _ -> + // 只要 global overlay 打开了,仍然以 overlay 为准(你已有逻辑) + if (isGlobalVisible()) return@OnDestinationChangedListener + bottomNav.visibility = if (shouldHideBottomNav(dest.id)) View.GONE else View.VISIBLE + } + + homeHost.navController.addOnDestinationChangedListener(listener) + shopHost.navController.addOnDestinationChangedListener(listener) + mineHost.navController.addOnDestinationChangedListener(listener) + } + + private fun closeGlobalIfPossible(): Boolean { + if (!isGlobalVisible()) return false + + val popped = globalNavController.popBackStack() + val stillVisible = globalNavController.currentDestination?.id != R.id.globalEmptyFragment + return popped || stillVisible + } + + private fun isGlobalVisible(): Boolean { + return findViewById(R.id.global_container).visibility == View.VISIBLE + } + + private fun setupBackPress() { + onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + // 1) 优先关 global + if (closeGlobalIfPossible()) return + + // 2) 再 pop 当前tab + val popped = currentTabNavController.popBackStack() + if (popped) return + + // 3) 当前tab到根了:如果不是home,切回home;否则退出 + if (currentTabTag != TAB_HOME) { + bottomNav.post { + bottomNav.selectedItemId = R.id.home_graph + } + switchTab(TAB_HOME) + } else { + finish() + } + } + }) } private fun handleNavigationFromIntent() { val navigateTo = intent.getStringExtra("navigate_to") if (navigateTo == "recharge_fragment") { - // 延迟执行导航,确保导航控制器已经准备好 bottomNav.post { - try { - navController.navigate(R.id.action_global_rechargeFragment) - } catch (e: Exception) { - // 如果导航失败,记录错误日志 - android.util.Log.e("MainActivity", "Failed to navigate to recharge fragment", e) + if (!isLoggedIn()) { + openGlobal(R.id.loginFragment) + return@post } + openGlobal(R.id.rechargeFragment) } } } -} + + private fun isLoggedIn(): Boolean { + return EncryptedSharedPreferencesUtil.contains(this, "user") + } + + override fun onSaveInstanceState(outState: Bundle) { + outState.putString("current_tab_tag", currentTabTag) + super.onSaveInstanceState(outState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/MyInputMethodService.kt b/app/src/main/java/com/example/myapplication/MyInputMethodService.kt index 05781d7..6530edb 100644 --- a/app/src/main/java/com/example/myapplication/MyInputMethodService.kt +++ b/app/src/main/java/com/example/myapplication/MyInputMethodService.kt @@ -44,7 +44,8 @@ import android.content.Intent import android.view.inputmethod.ExtractedTextRequest import android.graphics.drawable.GradientDrawable import kotlin.math.abs - +import java.text.BreakIterator +import android.widget.EditText class MyInputMethodService : InputMethodService(), KeyboardEnvironment { @@ -85,6 +86,10 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment { private const val TAG = "MyIME" private const val NOTIFICATION_CHANNEL_ID = "input_method_channel" private const val NOTIFICATION_ID = 1 + + private const val ZWJ = 0x200D // ZERO WIDTH JOINER + private const val VS16 = 0xFE0F // VARIATION SELECTOR-16 (emoji) + private const val VS15 = 0xFE0E // VARIATION SELECTOR-15 (text) } // ================= 表情 ================= private var emojiKeyboardView: View? = null @@ -604,6 +609,7 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment { } override fun showMainKeyboard() { + clearEditorState() val kb = ensureMainKeyboard() currentKeyboardView = kb.rootView setInputView(kb.rootView) @@ -611,6 +617,7 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment { } override fun showNumberKeyboard() { + clearEditorState() val kb = ensureNumberKeyboard() currentKeyboardView = kb.rootView setInputView(kb.rootView) @@ -618,6 +625,7 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment { } override fun showSymbolKeyboard() { + clearEditorState() val kb = ensureSymbolKeyboard() currentKeyboardView = kb.rootView setInputView(kb.rootView) @@ -625,6 +633,7 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment { } override fun showAiKeyboard() { + clearEditorState() val kb = ensureAiKeyboard() currentKeyboardView = kb.rootView setInputView(kb.rootView) @@ -632,6 +641,7 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment { } override fun showEmojiKeyboard() { + clearEditorState() val kb = ensureEmojiKeyboard() currentKeyboardView = kb.rootView setInputView(kb.rootView) @@ -704,24 +714,94 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment { playKeyClick() } - // 删除一个字符(原 handleBackspace) + // 删除 override fun deleteOne() { val ic = currentInputConnection ?: return - // 删除时少做 IPC:selectedText 也可能慢,所以只在需要时取 + // 记录删除前的极小上下文,用来判断“是否真的删掉了东西” + // 不要取多,避免开销 + val before1_pre = ic.getTextBeforeCursor(1, 0)?.toString().orEmpty() + val after1_pre = ic.getTextAfterCursor(1, 0)?.toString().orEmpty() + + // 1) 先处理选区:和你原来一致 val selected = ic.getSelectedText(0) if (!selected.isNullOrEmpty()) { - // 删选区 ic.commitText("", 1) - } else { - // 删光标前一个字符(更同步) - ic.deleteSurroundingText(1, 0) + scheduleRefreshSuggestions() + playKeyClick() + return } - scheduleRefreshSuggestions() + // 2) 无选区:优先按 code point 删除(解决“Emoji 要删两下”) + val deletedByCodePoint = try { + ic.deleteSurroundingTextInCodePoints(1, 0) + true + } catch (_: Throwable) { + false + } + + if (!deletedByCodePoint) { + // 兼容兜底(老实现) + ic.deleteSurroundingText(1, 0) + } else { + // 3) 兜底清理:处理 ZWJ/变体选择符/组合符,保证“一个可见 Emoji 一次删干净” + val before = ic.getTextBeforeCursor(32, 0)?.toString().orEmpty() + if (before.isNotEmpty()) { + var s = before + var extra = 0 + + fun endsWithJoinerOrVariationOrMark(str: String): Boolean { + if (str.isEmpty()) return false + val cp = Character.codePointBefore(str, str.length) + return cp == ZWJ || + cp == VS16 || + cp == VS15 || + Character.getType(cp) == Character.NON_SPACING_MARK.toInt() || + Character.getType(cp) == Character.COMBINING_SPACING_MARK.toInt() || + Character.getType(cp) == Character.ENCLOSING_MARK.toInt() + } + + while (s.isNotEmpty() && extra < 8 && endsWithJoinerOrVariationOrMark(s)) { + try { + ic.deleteSurroundingTextInCodePoints(1, 0) + } catch (_: Throwable) { + ic.deleteSurroundingText(1, 0) + break + } + extra++ + s = ic.getTextBeforeCursor(32, 0)?.toString().orEmpty() + } + + if (s.isNotEmpty() && Character.codePointBefore(s, s.length) == ZWJ) { + try { + ic.deleteSurroundingTextInCodePoints(1, 0) + } catch (_: Throwable) { + ic.deleteSurroundingText(1, 0) + } + } + } + } + + // ==== 关键:判断“删完后是否真的发生变化” ==== + val before1_post = ic.getTextBeforeCursor(1, 0)?.toString().orEmpty() + val after1_post = ic.getTextAfterCursor(1, 0)?.toString().orEmpty() + + val changed = (before1_pre != before1_post) || (after1_pre != after1_post) + + if (!changed) { + // ✅ 删不动(常见于验证码空格子继续按删除) + // 补发一个 KEYCODE_DEL,让宿主 EditText 的 OnKeyListener 能收到,执行“跳到前一格并删” + ic.sendKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)) + ic.sendKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL)) + } else { + // 只有真的改动了文本,才刷新联想(避免空删触发刷新抖动) + scheduleRefreshSuggestions() + } playKeyClick() } + + private fun refreshSuggestionsAfterEdit() { val ic = currentInputConnection ?: return @@ -1061,6 +1141,35 @@ class MyInputMethodService : InputMethodService(), KeyboardEnvironment { } } + private fun deleteOneGrapheme(editText: EditText) { + val text = editText.text ?: return + + // 优先删选中内容(和系统行为一致) + val startSel = editText.selectionStart + val endSel = editText.selectionEnd + if (startSel != -1 && endSel != -1 && startSel != endSel) { + val s = minOf(startSel, endSel) + val e = maxOf(startSel, endSel) + text.delete(s, e) + editText.setSelection(s) + return + } + + val cursor = startSel + if (cursor <= 0) return + + val s = text.toString() + + // 找到 cursor 前一个“字符边界” + val it = BreakIterator.getCharacterInstance() + it.setText(s) + + val prev = it.preceding(cursor) + if (prev != BreakIterator.DONE && prev >= 0 && prev < cursor) { + text.delete(prev, cursor) + editText.setSelection(prev) + } + } private fun stopRepeatDelete() { diff --git a/app/src/main/java/com/example/myapplication/network/ApiService.kt b/app/src/main/java/com/example/myapplication/network/ApiService.kt index 72993bb..03895e1 100644 --- a/app/src/main/java/com/example/myapplication/network/ApiService.kt +++ b/app/src/main/java/com/example/myapplication/network/ApiService.kt @@ -26,6 +26,35 @@ interface ApiService { @Body body: LoginRequest ): ApiResponse + //退出登录 + @GET("user/logout") + suspend fun logout( + ): ApiResponse + + //发送验证嘛 + @POST("user/sendVerifyMail") + suspend fun sendVerifyCode( + @Body body: SendVerifyCodeRequest + ): ApiResponse + + //注册 + @POST("user/register") + suspend fun register( + @Body body: RegisterRequest + ): ApiResponse + + //验证验证码 + @POST("user/verifyMailCode") + suspend fun verifyCode( + @Body body: VerifyCodeRequest + ): ApiResponse + + //重置密码 + @POST("user/resetPassWord") + suspend fun resetPassword( + @Body body: ResetPasswordRequest + ): ApiResponse + // =========================================用户================================= //获取用户详情 @GET("user/detail") diff --git a/app/src/main/java/com/example/myapplication/network/AuthEventBus.kt b/app/src/main/java/com/example/myapplication/network/AuthEventBus.kt index 4e1fdbb..d051603 100644 --- a/app/src/main/java/com/example/myapplication/network/AuthEventBus.kt +++ b/app/src/main/java/com/example/myapplication/network/AuthEventBus.kt @@ -1,5 +1,6 @@ package com.example.myapplication.network +import android.os.Bundle import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow @@ -21,4 +22,7 @@ object AuthEventBus { sealed class AuthEvent { data class TokenExpired(val message: String? = null) : 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() } diff --git a/app/src/main/java/com/example/myapplication/network/HttpInterceptors.kt b/app/src/main/java/com/example/myapplication/network/HttpInterceptors.kt index 62b3cf5..8e88907 100644 --- a/app/src/main/java/com/example/myapplication/network/HttpInterceptors.kt +++ b/app/src/main/java/com/example/myapplication/network/HttpInterceptors.kt @@ -3,12 +3,32 @@ package com.example.myapplication.network import android.util.Log import com.google.gson.Gson +import okhttp3.HttpUrl import okhttp3.Interceptor import okhttp3.Response import okhttp3.ResponseBody.Companion.toResponseBody import com.example.myapplication.utils.EncryptedSharedPreferencesUtil import android.content.Context + +// * 不需要登录的接口路径(相对完整路径) +// * 只写 /api/ 后面的部分 +// * 例如真实 URL: https://xxx.com/api/home/banner +// * 这里写: /home/banner +private val NO_LOGIN_REQUIRED_PATHS = setOf( + "/themes/listByStyle", + "/wallet/balance", +) + +private fun noLoginRequired(url: HttpUrl): Boolean { + val path = url.encodedPath // 例:/api/home/banner + + // 统一裁掉 /api 前缀 + val apiPath = path.substringAfter("/api", path) + + return NO_LOGIN_REQUIRED_PATHS.contains(apiPath) +} + /** * 请求拦截器:统一加 Header、token 等 */ @@ -102,14 +122,24 @@ val responseInterceptor = Interceptor { chain -> val errorResponse = gson.fromJson(bodyString, ErrorResponse::class.java) if (errorResponse.code == 40102) { - Log.w("1314520-HTTP", "token 过期: ${errorResponse.message}") + val isNoLoginApi = noLoginRequired(request.url) + + Log.w( + "1314520-HTTP", + "40102 path=${request.url.encodedPath}, noLogin=$isNoLoginApi" + ) + + // ✅ 只有"需要登录"的接口,才触发全局跳转 + if (!isNoLoginApi) { + AuthEventBus.emit(AuthEvent.TokenExpired(errorResponse.message)) + } - // 只发事件,UI 层去跳转 - AuthEventBus.emit(AuthEvent.TokenExpired(errorResponse.message)) - return@Interceptor response.newBuilder() .code(401) - .message("Login expired: ${errorResponse.message}") + .message( + if (isNoLoginApi) response.message + else "Login required: ${errorResponse.message}" + ) .body(bodyString.toResponseBody(mediaType)) .build() } diff --git a/app/src/main/java/com/example/myapplication/network/Models.kt b/app/src/main/java/com/example/myapplication/network/Models.kt index 52b9e08..1c2a916 100644 --- a/app/src/main/java/com/example/myapplication/network/Models.kt +++ b/app/src/main/java/com/example/myapplication/network/Models.kt @@ -33,6 +33,34 @@ data class LoginResponse( val token: String ) +//验证码发送邮箱 +data class SendVerifyCodeRequest( + val mailAddress: String +) + +//注册 +data class RegisterRequest( + val mailAddress: String, + val password: String, + val passwordConfirm: String, + val gender: Int?, + val verifyCode: String, + val inviteCode: String? +) + +//验证验证码 +data class VerifyCodeRequest( + val mailAddress: String, + val verifyCode: String, +) + +//重置密码 +data class ResetPasswordRequest( + val mailAddress: String, + val password: String, + val confirmPassword: String +) + // ======================================用户=================================== //获取用户详情 data class User( diff --git a/app/src/main/java/com/example/myapplication/ui/EmptyFragment.kt b/app/src/main/java/com/example/myapplication/ui/EmptyFragment.kt new file mode 100644 index 0000000..40b9284 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/ui/EmptyFragment.kt @@ -0,0 +1,16 @@ +package com.example.myapplication.ui + +import android.os.Bundle +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.example.myapplication.R + +class EmptyFragment : Fragment(R.layout.fragment_empty) { + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + // 设置透明背景,确保不遮挡底层内容 + view.setBackgroundResource(android.R.color.transparent) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/ui/home/HomeFragment.kt b/app/src/main/java/com/example/myapplication/ui/home/HomeFragment.kt index 09415f4..6de4209 100644 --- a/app/src/main/java/com/example/myapplication/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/example/myapplication/ui/home/HomeFragment.kt @@ -15,27 +15,24 @@ import android.widget.LinearLayout import android.widget.TextView import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.content.ContextCompat -import androidx.core.widget.NestedScrollView import androidx.core.view.isVisible import androidx.fragment.app.Fragment +import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.GridLayoutManager -import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 import com.example.myapplication.ImeGuideActivity import com.example.myapplication.R -import com.example.myapplication.network.ApiResponse -import com.example.myapplication.network.RetrofitClient -import com.example.myapplication.network.listByTagWithNotLogin -import com.example.myapplication.network.PersonaClick +import com.example.myapplication.network.* import com.example.myapplication.utils.EncryptedSharedPreferencesUtil import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.card.MaterialCardView +import kotlinx.coroutines.Job import kotlinx.coroutines.launch import kotlin.math.abs -import com.example.myapplication.network.AddPersonaClick class HomeFragment : Fragment() { @@ -49,21 +46,17 @@ class HomeFragment : Fragment() { private lateinit var tabList1: TextView private lateinit var tabList2: TextView private lateinit var backgroundImage: ImageView - private var preloadJob: kotlinx.coroutines.Job? = null + private var lastList1RenderKey: String? = null + + private var preloadJob: Job? = null private var allPersonaCache: List = emptyList() - private val sharedPool = RecyclerView.RecycledViewPool() + private val personaCache = mutableMapOf>() private var parentWidth = 0 private var parentHeight = 0 - - // 你点了哪个 tag(列表二) private var clickedTagId: Int? = null - // ✅ 列表二:每个 tagId 对应一份 persona 数据,避免串页 - private val personaCache = mutableMapOf>() - data class Tag(val id: Int, val tagName: String) - private val tags = mutableListOf() private val dragToCloseThreshold by lazy { @@ -71,11 +64,9 @@ class HomeFragment : Fragment() { (dp * resources.displayMetrics.density) } - private val list1Adapter: List1Adapter by lazy { - List1Adapter { item: String -> - Log.d("HomeFragment", "list1 click: $item") - } - } + // ---------------- ViewPager2 + Tabs ---------------- + private var sheetAdapter: SheetPagerAdapter? = null + private var pageChangeCallback: ViewPager2.OnPageChangeCallback? = null override fun onDestroyView() { preloadJob?.cancel() @@ -89,23 +80,56 @@ class HomeFragment : Fragment() { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - return inflater.inflate(R.layout.fragment_home, container, false) - } + ): View? = inflater.inflate(R.layout.fragment_home, container, false) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - // 充值按钮点击 + viewLifecycleOwner.lifecycleScope.launch { + viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { + AuthEventBus.events.collect { event -> + when (event) { + AuthEvent.LoginSuccess -> { + // 1) 清掉未登录缓存 + preloadJob?.cancel() + personaCache.clear() + allPersonaCache = emptyList() + lastList1RenderKey = null + + // 2) 重新拉列表1(登录态接口会变) + viewLifecycleOwner.lifecycleScope.launch { + allPersonaCache = fetchAllPersonaList() + notifyPageChangedOnMain(0) + } + + // 3) 如果当前在某个 tag 页,也建议重新拉当前页数据 + val pos = viewPager.currentItem + if (pos > 0) { + val tagId = tags.getOrNull(pos - 1)?.id + if (tagId != null) { + viewLifecycleOwner.lifecycleScope.launch { + personaCache[tagId] = fetchPersonaByTag(tagId) + notifyPageChangedOnMain(pos) + } + } + } + } + else -> Unit + } + } + } + } + + + // 充值按钮点击 - 使用事件总线打开全局页面 view.findViewById(R.id.rechargeButton).setOnClickListener { - findNavController().navigate(R.id.action_global_rechargeFragment) + AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.rechargeFragment)) } // 输入法激活跳转 view.findViewById(R.id.floatingImage).setOnClickListener { - if (isAdded) { - startActivity(Intent(requireActivity(), ImeGuideActivity::class.java)) - } + if (!isAdded) return@setOnClickListener + startActivity(Intent(requireActivity(), ImeGuideActivity::class.java)) } scrim = view.findViewById(R.id.view_scrim) @@ -117,11 +141,14 @@ class HomeFragment : Fragment() { tabList2 = view.findViewById(R.id.tab_list2) viewPager = view.findViewById(R.id.viewPager) viewPager.isSaveEnabled = false + viewPager.offscreenPageLimit = 2 backgroundImage = bottomSheet.findViewById(R.id.backgroundImage) + val root = view.findViewById(R.id.rootCoordinator) val floatingImage = view.findViewById(R.id.floatingImage) root.post { + if (!isAdded) return@post parentWidth = root.width parentHeight = root.height } @@ -130,43 +157,96 @@ class HomeFragment : Fragment() { setupBottomSheet(view) setupTopTabs() - // 先把 ViewPager / Tags 初始化为空(避免你下面网络回来前被调用多次) - setupViewPager() + // ✅ setupViewPager 只初始化一次 + setupViewPagerOnce() + + // 标签 UI 初始为空 setupTags() - //刚进来强制显示列表1 + // 默认显示列表1 viewPager.setCurrentItem(0, false) updateTabsAndTags(0) - // 加载标签列表(列表一) + // 加载列表一 viewLifecycleOwner.lifecycleScope.launch { try { val list = fetchAllPersonaList() + if (!isAdded) return@launch allPersonaCache = list - viewPager.adapter?.notifyItemChanged(0) // 只刷新第一页 + + // ✅ 关键:数据变了就清 renderKey,允许重建一次 UI + lastList1RenderKey = null + + notifyPageChangedOnMain(0) } catch (e: Exception) { Log.e("1314520-HomeFragment", "获取列表一失败", e) } } - // 拉标签 + 默认加载第一个 tag 的 persona(列表二第一个页) + + // 拉标签 + 预加载 viewLifecycleOwner.lifecycleScope.launch { try { val response = RetrofitClient.apiService.tagList() + if (!isAdded) return@launch + tags.clear() response.data?.let { networkTags -> tags.addAll(networkTags.map { Tag(it.id, it.tagName) }) } - // 刷新:页数和标签栏 - setupViewPager() + + // ✅ 只更新页数(不重建 adapter/callback) + sheetAdapter?.updatePageCount(1 + tags.size) + + // 重新画 tags setupTags() - startPreloadAllTags() + + // ✅ 预加载只填缓存,不刷 UI + startPreloadAllTagsFillCacheOnly() } catch (e: Exception) { Log.e("1314520-HomeFragment", "获取标签失败", e) } } } + // ================== 你要求的核心优化:setupViewPager 只初始化一次 ================== + + private fun setupViewPagerOnce() { + if (sheetAdapter != null) return + + sheetAdapter = SheetPagerAdapter(1 + tags.size) + viewPager.adapter = sheetAdapter + + // ✅ 禁止 itemAnimator(减少 layout 抖动) + (viewPager.getChildAt(0) as? RecyclerView)?.itemAnimator = null + + pageChangeCallback = object : ViewPager2.OnPageChangeCallback() { + override fun onPageSelected(position: Int) { + if (!isAdded) return + updateTabsAndTags(position) + + // ✅ 修复:当切换到标签页且缓存已有数据时,强制刷新UI + if (position > 0) { + val tagIndex = position - 1 + val tagId = tags.getOrNull(tagIndex)?.id + if (tagId != null && personaCache.containsKey(tagId)) { + notifyPageChangedOnMain(position) + } + } + } + } + viewPager.registerOnPageChangeCallback(pageChangeCallback!!) + } + + // ✅ 统一:确保 notifyItemChanged 只在主线程 + private fun notifyPageChangedOnMain(position: Int) { + viewPager.post { + if (!isAdded) return@post + viewPager.adapter?.notifyItemChanged(position) + } + } + // ---------------- 拖拽效果 ---------------- + private fun initDrag(target: View, parent: ViewGroup) { var dX = 0f var dY = 0f @@ -245,6 +325,7 @@ class HomeFragment : Fragment() { } // ---------------- BottomSheet 行为 ---------------- + private fun setupBottomSheet(root: View) { bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet) @@ -254,6 +335,7 @@ class HomeFragment : Fragment() { bottomSheetBehavior.halfExpandedRatio = 0.7f root.post { + if (!isAdded) return@post val coordinatorHeight = root.height - 40 val button = root.findViewById(R.id.rechargeButton) val peek = (coordinatorHeight - button.bottom).coerceAtLeast(200) @@ -296,69 +378,17 @@ class HomeFragment : Fragment() { } } - // ---------------- ViewPager2 + Tabs ---------------- - private var sheetAdapter: SheetPagerAdapter? = null - private var pageChangeCallback: ViewPager2.OnPageChangeCallback? = null - - private fun setupViewPager() { - if (sheetAdapter == null) { - sheetAdapter = SheetPagerAdapter(1 + tags.size) - viewPager.adapter = sheetAdapter - - pageChangeCallback = object : ViewPager2.OnPageChangeCallback() { - override fun onPageSelected(position: Int) { - updateTabsAndTags(position) - } - } - viewPager.registerOnPageChangeCallback(pageChangeCallback!!) - } else { - // tags 数量变了,只更新 pageCount 并刷新一次即可 - sheetAdapter!!.updatePageCount(1 + tags.size) - } - } - - - private fun startPreloadAllTags() { - preloadJob?.cancel() - - // 限制并发,避免一下子打爆网络/主线程调度抖动 - val semaphore = kotlinx.coroutines.sync.Semaphore(permits = 2) - - preloadJob = viewLifecycleOwner.lifecycleScope.launch { - // tags 还没拿到就别跑 - if (tags.isEmpty()) return@launch - - // 逐个 tag 预拉取(并发=2) - tags.forEachIndexed { index, tag -> - // 已经有缓存就跳过 - if (personaCache.containsKey(tag.id)) return@forEachIndexed - launch { - semaphore.acquire() - try { - val list = fetchPersonaByTag(tag.id) - personaCache[tag.id] = list - - val pagePos = 1 + index - kotlinx.coroutines.withContext(kotlinx.coroutines.Dispatchers.Main) { - viewPager.adapter?.notifyItemChanged(pagePos) - } - } finally { - semaphore.release() - } - } - } - } - } - + // ---------------- Tabs ---------------- private fun setupTopTabs() { tabList1.setOnClickListener { viewPager.currentItem = 0 } tabList2.setOnClickListener { - // 没有标签就别切 if (tags.isNotEmpty()) viewPager.currentItem = 1 } } + // ---------------- Tags ---------------- + private fun setupTags() { tagContainer.removeAllViews() @@ -369,28 +399,26 @@ class HomeFragment : Fragment() { tv.setOnClickListener { clickedTagId = tag.id val pagePos = 1 + index - - // ✅ 先切页:用户体感立刻响应 + + // 先切页:响应快 viewPager.setCurrentItem(pagePos, true) - - // ✅ 有缓存就不阻塞(可选:同时后台刷新) + + // ✅ Tag 切换不触发多余 notify: + // 1) 有缓存:不 notify(onBind 会直接显示缓存) val cached = personaCache[tag.id] - if (cached != null) { - viewPager.adapter?.notifyItemChanged(pagePos) - return@setOnClickListener - } - - // ✅ 没缓存:页内显示 loading(你 onBind 已经处理 cached==null 的 loading) - viewPager.adapter?.notifyItemChanged(pagePos) - - // 后台拉取,回来只刷新这一页 + if (cached != null) return@setOnClickListener + + // 2) 没缓存:只 notify 一次,让页显示 loading + notifyPageChangedOnMain(pagePos) + + // 后台拉取,回来再 notify 一次 viewLifecycleOwner.lifecycleScope.launch { val list = fetchPersonaByTag(tag.id) + if (!isAdded) return@launch personaCache[tag.id] = list - viewPager.adapter?.notifyItemChanged(pagePos) // ✅ 只刷新这一页 + notifyPageChangedOnMain(pagePos) } } - tagContainer.addView(tv) } @@ -399,14 +427,16 @@ class HomeFragment : Fragment() { } private fun updateTabsAndTags(position: Int) { + val ctx = context ?: return + if (position == 0) { - tabList1.setTextColor(requireContext().getColor(R.color.black)) - tabList2.setTextColor(requireContext().getColor(R.color.light_black)) + tabList1.setTextColor(ctx.getColor(R.color.black)) + tabList2.setTextColor(ctx.getColor(R.color.light_black)) tagScroll.isVisible = false fadeImage(backgroundImage, R.drawable.option_background) } else { - tabList1.setTextColor(requireContext().getColor(R.color.light_black)) - tabList2.setTextColor(requireContext().getColor(R.color.black)) + tabList1.setTextColor(ctx.getColor(R.color.light_black)) + tabList2.setTextColor(ctx.getColor(R.color.black)) tagScroll.isVisible = true fadeImage(backgroundImage, R.drawable.option_background_two) @@ -416,8 +446,9 @@ class HomeFragment : Fragment() { } private fun fadeImage(imageView: ImageView, newImageRes: Int) { + val ctx = context ?: return val oldDrawable = imageView.drawable - val newDrawable = ContextCompat.getDrawable(requireContext(), newImageRes) ?: return + val newDrawable = ContextCompat.getDrawable(ctx, newImageRes) ?: return if (oldDrawable == null) { imageView.setImageDrawable(newDrawable) @@ -430,14 +461,17 @@ class HomeFragment : Fragment() { imageView.setImageDrawable(transitionDrawable) transitionDrawable.startTransition(300) } - + private fun highlightTag(index: Int) { + val ctx = context ?: return + for (i in 0 until tagContainer.childCount) { val child = tagContainer.getChildAt(i) as TextView if (i == index) { child.setBackgroundResource(R.drawable.tag_selected_bg) - child.setTextColor(requireContext().getColor(android.R.color.white)) + child.setTextColor(ctx.getColor(android.R.color.white)) tagScroll.post { + if (!isAdded) return@post val scrollViewWidth = tagScroll.width val childCenter = child.left + child.width / 2 val targetScrollX = childCenter - scrollViewWidth / 2 @@ -445,25 +479,71 @@ class HomeFragment : Fragment() { } } else { child.setBackgroundResource(R.drawable.tag_unselected_bg) - child.setTextColor(requireContext().getColor(R.color.light_black)) + child.setTextColor(ctx.getColor(R.color.light_black)) } } } + // ---------------- 预加载:只填缓存,不刷新 UI ---------------- + + private fun startPreloadAllTagsFillCacheOnly() { + preloadJob?.cancel() + + val semaphore = kotlinx.coroutines.sync.Semaphore(permits = 2) + + preloadJob = viewLifecycleOwner.lifecycleScope.launch { + if (tags.isEmpty()) return@launch + + tags.forEach { tag -> + if (personaCache.containsKey(tag.id)) return@forEach + + launch { + semaphore.acquire() + try { + val list = fetchPersonaByTag(tag.id) + personaCache[tag.id] = list + + // ✅ 只在用户正在看的页时刷新一次(不算乱刷 UI) + val idx = tags.indexOfFirst { it.id == tag.id } + val thisPos = 1 + idx + if (idx >= 0 && viewPager.currentItem == thisPos) { + notifyPageChangedOnMain(thisPos) + } + + } catch (e: Exception) { + Log.e("HomeFragment", "preload tag=${tag.id} fail", e) + } finally { + semaphore.release() + } + } + } + } + } + + // ---------------- ViewPager Adapter ---------------- + inner class SheetPagerAdapter( private var pageCount: Int ) : RecyclerView.Adapter() { - + inner class PageViewHolder(val root: View) : RecyclerView.ViewHolder(root) - + fun updatePageCount(newCount: Int) { + if (newCount == pageCount) return + + val old = pageCount pageCount = newCount - notifyDataSetChanged() + + if (newCount > old) { + notifyItemRangeInserted(old, newCount - old) + } else { + notifyItemRangeRemoved(newCount, old - newCount) + } } - + override fun getItemViewType(position: Int): Int = if (position == 0) 0 else 1 - + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PageViewHolder { val layoutId = if (viewType == 0) { R.layout.bottom_page_list1 @@ -473,42 +553,50 @@ class HomeFragment : Fragment() { val root = LayoutInflater.from(parent.context).inflate(layoutId, parent, false) return PageViewHolder(root) } - + override fun onBindViewHolder(holder: PageViewHolder, position: Int) { val root = holder.root - + if (position == 0) { renderList1(root, allPersonaCache) } else { val rv2 = root.findViewById(R.id.recyclerView) val loadingView = root.findViewById(R.id.loadingView) - + rv2.setHasFixedSize(true) + + // ✅ 禁止 itemAnimator(减少 layout 抖动) rv2.itemAnimator = null + rv2.isNestedScrollingEnabled = false - + var adapter = rv2.adapter as? PersonaAdapter if (adapter == null) { adapter = PersonaAdapter { click -> when (click) { is PersonaClick.Item -> { val id = click.persona.id + if (!isAdded || childFragmentManager.isStateSaved) return@PersonaAdapter PersonaDetailDialogFragment .newInstance(id) .show(childFragmentManager, "persona_detail") } + is PersonaClick.Add -> { - lifecycleScope.launch { - if (click.persona.added == true) { - click.persona.id?.let { id -> - RetrofitClient.apiService.delUserCharacter(id.toInt()) + viewLifecycleOwner.lifecycleScope.launch { + try { + if (click.persona.added == true) { + click.persona.id?.let { id -> + RetrofitClient.apiService.delUserCharacter(id.toInt()) + } + } else { + val req = AddPersonaClick( + characterId = click.persona.id?.toInt() ?: 0, + emoji = click.persona.emoji ?: "" + ) + RetrofitClient.apiService.addUserCharacter(req) } - } else { - val req = AddPersonaClick( - characterId = click.persona.id?.toInt() ?: 0, - emoji = click.persona.emoji ?: "" - ) - RetrofitClient.apiService.addUserCharacter(req) + } catch (_: Exception) { } } } @@ -517,17 +605,17 @@ class HomeFragment : Fragment() { rv2.layoutManager = GridLayoutManager(root.context, 2) rv2.adapter = adapter } - + val tagIndex = position - 1 if (tagIndex !in tags.indices) { loadingView.isVisible = false adapter.submitList(emptyList()) return } - + val tagId = tags[tagIndex].id val cached = personaCache[tagId] - + if (cached == null) { loadingView.isVisible = true adapter.submitList(emptyList()) @@ -537,175 +625,147 @@ class HomeFragment : Fragment() { } } } - + override fun getItemCount(): Int = pageCount } - - // 通过 tagIndex 取出该页要显示的数据 - private fun getPersonaListByTagIndex(tagIndex: Int): List { - if (tagIndex !in tags.indices) return emptyList() - val tagId = tags[tagIndex].id - return personaCache[tagId] ?: emptyList() - } + // ---------------- 列表一渲染(原逻辑不动) ---------------- private fun renderList1(root: View, list: List) { - // 1) 排序:rank 小的排前面 + val key = buildString { + list.forEach { p -> + append(p.id).append('_') + append(p.added).append('_') + append(p.rank).append('|') + } + } + if (key == lastList1RenderKey) return + lastList1RenderKey = key val sorted = list.sortedBy { it.rank ?: Int.MAX_VALUE } - val top3 = sorted.take(3) val others = if (sorted.size > 3) sorted.drop(3) else emptyList() - - // 2) 绑定前三名(注意:你的 UI 排列是:第二/第一/第三) - bindTopItem(root, + + bindTopItem( + root, avatarId = R.id.avatar_first, nameId = R.id.name_first, addBtnId = R.id.btn_add_first, - container = R.id.container_first, - item = top3.getOrNull(0) // rank 最小 = 第一名 + containerId = R.id.container_first, + item = top3.getOrNull(0) ) - - bindTopItem(root, + + bindTopItem( + root, avatarId = R.id.avatar_second, nameId = R.id.name_second, addBtnId = R.id.btn_add_second, - container = R.id.container_second, - item = top3.getOrNull(1) // 第二名 + containerId = R.id.container_second, + item = top3.getOrNull(1) ) - - bindTopItem(root, + + bindTopItem( + root, avatarId = R.id.avatar_third, nameId = R.id.name_third, addBtnId = R.id.btn_add_third, - container = R.id.container_third, - item = top3.getOrNull(2) // 第三名 + containerId = R.id.container_third, + item = top3.getOrNull(2) ) - - // 3) 渲染后面的内容卡片 + val container = root.findViewById(R.id.container_others) container.removeAllViews() - + val inflater = LayoutInflater.from(root.context) others.forEach { p -> val itemView = inflater.inflate(R.layout.item_rank_other, container, false) - - itemView.findViewById(R.id.tv_rank).text = (p.rank ?: "--").toString() itemView.findViewById(R.id.tv_name).text = p.characterName ?: "" itemView.findViewById(R.id.tv_desc).text = p.characterBackground ?: "" - - // 头像 + val iv = itemView.findViewById(R.id.iv_avatar) - // Glide 示例 com.bumptech.glide.Glide.with(iv).load(p.avatarUrl).into(iv) - + itemView.setOnClickListener { - val id = p.id - Log.d("HomeFragment", "list1 others click id=$id") + if (!isAdded || childFragmentManager.isStateSaved) return@setOnClickListener PersonaDetailDialogFragment - .newInstance(id) + .newInstance(p.id) .show(childFragmentManager, "persona_detail") } - // 只点“添加”按钮 itemView.findViewById(R.id.btn_add).setOnClickListener { - val id = p.id - lifecycleScope.launch { - if(p.added == true){ - //取消收藏 - p.id?.let { id -> - try { - RetrofitClient.apiService.delUserCharacter(id.toInt()) - } catch (e: Exception) { - // 处理错误 - } - } - }else{ - val addPersonaRequest = AddPersonaClick( - characterId = p.id?.toInt() ?: 0, - emoji = p.emoji ?: "" - ) - try { - RetrofitClient.apiService.addUserCharacter(addPersonaRequest) - } catch (e: Exception) { - // 处理错误 + viewLifecycleOwner.lifecycleScope.launch { + try { + if (p.added == true) { + p.id?.let { id -> RetrofitClient.apiService.delUserCharacter(id.toInt()) } + } else { + val req = AddPersonaClick( + characterId = p.id?.toInt() ?: 0, + emoji = p.emoji ?: "" + ) + RetrofitClient.apiService.addUserCharacter(req) } + } catch (_: Exception) { } } } - + container.addView(itemView) } } - + private fun bindTopItem( root: View, avatarId: Int, nameId: Int, addBtnId: Int, - container: Int, + containerId: Int, item: listByTagWithNotLogin? ) { val avatar = root.findViewById(avatarId) val name = root.findViewById(nameId) val addBtn = root.findViewById(addBtnId) - val container = root.findViewById(container) - + val container = root.findViewById(containerId) + if (item == null) { - // 没数据就隐藏(或者显示占位) - // avatar.isVisible = false name.isVisible = false addBtn.isVisible = false return } - - avatar.isVisible = true + name.isVisible = true addBtn.isVisible = true - + name.text = item.characterName ?: "" - - // 头像 com.bumptech.glide.Glide.with(avatar).load(item.avatarUrl).into(avatar) - + addBtn.setOnClickListener { - val id = item.id - lifecycleScope.launch { - if(item.added == true){ - //取消收藏 - item.id?.let { id -> - try { - RetrofitClient.apiService.delUserCharacter(id.toInt()) - } catch (e: Exception) { - // 处理错误 - } - } - }else{ - val addPersonaRequest = AddPersonaClick( - characterId = item.id?.toInt() ?: 0, - emoji = item.emoji ?: "" - ) - try { - RetrofitClient.apiService.addUserCharacter(addPersonaRequest) - } catch (e: Exception) { - // 处理错误 + viewLifecycleOwner.lifecycleScope.launch { + try { + if (item.added == true) { + item.id?.let { id -> RetrofitClient.apiService.delUserCharacter(id.toInt()) } + } else { + val req = AddPersonaClick( + characterId = item.id?.toInt() ?: 0, + emoji = item.emoji ?: "" + ) + RetrofitClient.apiService.addUserCharacter(req) } + } catch (_: Exception) { } } } container.setOnClickListener { - val id = item.id - Log.d("HomeFragment", "list1 top click id=$id rank=${item.rank}") + if (!isAdded || childFragmentManager.isStateSaved) return@setOnClickListener PersonaDetailDialogFragment - .newInstance(id) + .newInstance(item.id) .show(childFragmentManager, "persona_detail") } } - - + // ---------------- 网络请求 ---------------- + private suspend fun fetchPersonaByTag(tagId: Int): List { return try { val resp = if (!isLoggedIn()) { @@ -715,54 +775,36 @@ class HomeFragment : Fragment() { } resp.data ?: emptyList() } catch (e: Exception) { - if(!isLoggedIn()){ - //未登录用户获取人设列表 - Log.e("1314520-HomeFragment", "未登录根据标签获取人设列表", e) - }else{ - Log.e("1314520-HomeFragment", "登录根据标签获取人设列表", e) - } + Log.e("1314520-HomeFragment", "按标签获取人设列表失败 tagId=$tagId", e) emptyList() } } private suspend fun fetchAllPersonaList(): List { return try { - val personaData = if (!isLoggedIn()) { + val resp = if (!isLoggedIn()) { RetrofitClient.apiService.personaListWithNotLogin() } else { RetrofitClient.apiService.personaByTag() } - personaData.data ?: emptyList() + resp.data ?: emptyList() } catch (e: Exception) { - if(!isLoggedIn()){ - //未登录用户获取人设列表 - Log.e("1314520-HomeFragment", "未登录用户人设列表", e) - }else{ - Log.e("1314520-HomeFragment", "登录用户人设列表", e) - } + Log.e("1314520-HomeFragment", "获取列表一失败", e) emptyList() } } - suspend fun getpersonaLis(id: Int): ApiResponse>? { - return try { - RetrofitClient.apiService.personaListByTag(id) - } catch (e: Exception) { - Log.e("1314520-HomeFragment", "未登录用户按标签查询人设列表", e) - null - } - } - - suspend fun loggedInGetpersonaLis(id: Int): ApiResponse>? { - return try { - RetrofitClient.apiService.loggedInPersonaListByTag(id) - } catch (e: Exception) { - Log.e("1314520-HomeFragment", "登录用户按标签查询人设列表", e) - null - } - } - + // ✅ 不再 requireContext(),避免 detach 直接崩 private fun isLoggedIn(): Boolean { - return EncryptedSharedPreferencesUtil.contains(requireContext(), "user") + val ctx = context ?: return false + return EncryptedSharedPreferencesUtil.contains(ctx, "user") + } + + // ✅ 统一安全导航:stateSaved 防护(切很快/后台回来时很重要) + private fun safeNavigate(actionId: Int) { + if (!isAdded) return + if (parentFragmentManager.isStateSaved) return + runCatching { findNavController().navigate(actionId) } + .onFailure { Log.e("HomeFragment", "navigate fail: $actionId", it) } } } diff --git a/app/src/main/java/com/example/myapplication/ui/keyboard/KeyboardDetailFragment.kt b/app/src/main/java/com/example/myapplication/ui/keyboard/KeyboardDetailFragment.kt index 1d5b1e7..3cdda23 100644 --- a/app/src/main/java/com/example/myapplication/ui/keyboard/KeyboardDetailFragment.kt +++ b/app/src/main/java/com/example/myapplication/ui/keyboard/KeyboardDetailFragment.kt @@ -40,6 +40,8 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.io.BufferedInputStream import java.io.FileInputStream +import com.example.myapplication.ui.shop.ShopEvent +import com.example.myapplication.ui.shop.ShopEventBus class KeyboardDetailFragment : Fragment() { @@ -291,6 +293,8 @@ class KeyboardDetailFragment : Fragment() { if (response?.code == 0) { loadData() } + + ShopEventBus.post(ShopEvent.ThemePurchased) } catch (e: Exception) { Log.e("KeyboardDetailFragment", "购买主题失败", e) } diff --git a/app/src/main/java/com/example/myapplication/ui/login/CodeEditText.kt b/app/src/main/java/com/example/myapplication/ui/login/CodeEditText.kt new file mode 100644 index 0000000..bf78a0a --- /dev/null +++ b/app/src/main/java/com/example/myapplication/ui/login/CodeEditText.kt @@ -0,0 +1,43 @@ +package com.example.myapplication.ui.common + +import android.content.Context +import android.util.AttributeSet +import android.view.inputmethod.EditorInfo +import android.view.inputmethod.InputConnection +import android.view.inputmethod.InputConnectionWrapper +import androidx.appcompat.widget.AppCompatEditText + +class CodeEditText @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = android.R.attr.editTextStyle +) : AppCompatEditText(context, attrs, defStyleAttr) { + + var onDelPressed: (() -> Unit)? = null + + override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection { + val ic = super.onCreateInputConnection(outAttrs) + return object : InputConnectionWrapper(ic, true) { + + // 软键盘删除通常走这个 + override fun deleteSurroundingText(beforeLength: Int, afterLength: Int): Boolean { + if (beforeLength == 1 && afterLength == 0) { + onDelPressed?.invoke() + return true + } + return super.deleteSurroundingText(beforeLength, afterLength) + } + + // 一些键盘会直接发 KeyEvent DEL + override fun sendKeyEvent(event: android.view.KeyEvent): Boolean { + if (event.action == android.view.KeyEvent.ACTION_DOWN && + event.keyCode == android.view.KeyEvent.KEYCODE_DEL + ) { + onDelPressed?.invoke() + return true + } + return super.sendKeyEvent(event) + } + } + } +} diff --git a/app/src/main/java/com/example/myapplication/ui/login/ForgetPasswordEmailFragment.kt b/app/src/main/java/com/example/myapplication/ui/login/ForgetPasswordEmailFragment.kt index fb3c8b8..a4935e6 100644 --- a/app/src/main/java/com/example/myapplication/ui/login/ForgetPasswordEmailFragment.kt +++ b/app/src/main/java/com/example/myapplication/ui/login/ForgetPasswordEmailFragment.kt @@ -5,14 +5,25 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.fragment.app.Fragment -import com.example.myapplication.R -import com.google.android.material.textfield.TextInputLayout +import android.widget.EditText import android.widget.TextView +import android.widget.Toast +import android.widget.FrameLayout +import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController +import com.example.myapplication.R +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.launch +import com.example.myapplication.network.SendVerifyCodeRequest +import com.example.myapplication.network.RetrofitClient +import com.example.myapplication.utils.EncryptedSharedPreferencesUtil +import android.util.Log class ForgetPasswordEmailFragment : Fragment() { + private lateinit var emailEditText: EditText // 邮箱输入框 + private var loadingOverlay: com.example.myapplication.ui.common.LoadingOverlay? = null // 加载遮罩层 + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -20,12 +31,63 @@ class ForgetPasswordEmailFragment : Fragment() { ): View? { return inflater.inflate(R.layout.fragment_forget_password_email, container, false) } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - //验证码页面 + // 初始化加载遮罩层 + loadingOverlay = com.example.myapplication.ui.common.LoadingOverlay.attach(view as ViewGroup) + + emailEditText = view.findViewById(R.id.et_email) + + view.findViewById(R.id.iv_close).setOnClickListener { + parentFragmentManager.popBackStack() + } + + // 下一步按钮点击事件 view.findViewById(R.id.nextstep).setOnClickListener { - findNavController().navigate(R.id.action_forgetPasswordEmailFragment_to_forgetPasswordVerifyFragment) - } + // 对输入框去除首尾空格 + val email = emailEditText.text.toString().trim() + + // 判断邮箱是否为空 + if (email.isEmpty()) { + Toast.makeText(activity, "Please enter your email address", Toast.LENGTH_SHORT).show() + } else if (!isValidEmail(email)) { + Toast.makeText(activity, "The email address format is incorrect", Toast.LENGTH_SHORT).show() + } else { + loadingOverlay?.show() + viewLifecycleOwner.lifecycleScope.launch { + try { + val body = SendVerifyCodeRequest(email) + 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() + } + } catch (e: Exception) { + Log.e("1314520-MineFragment", "发送验证码失败", e) + } finally { + loadingOverlay?.hide() + } + } + } + } + } + + override fun onDestroyView() { + loadingOverlay?.remove() + loadingOverlay = null + super.onDestroyView() + } + + /** + * 验证邮箱格式是否有效 + * @param email 要验证的邮箱地址 + * @return 如果邮箱格式有效返回true,否则返回false + */ + private fun isValidEmail(email: String): Boolean { + val emailRegex = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$" + return email.matches(emailRegex.toRegex()) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/ui/login/ForgetPasswordResetFragment.kt b/app/src/main/java/com/example/myapplication/ui/login/ForgetPasswordResetFragment.kt index 04d0a96..f7351e1 100644 --- a/app/src/main/java/com/example/myapplication/ui/login/ForgetPasswordResetFragment.kt +++ b/app/src/main/java/com/example/myapplication/ui/login/ForgetPasswordResetFragment.kt @@ -2,13 +2,36 @@ package com.example.myapplication.ui.login import android.os.Bundle +import android.text.InputType +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.EditText +import android.widget.FrameLayout +import android.widget.ImageView +import android.widget.TextView +import android.widget.Toast import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController import com.example.myapplication.R +import com.example.myapplication.network.ResetPasswordRequest +import com.example.myapplication.network.RetrofitClient +import com.example.myapplication.ui.common.LoadingOverlay +import com.example.myapplication.utils.EncryptedSharedPreferencesUtil +import kotlinx.coroutines.launch class ForgetPasswordResetFragment : Fragment() { + + private lateinit var passwordEditText: EditText // 密码输入框 + private lateinit var confirmPasswordEditText: EditText // 确认密码输入框 + private lateinit var toggleImageView: android.widget.ImageView // 密码显示/隐藏按钮 + private lateinit var confirmtoggleImageView: android.widget.ImageView // 确认密码显示/隐藏按钮 + private var loadingOverlay: LoadingOverlay? = null // 加载遮罩层 + private var isPasswordVisible = false // 密码可见性状态 + private var isConfirmPasswordVisible = false // 确认密码可见性状态 + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -17,5 +40,98 @@ class ForgetPasswordResetFragment : Fragment() { return inflater.inflate(R.layout.fragment_forget_password_reset, container, false) } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + view.findViewById(R.id.iv_close).setOnClickListener { + parentFragmentManager.popBackStack() + } + + passwordEditText = view.findViewById(R.id.et_password) + confirmPasswordEditText = view.findViewById(R.id.et_confirm_password) + toggleImageView = view.findViewById(R.id.iv_toggle) + confirmtoggleImageView = view.findViewById(R.id.iv_confirm_toggle) + + // 初始化加载遮罩层 + loadingOverlay = LoadingOverlay.attach(view as ViewGroup) + + // 密码显示/隐藏按钮点击事件 + passwordEditText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD + + toggleImageView.setOnClickListener { + isPasswordVisible = !isPasswordVisible + + if (isPasswordVisible) { + // 显示密码 + passwordEditText.inputType = + InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD + toggleImageView.setImageResource(R.drawable.display) + } else { + // 隐藏密码 + passwordEditText.inputType = + InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD + toggleImageView.setImageResource(R.drawable.hide) + } + // 保持光标在末尾 + passwordEditText.setSelection(passwordEditText.text?.length ?: 0) + } + + // 确认密码显示/隐藏按钮点击事件 + confirmPasswordEditText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD + + confirmtoggleImageView.setOnClickListener { + isConfirmPasswordVisible = !isConfirmPasswordVisible + + if (isConfirmPasswordVisible) { + // 显示密码 + confirmPasswordEditText.inputType = + InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD + confirmtoggleImageView.setImageResource(R.drawable.display) + } else { + // 隐藏密码 + confirmPasswordEditText.inputType = + InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD + confirmtoggleImageView.setImageResource(R.drawable.hide) + } + // 保持光标在末尾 + confirmPasswordEditText.setSelection(confirmPasswordEditText.text?.length ?: 0) + } + + + val savedEmail = EncryptedSharedPreferencesUtil.get(requireContext(), "forget_email", String::class.java) + + view.findViewById(R.id.nextstep).setOnClickListener { + val password = passwordEditText.text.toString().trim() + val confirmPassword = confirmPasswordEditText.text.toString().trim() + + //判断密码,邮箱,确认密码是否为空 + if (password.isEmpty() || confirmPassword.isEmpty()) { + Toast.makeText(activity, "Please fill in the complete information", Toast.LENGTH_SHORT).show() + } else if (password != confirmPassword) { + Toast.makeText(activity, "The two password entries are inconsistent", Toast.LENGTH_SHORT).show() + } else { + loadingOverlay?.show() + viewLifecycleOwner.lifecycleScope.launch { + try { + val body = ResetPasswordRequest( + mailAddress = savedEmail!!, + password = password, + confirmPassword = confirmPassword + ) + 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() + // 使用忘记密码专用的action跳转到登录页面 + findNavController().navigate(R.id.action_global_loginFragment_from_forget_password) + } + } catch (e: Exception) { + Log.e("1314520-MineFragment", "重置密码失败", e) + } finally { + loadingOverlay?.hide() + } + } + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/ui/login/ForgetPasswordVerifyFragment.kt b/app/src/main/java/com/example/myapplication/ui/login/ForgetPasswordVerifyFragment.kt index 15d3047..b36050f 100644 --- a/app/src/main/java/com/example/myapplication/ui/login/ForgetPasswordVerifyFragment.kt +++ b/app/src/main/java/com/example/myapplication/ui/login/ForgetPasswordVerifyFragment.kt @@ -9,15 +9,23 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.EditText +import android.widget.FrameLayout import androidx.fragment.app.Fragment import com.example.myapplication.R import android.widget.TextView import androidx.navigation.fragment.findNavController - +import com.example.myapplication.utils.EncryptedSharedPreferencesUtil +import android.widget.Toast +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.launch +import com.example.myapplication.network.RetrofitClient +import com.example.myapplication.network.VerifyCodeRequest +import android.util.Log class ForgetPasswordVerifyFragment : Fragment() { private lateinit var codeInputs: List + private var loadingOverlay: com.example.myapplication.ui.common.LoadingOverlay? = null//加载遮罩层 override fun onCreateView( inflater: LayoutInflater, @@ -29,12 +37,47 @@ class ForgetPasswordVerifyFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + loadingOverlay = com.example.myapplication.ui.common.LoadingOverlay.attach(view as ViewGroup) - //验证码页面 - view.findViewById< - TextView>(R.id.nextstep).setOnClickListener { - findNavController().navigate(R.id.action_forgetPasswordVerifyFragment_to_forgetPasswordResetFragment) - } + val savedEmail = EncryptedSharedPreferencesUtil.get(requireContext(), "forget_email", String::class.java) + + view.findViewById(R.id.tv_code_hint).setText("A verification email has been sent to ${savedEmail}. Please check your inbox to complete the verification.") + + + view.findViewById(R.id.iv_close).setOnClickListener { + parentFragmentManager.popBackStack() + } + + view.findViewById(R.id.nextstep).setOnClickListener { + // 验证验证码 + val verifyCode = getVerifyCode() + if (verifyCode.length != 6) { + Toast.makeText(activity, "The verification code format is incorrect", Toast.LENGTH_SHORT).show() + return@setOnClickListener + } + + // 显示加载遮罩层 + loadingOverlay?.show() + + viewLifecycleOwner.lifecycleScope.launch { + try { + val body = VerifyCodeRequest( + mailAddress = savedEmail!!, + verifyCode = verifyCode + ) + 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) + } + } catch (e: Exception) { + Log.e("1314520-MineFragment", "验证码验证失败", e) + } finally { + // 隐藏加载遮罩层 + loadingOverlay?.hide() + } + } + } codeInputs = listOf( view.findViewById(R.id.et_code_1), diff --git a/app/src/main/java/com/example/myapplication/ui/login/LoginFragment.kt b/app/src/main/java/com/example/myapplication/ui/login/LoginFragment.kt index 9d8a473..fba0d87 100644 --- a/app/src/main/java/com/example/myapplication/ui/login/LoginFragment.kt +++ b/app/src/main/java/com/example/myapplication/ui/login/LoginFragment.kt @@ -21,6 +21,11 @@ import com.example.myapplication.utils.EncryptedSharedPreferencesUtil import com.google.android.material.button.MaterialButton import android.widget.Toast import kotlinx.coroutines.launch +import androidx.fragment.app.setFragmentResult +import com.example.myapplication.ui.mine.MineFragment +import androidx.core.os.bundleOf +import com.example.myapplication.network.AuthEventBus +import com.example.myapplication.network.AuthEvent class LoginFragment : Fragment() { @@ -52,18 +57,14 @@ class LoginFragment : Fragment() { // 注册 view.findViewById(R.id.tv_signup).setOnClickListener { - findNavController().navigate(R.id.action_mineFragment_to_registerFragment) + findNavController().navigate(R.id.action_loginFragment_to_registerFragment) } // 忘记密码 view.findViewById(R.id.tv_forgot_password).setOnClickListener { findNavController().navigate(R.id.action_loginFragment_to_forgetPasswordEmailFragment) } - // 返回按钮 - view.findViewById(R.id.iv_close).setOnClickListener { - findNavController().previousBackStackEntry - ?.savedStateHandle - ?.set("from_login", true) - + // 返回 - 在global_graph中,直接popBackStack回到globalEmptyFragment + view.findViewById(R.id.iv_close).setOnClickListener { findNavController().popBackStack() } // 绑定控件(id 必须和 xml 里的一样) @@ -122,7 +123,9 @@ class LoginFragment : Fragment() { if (response.code == 0) { EncryptedSharedPreferencesUtil.save(requireContext(), "user", response.data) EncryptedSharedPreferencesUtil.save(requireContext(), "email",email) - findNavController().popBackStack() + // 触发登录成功事件,让MainActivity关闭全局overlay + AuthEventBus.emit(AuthEvent.LoginSuccess) + // 不在这里popBackStack,让MainActivity的LoginSuccess事件处理关闭全局overlay } else { Toast.makeText(requireContext(), "Login failed: ${response.message}", Toast.LENGTH_SHORT).show() } @@ -136,4 +139,8 @@ class LoginFragment : Fragment() { } } } + + private fun isLoggedIn(): Boolean { + return EncryptedSharedPreferencesUtil.contains(requireContext(), "user") + } } diff --git a/app/src/main/java/com/example/myapplication/ui/login/RegisterFragment.kt b/app/src/main/java/com/example/myapplication/ui/login/RegisterFragment.kt index 54aa6c1..b1eeb8c 100644 --- a/app/src/main/java/com/example/myapplication/ui/login/RegisterFragment.kt +++ b/app/src/main/java/com/example/myapplication/ui/login/RegisterFragment.kt @@ -1,17 +1,40 @@ package com.example.myapplication.ui.login import android.os.Bundle +import android.text.InputType import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.EditText +import android.widget.FrameLayout +import android.widget.ImageView +import android.widget.TextView +import android.widget.Toast import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController -import android.widget.FrameLayout -import android.widget.TextView import com.example.myapplication.R +import androidx.lifecycle.lifecycleScope +import com.example.myapplication.network.SendVerifyCodeRequest +import com.example.myapplication.network.RetrofitClient +import com.example.myapplication.utils.EncryptedSharedPreferencesUtil +import com.example.myapplication.ui.common.LoadingOverlay +import kotlinx.coroutines.launch +import android.util.Log class RegisterFragment : Fragment() { + private lateinit var passwordEditText: EditText // 密码输入框 + private lateinit var confirmPasswordEditText: EditText // 确认密码输入框 + private lateinit var emailEditText: EditText // 邮箱输入框 + private lateinit var toggleImageView: ImageView // 密码显示/隐藏按钮 + private lateinit var confirmtoggleImageView: ImageView // 确认密码显示/隐藏按钮 + private lateinit var nextStepButton: TextView // 下一步按钮 + + private var isPasswordVisible = false + private var isConfirmPasswordVisible = false + private var loadingOverlay: LoadingOverlay? = null // 加载遮罩层 + + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -23,9 +46,114 @@ class RegisterFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + toggleImageView = view.findViewById(R.id.iv_toggle) + confirmtoggleImageView = view.findViewById(R.id.iv_confirm_toggle) + passwordEditText = view.findViewById(R.id.et_password) + confirmPasswordEditText = view.findViewById(R.id.et_confirm_password) + emailEditText = view.findViewById(R.id.et_email) + nextStepButton = view.findViewById(R.id.btn_next_step) + + // 初始化加载遮罩层 + loadingOverlay = LoadingOverlay.attach(view as ViewGroup) + + // 密码显示/隐藏按钮点击事件 + passwordEditText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD + + toggleImageView.setOnClickListener { + isPasswordVisible = !isPasswordVisible + + if (isPasswordVisible) { + // 显示密码 + passwordEditText.inputType = + InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD + toggleImageView.setImageResource(R.drawable.display) + } else { + // 隐藏密码 + passwordEditText.inputType = + InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD + toggleImageView.setImageResource(R.drawable.hide) + } + // 保持光标在末尾 + passwordEditText.setSelection(passwordEditText.text?.length ?: 0) + } + + // 确认密码显示/隐藏按钮点击事件 + confirmPasswordEditText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD + + confirmtoggleImageView.setOnClickListener { + isConfirmPasswordVisible = !isConfirmPasswordVisible + + if (isConfirmPasswordVisible) { + // 显示密码 + confirmPasswordEditText.inputType = + InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD + confirmtoggleImageView.setImageResource(R.drawable.display) + } else { + // 隐藏密码 + confirmPasswordEditText.inputType = + InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD + confirmtoggleImageView.setImageResource(R.drawable.hide) + } + // 保持光标在末尾 + confirmPasswordEditText.setSelection(confirmPasswordEditText.text?.length ?: 0) + } + + // 下一步按钮点击事件 + nextStepButton.setOnClickListener { + // 对输入框去除首尾空格 + val email = emailEditText.text.toString().trim() + val password = passwordEditText.text.toString().trim() + val confirmPassword = confirmPasswordEditText.text.toString().trim() + + //判断密码,邮箱,确认密码是否为空 + if (password.isEmpty() || email.isEmpty() || confirmPassword.isEmpty()) { + Toast.makeText(activity, "Please fill in the complete information", Toast.LENGTH_SHORT).show() + } else if (password != confirmPassword) { + Toast.makeText(activity, "The two password entries are inconsistent", Toast.LENGTH_SHORT).show() + } else if (!isValidEmail(email)) { + Toast.makeText(activity, "The email address format is incorrect", Toast.LENGTH_SHORT).show() + } else { + loadingOverlay?.show() + viewLifecycleOwner.lifecycleScope.launch { + try { + val body = SendVerifyCodeRequest(email) + val response = RetrofitClient.apiService.sendVerifyCode(body) + if (response.code == 0) { + 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() + } + } catch (e: Exception) { + Log.e("1314520-MineFragment", "获取失败", e) + } finally { + loadingOverlay?.hide() + } + } + } + } + + + // 返回按钮 view.findViewById(R.id.iv_close).setOnClickListener { - parentFragmentManager.popBackStack() - } + parentFragmentManager.popBackStack() + } + } + + override fun onDestroyView() { + loadingOverlay?.remove() + super.onDestroyView() + } + + + // 验证邮箱格式是否有效 + // @param email 要验证的邮箱地址 + // @return 如果邮箱格式有效返回true,否则返回false + + private fun isValidEmail(email: String): Boolean { + val emailRegex = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$" + return email.matches(emailRegex.toRegex()) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/myapplication/ui/login/RegisterVerifyFragment.kt b/app/src/main/java/com/example/myapplication/ui/login/RegisterVerifyFragment.kt new file mode 100644 index 0000000..830e9d1 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/ui/login/RegisterVerifyFragment.kt @@ -0,0 +1,175 @@ +// 忘记密码验证码输入页面 +package com.example.myapplication.ui.login + +import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.Toast +import android.util.Log +import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController +import com.example.myapplication.R +import com.example.myapplication.network.RegisterRequest +import com.example.myapplication.network.RetrofitClient +import com.example.myapplication.ui.common.CodeEditText +import com.example.myapplication.utils.EncryptedSharedPreferencesUtil +import kotlinx.coroutines.launch +import android.widget.TextView + +class RegisterVerifyFragment : Fragment() { + + private lateinit var codeInputs: List + private var loadingOverlay: com.example.myapplication.ui.common.LoadingOverlay? = null // 加载遮罩层 + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_register_verify, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + // 初始化加载遮罩层 + loadingOverlay = com.example.myapplication.ui.common.LoadingOverlay.attach(view as ViewGroup) + + view.findViewById(R.id.iv_close).setOnClickListener { + parentFragmentManager.popBackStack() + } + + // 注意:布局里的 6 个输入框需要是 CodeEditText + codeInputs = listOf( + view.findViewById(R.id.et_code_1), + view.findViewById(R.id.et_code_2), + view.findViewById(R.id.et_code_3), + view.findViewById(R.id.et_code_4), + view.findViewById(R.id.et_code_5), + view.findViewById(R.id.et_code_6) + ) + + setupVerifyCodeInputs() + + val savedEmail = EncryptedSharedPreferencesUtil.get(requireContext(), "register_email", String::class.java) + val savedPassword = EncryptedSharedPreferencesUtil.get(requireContext(), "register_password", String::class.java) + val savedConfirmPassword = EncryptedSharedPreferencesUtil.get(requireContext(), "register_confirm_password", String::class.java) + val savedGender = EncryptedSharedPreferencesUtil.get(requireContext(), "gender", String::class.java) + val savedInviteCode = EncryptedSharedPreferencesUtil.get(requireContext(), "inviteCode", String::class.java) + + view.findViewById(R.id.tv_code_hint).text = + "A verification email has been sent to ${savedEmail}. Please check your inbox to complete the verification." + + view.findViewById(R.id.nextstep).setOnClickListener { + val verifyCode = getVerifyCode() + if (verifyCode.length != 6) { + Toast.makeText(activity, "The verification code format is incorrect", Toast.LENGTH_SHORT).show() + return@setOnClickListener + } + + loadingOverlay?.show() + + viewLifecycleOwner.lifecycleScope.launch { + try { + val body = RegisterRequest( + mailAddress = savedEmail!!, + password = savedPassword!!, + passwordConfirm = savedConfirmPassword!!, + gender = savedGender?.toIntOrNull() ?: 0, + verifyCode = verifyCode, + inviteCode = savedInviteCode + ) + + val response = RetrofitClient.apiService.register(body) + if (response.code == 0) { + Toast.makeText(activity, "Registration successful", 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) + } + } catch (e: Exception) { + Log.e("1314520-MineFragment", "注册失败", e) + } finally { + loadingOverlay?.hide() + } + } + } + } + + override fun onDestroyView() { + loadingOverlay?.remove() + super.onDestroyView() + } + + private fun setupVerifyCodeInputs() { + codeInputs.forEachIndexed { index, editText -> + + // 输入监听:自动跳到下一格;多字符只取最后一位(可应付部分粘贴/联想) + editText.addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} + + override fun afterTextChanged(s: Editable?) { + val text = s?.toString().orEmpty() + + if (text.length > 1) { + editText.setText(text.last().toString()) + editText.setSelection(1) + } + + if (text.isNotEmpty() && index < codeInputs.size - 1) { + codeInputs[index + 1].requestFocus() + } + } + }) + + // ✅ 删除统一走这里:软键盘 deleteSurroundingText + 硬件 DEL 都能触发 + editText.onDelPressed = { + handleDeleteAction(index, editText) + } + } + } + + // 获取完整验证码 + private fun getVerifyCode(): String { + return codeInputs.joinToString("") { it.text?.toString().orEmpty() } + } + + /** + * 删除逻辑:当前有内容先删当前;当前为空就跳到前面最近有内容的格子并删除 + */ + private fun handleDeleteAction(index: Int, currentEditText: CodeEditText) { + // 1) 当前格有内容:清空当前格 + if (!currentEditText.text.isNullOrEmpty()) { + currentEditText.text?.clear() + return + } + + // 2) 当前为空:向前找最近一个有内容的格子,跳过去并清空 + var targetIndex = index - 1 + while (targetIndex >= 0) { + val targetEditText = codeInputs[targetIndex] + if (!targetEditText.text.isNullOrEmpty()) { + targetEditText.requestFocus() + targetEditText.text?.clear() + targetEditText.post { targetEditText.setSelection(0) } + return + } + targetIndex-- + } + + // 3) 前面也都空:就停在第一个 + if (index > 0) { + val first = codeInputs[0] + first.requestFocus() + first.post { first.setSelection(0) } + } + } +} diff --git a/app/src/main/java/com/example/myapplication/ui/mine/MineFragment.kt b/app/src/main/java/com/example/myapplication/ui/mine/MineFragment.kt index 171078e..fb0602f 100644 --- a/app/src/main/java/com/example/myapplication/ui/mine/MineFragment.kt +++ b/app/src/main/java/com/example/myapplication/ui/mine/MineFragment.kt @@ -1,23 +1,32 @@ package com.example.myapplication.ui.mine 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.example.myapplication.R -import android.widget.LinearLayout -import com.example.myapplication.network.RetrofitClient +import com.example.myapplication.network.AuthEvent +import com.example.myapplication.network.AuthEventBus import com.example.myapplication.network.LoginResponse -import de.hdodenhof.circleimageview.CircleImageView -import android.util.Log -import kotlinx.coroutines.launch -import android.widget.TextView +import com.example.myapplication.network.RetrofitClient import com.example.myapplication.utils.EncryptedSharedPreferencesUtil -import androidx.navigation.navOptions +import de.hdodenhof.circleimageview.CircleImageView +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch class MineFragment : Fragment() { @@ -25,129 +34,179 @@ class MineFragment : Fragment() { private lateinit var time: TextView private lateinit var logout: TextView + private var loadUserJob: Job? = null + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - return inflater.inflate(R.layout.fragment_mine, container, false) + ): View = inflater.inflate(R.layout.fragment_mine, container, false) + + override fun onDestroyView() { + loadUserJob?.cancel() + super.onDestroyView() } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - // 判断是否登录(门禁) - if (!isLoggedIn()) { - val nav = findNavController() - - // 改用 savedStateHandle 的标记:LoginFragment 返回时写入 - val fromLogin = nav.currentBackStackEntry - ?.savedStateHandle - ?.get("from_login") == true - - // 用完就清掉 - nav.currentBackStackEntry?.savedStateHandle?.remove("from_login") - - view?.post { - try { - if (fromLogin) { - // 从登录页回来仍未登录:跳首页 - nav.navigate(R.id.action_global_homeFragment) - } else { - // 不是从登录页来:跳登录 - nav.navigate(R.id.action_mineFragment_to_loginFragment) - } - } catch (e: IllegalArgumentException) { - // 万一你的导航框架在当前时机解析 action 有问题,兜底:直接去目标 Fragment id - if (fromLogin) { - nav.navigate(R.id.homeFragment) - } else { - nav.navigate(R.id.loginFragment) - } - } - } - - return - } - - nickname = view.findViewById(R.id.nickname) time = view.findViewById(R.id.time) logout = view.findViewById(R.id.logout) + // 1) 先用本地缓存秒出首屏 + renderFromCache() - // 获取用户信息, 并显示 - val user = EncryptedSharedPreferencesUtil.get(requireContext(), "Personal_information", LoginResponse::class.java) - nickname.text = user?.nickName ?: "" - time.text = user?.vipExpiry?.let { "Due on November $it" } ?: "" - - // 2) 下一帧再请求网络(让首帧先出来) - view.post { - viewLifecycleOwner.lifecycleScope.launch { - try { - val response = RetrofitClient.apiService.getUser() - nickname.text = response.data?.nickName ?: "" - time.text = response.data?.vipExpiry?.let { "Due on November $it" } ?: "" - EncryptedSharedPreferencesUtil.save(requireContext(), "Personal_information", response.data) - } catch (e: Exception) { - Log.e("1314520-MineFragment", "获取失败", e) + // 2) 首次进入不刷新,由onResume处理 + + // // ✅ 手动刷新:不改布局也能用 + // // - 点昵称刷新 + // nickname.setOnClickListener { refreshUser(force = true, showToast = true) } + // // - 长按 time 刷新 + // time.setOnLongClickListener { + // refreshUser(force = true, showToast = true) + // true + // } + + logout.setOnClickListener { + LogoutDialogFragment { doLogout() } + .show(parentFragmentManager, "logout_dialog") + } + + view.findViewById(R.id.imgLeft).setOnClickListener { + // 使用事件总线打开充值页面 + AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.rechargeFragment)) + } + view.findViewById(R.id.imgRight).setOnClickListener { + // 使用事件总线打开金币充值页面 + AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.goldCoinRechargeFragment)) + } + view.findViewById(R.id.avatar).setOnClickListener { + safeNavigate(R.id.action_mineFragment_to_personalSettings) + } + view.findViewById(R.id.keyboard_settings).setOnClickListener { + safeNavigate(R.id.action_mineFragment_to_mykeyboard) + } + view.findViewById(R.id.click_Feedback).setOnClickListener { + safeNavigate(R.id.action_mineFragment_to_feedbackFragment) + } + view.findViewById(R.id.click_Notice).setOnClickListener { + safeNavigate(R.id.action_mineFragment_to_notificationFragment) + } + + // ✅ 监听登录成功/登出事件(跨 NavHost 可靠) + viewLifecycleOwner.lifecycleScope.launch { + viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { + AuthEventBus.events.collect { event -> + when (event) { + AuthEvent.LoginSuccess -> { + // 先从本地秒渲染,再强制打接口更新 + renderFromCache() + refreshUser(force = true, showToast = false) + } + else -> Unit + } } } } - - // 退出登录(先确认) - logout.setOnClickListener { - LogoutDialogFragment { - // ✅ 用户确认后才执行 - EncryptedSharedPreferencesUtil.remove(requireContext(), "Personal_information") - EncryptedSharedPreferencesUtil.remove(requireContext(), "user") - - // ⚠️ 建议用 popUpTo 清栈,避免按返回回到已登录页面 - findNavController().navigate(R.id.action_mineFragment_to_loginFragment) - }.show(parentFragmentManager, "logout_dialog") - } - - - // 会员充值按钮点击 - view.findViewById(R.id.imgLeft).setOnClickListener { - findNavController().navigate(R.id.action_global_rechargeFragment) - } - - // 金币充值按钮点击 - view.findViewById(R.id.imgRight).setOnClickListener { - findNavController().navigate(R.id.action_global_goldCoinRechargeFragment) - } - - // 头像点击 - view.findViewById(R.id.avatar).setOnClickListener { - findNavController().navigate(R.id.action_mineFragment_to_personalSettings) - } - - //我的键盘 - view.findViewById(R.id.keyboard_settings).setOnClickListener { - findNavController().navigate(R.id.action_mineFragment_to_mykeyboard) - } - - // 反馈按钮点击 - view.findViewById(R.id.click_Feedback).setOnClickListener { - findNavController().navigate(R.id.action_mineFragment_to_feedbackFragment) - } - - // 反馈按钮点击 - view.findViewById(R.id.click_Notice).setOnClickListener { - findNavController().navigate(R.id.action_mineFragment_to_notificationFragment) - } - - //隐私政策 - // view.findViewById(R.id.click_Privacy).setOnClickListener { - // findNavController().navigate(R.id.action_mineFragment_to_loginFragment) - // } - } + + override fun onResume() { + super.onResume() + // ✅ 回到页面先用缓存渲染一遍,再尝试刷新(不强制) + renderFromCache() + refreshUser(force = false) + } + + private fun renderFromCache() { + if (!isAdded) return + val cached = EncryptedSharedPreferencesUtil.get( + requireContext(), + "Personal_information", + LoginResponse::class.java + ) + nickname.text = cached?.nickName ?: "" + time.text = cached?.vipExpiry?.let { "Due on November $it" } ?: "" + } + + /** + * 刷新用户信息: + * - force=true:无条件打接口 + * - force=false:只要已登录就打一次(你可以后续加防抖,这里先保证“必能拿到数据”) + */ + private fun refreshUser(force: Boolean, showToast: Boolean = false) { + if (!isLoggedIn()) { + if (showToast && isAdded) Toast.makeText(requireContext(), "未登录", Toast.LENGTH_SHORT).show() + return + } + + loadUserJob?.cancel() + loadUserJob = viewLifecycleOwner.lifecycleScope.launch { + try { + val response = RetrofitClient.apiService.getUser() + if (!isAdded) return@launch + + val u = response.data + Log.d(TAG, "getUser ok: nick=${u?.nickName} vip=${u?.vipExpiry}") + + nickname.text = u?.nickName ?: "" + time.text = u?.vipExpiry?.let { "Due on November $it" } ?: "" + + EncryptedSharedPreferencesUtil.save(requireContext(), "Personal_information", u) + + if (showToast) Toast.makeText(requireContext(), "已刷新", 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(), "刷新失败", Toast.LENGTH_SHORT).show() + } + } + } + + private fun doLogout() { + viewLifecycleOwner.lifecycleScope.launch { + try { + val response = RetrofitClient.apiService.logout() + if (!isAdded) return@launch + + if (response.code == 0) { + EncryptedSharedPreferencesUtil.remove(requireContext(), "Personal_information") + EncryptedSharedPreferencesUtil.remove(requireContext(), "user") + + // 清空 UI + nickname.text = "" + time.text = "" + + // 触发登出事件,让MainActivity打开登录页面 + AuthEventBus.emit(AuthEvent.Logout(returnTabTag = "tab_mine")) + } else { + Log.e(TAG, "logout fail code=${response.code}") + } + } catch (e: Exception) { + Log.e(TAG, "logout exception", e) + } + } + } + private fun isLoggedIn(): Boolean { - return EncryptedSharedPreferencesUtil.contains(requireContext(), "user") + val ctx = context ?: return false + return EncryptedSharedPreferencesUtil.contains(ctx, "user") + } + + private fun safeNavigate(actionId: Int) { + if (!isAdded) return + if (parentFragmentManager.isStateSaved) return + + val navController: NavController = findNavController() + runCatching { navController.navigate(actionId) } + .onFailure { Log.e(TAG, "navigate error: $actionId", it) } + } + + companion object { + private const val TAG = "1314520-MineFragment" } } diff --git a/app/src/main/java/com/example/myapplication/ui/shop/ShopEvent.kt b/app/src/main/java/com/example/myapplication/ui/shop/ShopEvent.kt new file mode 100644 index 0000000..a2b9f15 --- /dev/null +++ b/app/src/main/java/com/example/myapplication/ui/shop/ShopEvent.kt @@ -0,0 +1,20 @@ +package com.example.myapplication.ui.shop + +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.asSharedFlow + +sealed class ShopEvent { + object ThemePurchased : ShopEvent() +} + +object ShopEventBus { + private val _events = MutableSharedFlow( + replay = 0, + extraBufferCapacity = 1 + ) + val events = _events.asSharedFlow() + + fun post(event: ShopEvent) { + _events.tryEmit(event) + } +} diff --git a/app/src/main/java/com/example/myapplication/ui/shop/ShopFragment.kt b/app/src/main/java/com/example/myapplication/ui/shop/ShopFragment.kt index 45be2a1..0b14ad5 100644 --- a/app/src/main/java/com/example/myapplication/ui/shop/ShopFragment.kt +++ b/app/src/main/java/com/example/myapplication/ui/shop/ShopFragment.kt @@ -1,6 +1,5 @@ package com.example.myapplication.ui.shop -import android.annotation.SuppressLint import android.animation.ArgbEvaluator import android.animation.ValueAnimator import android.graphics.Color @@ -14,41 +13,391 @@ import android.widget.HorizontalScrollView import android.widget.LinearLayout import android.widget.TextView import androidx.fragment.app.Fragment -import androidx.fragment.app.viewModels +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.widget.ViewPager2 import com.example.myapplication.R -import com.example.myapplication.network.ApiResponse -import com.example.myapplication.network.RetrofitClient -import com.example.myapplication.network.Theme -import com.example.myapplication.network.Wallet -import com.example.myapplication.network.themeStyle +import com.example.myapplication.network.* +import com.example.myapplication.utils.EncryptedSharedPreferencesUtil +import com.google.android.material.appbar.AppBarLayout +import kotlinx.coroutines.Job import kotlinx.coroutines.launch +import java.util.concurrent.atomic.AtomicBoolean class ShopFragment : Fragment(R.layout.fragment_shop) { + // ===== View ===== private lateinit var viewPager: ViewPager2 private lateinit var tagScroll: HorizontalScrollView private lateinit var tagContainer: LinearLayout private lateinit var balance: TextView private lateinit var swipeRefreshLayout: SwipeRefreshLayout - // 风格 tabs + // ===== Data ===== private var tabTitles: List = emptyList() private var styleIds: List = emptyList() - // ✅ 共享数据/缓存/加载都交给 VM - private val vm: ShopViewModel by viewModels() + // ===== ViewModel ===== + private lateinit var vm: ShopViewModel + + // ===== 状态控制 ===== + private var uiInited = false // ⭐ 核心:UI 是否已初始化 + private var loadJob: Job? = null + private val refreshing = AtomicBoolean(false) + private var pageCallback: ViewPager2.OnPageChangeCallback? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + vm = ViewModelProvider(this)[ShopViewModel::class.java] + } + + override fun onDestroyView() { + loadJob?.cancel() + pageCallback?.let { viewPager.unregisterOnPageChangeCallback(it) } + pageCallback = null + uiInited = false + super.onDestroyView() + } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + viewLifecycleOwner.lifecycleScope.launch { + viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { + ShopEventBus.events.collect { event -> + when (event) { + ShopEvent.ThemePurchased -> { + vm.clearCache() + refreshData() // ✅ 直接走你现有的刷新逻辑 + } + } + } + } + } + + viewLifecycleOwner.lifecycleScope.launch { + viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { + AuthEventBus.events.collect { event -> + when (event) { + AuthEvent.LoginSuccess -> { + // 登录态变化会影响钱包、主题列表、已购/可用状态:建议全量刷新 + if (!uiInited) { + uiInited = true + loadInitialData() + } else { + vm.clearCache() + refreshData() // 你已有:会 updateBalance + 重新拉主题 + forceLoadStyle + } + } + else -> Unit + } + } + } + } + + bindViews(view) + bindClicks(view) + setupSwipe() + fixViewPager2SwipeConflict() + + if (!uiInited) { + uiInited = true + loadInitialData() + } else { + // ⭐ 再切回来:只刷新轻量数据 + refreshBalanceOnly() + } + } + + // ========================== load ========================== + + private fun loadInitialData() { + loadJob?.cancel() + loadJob = viewLifecycleOwner.lifecycleScope.launch { + + // 钱包 + updateBalance(getwalletBalance()) + + // 主题 + val themeResp = getThemeList() + tabTitles = themeResp?.data ?: emptyList() + styleIds = tabTitles.map { it.id } + + setupViewPagerOnce() + setupTagsOnce() + + styleIds.firstOrNull()?.let { vm.loadStyleIfNeeded(it) } + } + } + + private fun refreshBalanceOnly() { + viewLifecycleOwner.lifecycleScope.launch { + updateBalance(getwalletBalance()) + } + } + + private fun refreshData() { + loadJob?.cancel() + loadJob = viewLifecycleOwner.lifecycleScope.launch { + try { + updateBalance(getwalletBalance()) + + val newThemes = getThemeList()?.data ?: emptyList() + if (newThemes != tabTitles) { + tabTitles = newThemes + styleIds = tabTitles.map { it.id } + + setupViewPagerOnce(force = true) + setupTagsOnce(force = true) + + vm.clearCache() + styleIds.forEach { vm.forceLoadStyle(it) } + } else { + styleIds.getOrNull(viewPager.currentItem) + ?.let { vm.forceLoadStyle(it) } + } + } catch (e: Exception) { + Log.e("ShopFragment", "refresh error", e) + } finally { + refreshing.set(false) + swipeRefreshLayout.isRefreshing = false + } + } + } + + // ========================== ViewPager ========================== + + private fun setupViewPagerOnce(force: Boolean = false) { + if (viewPager.adapter != null && !force) return + + pageCallback?.let { viewPager.unregisterOnPageChangeCallback(it) } + + viewPager.adapter = ShopPagerAdapter(this, styleIds) + viewPager.offscreenPageLimit = 1 + + pageCallback = object : ViewPager2.OnPageChangeCallback() { + override fun onPageSelected(position: Int) { + updateTagState(position) + styleIds.getOrNull(position)?.let { vm.loadStyleIfNeeded(it) } + } + } + viewPager.registerOnPageChangeCallback(pageCallback!!) + } + + private fun setupTagsOnce(force: Boolean = false) { + if (tagContainer.childCount > 0 && !force) return + + tagContainer.removeAllViews() + val density = resources.displayMetrics.density + + tabTitles.forEachIndexed { index, theme -> + val tv = TextView(requireContext()).apply { + text = theme.styleName + textSize = 12f + setPadding( + (16 * density).toInt(), + (6 * density).toInt(), + (16 * density).toInt(), + (6 * density).toInt() + ) + background = createCapsuleBackground() + isSelected = index == 0 + updateTagStyleNoAnim(this, isSelected) + setOnClickListener { viewPager.currentItem = index } + } + val gap = (6 * density).toInt() // 标签间距 6dp + + val lp = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ).apply { + marginEnd = if (index == tabTitles.lastIndex) 0 else gap + } + tagContainer.addView(tv, lp) + } + } + + private fun updateTagState(position: Int) { + for (i in 0 until tagContainer.childCount) { + val tv = tagContainer.getChildAt(i) as TextView + val selected = i == position + if (tv.isSelected != selected) { + tv.isSelected = selected + updateTagStyleWithAnim(tv, selected) + + if (selected) { + tv.post { + if (!isAdded) return@post + val scrollX = tv.left - (tagScroll.width - tv.width) / 2 + tagScroll.smoothScrollTo(scrollX, 0) + } + } + } + } + } + + // ========================== UI helpers ========================== + + private fun updateBalance(walletResp: ApiResponse?) { + val value = walletResp?.data?.balanceDisplay ?: 0 + val text = value.toString() + balance.text = text + adjustBalanceTextSize(text) + } + + private fun adjustBalanceTextSize(text: String) { + balance.textSize = when (text.length) { + in 0..3 -> 40f + 4 -> 36f + 5 -> 32f + 6 -> 28f + 7 -> 24f + 8 -> 22f + 9 -> 20f + else -> 16f + } + } + + private fun createCapsuleBackground(selected: Boolean = false): GradientDrawable = + GradientDrawable().apply { + val d = resources.displayMetrics.density + cornerRadius = 50f * d + if (selected) { + setColor(Color.WHITE) + setStroke((1 * d).toInt().coerceAtLeast(1), Color.parseColor("#02BEAC")) + } else { + setColor(Color.parseColor("#F1F1F1")) + setStroke(0, Color.TRANSPARENT) + } + } + + private fun updateTagStyleNoAnim(tv: TextView, selected: Boolean) { + tv.setTypeface(null, if (selected) Typeface.BOLD else Typeface.NORMAL) + tv.setTextColor(if (selected) Color.parseColor("#1B1F1A") else Color.parseColor("#9F9F9F")) + tv.background = createCapsuleBackground(selected) + } + + private fun updateTagStyleWithAnim(tv: TextView, selected: Boolean) { + val start = if (selected) Color.parseColor("#9F9F9F") else Color.parseColor("#1B1F1A") + val end = if (selected) Color.parseColor("#1B1F1A") else Color.parseColor("#9F9F9F") + ValueAnimator.ofObject(ArgbEvaluator(), start, end).apply { + duration = 150 + addUpdateListener { tv.setTextColor(it.animatedValue as Int) } + start() + } + tv.setTypeface(null, if (selected) Typeface.BOLD else Typeface.NORMAL) + tv.background = createCapsuleBackground(selected) + } + + private var appBarFullyExpanded = true + + private fun setupSwipe() { + swipeRefreshLayout.setOnRefreshListener { + if (refreshing.compareAndSet(false, true)) { + refreshData() + } else { + swipeRefreshLayout.isRefreshing = false + } + } + setupSwipeRefreshConflictFix() + } + + private fun setupSwipeRefreshConflictFix() { + val appBar = requireView().findViewById(R.id.appBar) + + // 1) 监听 AppBar 是否完全展开 + appBar.addOnOffsetChangedListener { _, verticalOffset -> + appBarFullyExpanded = (verticalOffset == 0) + } + + // 2) 核心:自定义"子 View 是否能向上滚"的判断 + swipeRefreshLayout.setOnChildScrollUpCallback { _, _ -> + // AppBar 没完全展开:不要让刷新抢手势(优先展开/折叠头部) + if (!appBarFullyExpanded) return@setOnChildScrollUpCallback true + // 找到 ViewPager2 当前页的 RecyclerView + val rv = findCurrentPageRecyclerView() + // rv 能向上滚:说明列表不在顶部 -> 禁止触发刷新 + rv?.canScrollVertically(-1) ?: false + } + } + + private fun findCurrentPageRecyclerView(): RecyclerView? { + // FragmentStateAdapter 默认 tag 通常是 "f0", "f1"... + val pos = viewPager.currentItem + val f = childFragmentManager.findFragmentByTag("f$pos") + return f?.view?.findViewById(R.id.recyclerView) + } + + private fun fixViewPager2SwipeConflict() { + (viewPager.getChildAt(0) as? RecyclerView)?.setOnTouchListener { v, e -> + when (e.actionMasked) { + MotionEvent.ACTION_DOWN -> { + // 不再在 ACTION_DOWN 时就 disallow,让父容器有机会判断 + false + } + MotionEvent.ACTION_MOVE -> { + // 只对横向滑动明显时 disallow + val dx = Math.abs(e.x - v.x) + val dy = Math.abs(e.y - v.y) + if (dx > dy * 2) { // 横向滑动明显 + v.parent?.requestDisallowInterceptTouchEvent(true) + } + false + } + MotionEvent.ACTION_UP, + MotionEvent.ACTION_CANCEL -> { + v.parent?.requestDisallowInterceptTouchEvent(false) + false + } + } + false + } + } + + // ========================== Adapter ========================== + + private inner class ShopPagerAdapter( + fragment: Fragment, + private val styleIds: List + ) : FragmentStateAdapter(fragment) { + override fun getItemCount() = styleIds.size + override fun createFragment(position: Int) = + ShopStylePageFragment.newInstance(styleIds[position]) + } + + // ========================== network ========================== + + private suspend fun getwalletBalance(): ApiResponse? = + runCatching { RetrofitClient.apiService.walletBalance() }.getOrNull() + + private suspend fun getThemeList(): ApiResponse>? = + runCatching { RetrofitClient.apiService.themeList() }.getOrNull() + + private fun bindViews(view: View) { + viewPager = view.findViewById(R.id.viewPager) + tagScroll = view.findViewById(R.id.tagScroll) + tagContainer = view.findViewById(R.id.tagContainer) + balance = view.findViewById(R.id.balance) + swipeRefreshLayout = view.findViewById(R.id.swipeRefreshLayout) + + swipeRefreshLayout.isEnabled = true + swipeRefreshLayout.setColorSchemeColors( + Color.parseColor("#02BEAC"), + Color.parseColor("#1B1F1A"), + Color.parseColor("#9F9F9F") + ) + } + + private fun bindClicks(view: View) { view.findViewById(R.id.rechargeButton).setOnClickListener { - findNavController().navigate(R.id.action_global_goldCoinRechargeFragment) + // 使用事件总线打开金币充值页面 + AuthEventBus.emit(AuthEvent.OpenGlobalPage(R.id.goldCoinRechargeFragment)) } view.findViewById(R.id.skinButton).setOnClickListener { findNavController().navigate(R.id.action_shopfragment_to_myskin) @@ -56,366 +405,7 @@ class ShopFragment : Fragment(R.layout.fragment_shop) { view.findViewById(R.id.searchButton).setOnClickListener { findNavController().navigate(R.id.action_shopfragment_to_searchfragment) } - - tagScroll = view.findViewById(R.id.tagScroll) - tagContainer = view.findViewById(R.id.tagContainer) - viewPager = view.findViewById(R.id.viewPager) - balance = view.findViewById(R.id.balance) - swipeRefreshLayout = view.findViewById(R.id.swipeRefreshLayout) - - // 设置下拉刷新监听器 - swipeRefreshLayout.setOnRefreshListener { - refreshData() - } - - // 设置刷新指示器颜色 - swipeRefreshLayout.setColorSchemeColors( - Color.parseColor("#02BEAC"), - Color.parseColor("#1B1F1A"), - Color.parseColor("#9F9F9F") - ) - - // 禁用默认的刷新行为,使用自定义逻辑 - swipeRefreshLayout.isEnabled = false - - // 设置 ViewPager 的子页面滚动监听 - setupViewPagerScrollListener() - - loadInitialData() - - // 修复 ViewPager2 和 SwipeRefreshLayout 的手势冲突 - fixViewPager2SwipeConflict() } - private fun loadInitialData() { - viewLifecycleOwner.lifecycleScope.launch { - val walletResp = getwalletBalance() - val balanceText = (walletResp?.data?.balanceDisplay ?: 0).toString() - balance.text = balanceText - adjustBalanceTextSize(balanceText) - - val themeListResp = getThemeList() - tabTitles = themeListResp?.data ?: emptyList() - Log.d("1314520-Shop", "风格列表: $tabTitles") - - styleIds = tabTitles.map { it.id } - - viewPager.adapter = ShopPagerAdapter(this@ShopFragment, styleIds) - - setupTags() - setupViewPager() - - // ✅ 默认加载第一个(交给 VM) - viewPager.post { - styleIds.firstOrNull()?.let { vm.loadStyleIfNeeded(it) } - } - } - } - - /** - * 根据字符数量调整余额文本的字体大小 - * 字符数量越多,字体越小 - */ - private fun adjustBalanceTextSize(text: String) { - val maxFontSize = 40f // 最大字体大小(sp) - val minFontSize = 16f // 最小字体大小(sp) - - // 根据字符数量计算字体大小 - val fontSize = when (text.length) { - 0, 1, 2, 3 -> maxFontSize // 0-3个字符使用最大字体 - 4 -> 36f - 5 -> 32f - 6 -> 28f - 7 -> 24f - 8 -> 22f - 9 -> 20f - else -> minFontSize // 10个字符及以上使用最小字体 - } - - balance.textSize = fontSize - } - - private fun refreshData() { - viewLifecycleOwner.lifecycleScope.launch { - try { - // 重新获取钱包余额 - val walletResp = getwalletBalance() - val balanceText = (walletResp?.data?.balanceDisplay ?: 0).toString() - balance.text = balanceText - adjustBalanceTextSize(balanceText) - - // 重新获取主题列表 - val themeListResp = getThemeList() - val newTabTitles = themeListResp?.data ?: emptyList() - - // 检查主题列表是否有变化 - if (newTabTitles != tabTitles) { - tabTitles = newTabTitles - styleIds = tabTitles.map { it.id } - - // 重新设置适配器 - viewPager.adapter = ShopPagerAdapter(this@ShopFragment, styleIds) - - // 重新设置标签 - setupTags() - - // 通知 ViewModel 清除缓存 - vm.clearCache() - - // 强制重新加载所有页面的数据 - styleIds.forEach { styleId -> - // 强制重新加载,即使有缓存也要重新获取 - vm.forceLoadStyle(styleId) - } - } else { - // 主题列表没有变化,强制重新加载当前页面的数据 - val currentPosition = viewPager.currentItem - styleIds.getOrNull(currentPosition)?.let { vm.forceLoadStyle(it) } - } - - Log.d("1314520-Shop", "下拉刷新完成") - } catch (e: Exception) { - Log.e("1314520-Shop", "下拉刷新失败", e) - } finally { - // 停止刷新动画 - swipeRefreshLayout.isRefreshing = false - } - } - } - - /** 子页读取缓存(从 VM 读) */ - fun getCachedList(styleId: Int): List = vm.getCached(styleId) - - /** 动态创建标签 */ - private fun setupTags() { - tagContainer.removeAllViews() - - val context = requireContext() - val density = context.resources.displayMetrics.density - val paddingHorizontal = (16 * density).toInt() - val paddingVertical = (6 * density).toInt() - val marginEnd = (8 * density).toInt() - - tabTitles.forEachIndexed { index, title -> - val tv = TextView(context).apply { - text = title.styleName - textSize = 12f - setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical) - - layoutParams = LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.MATCH_PARENT - ).apply { setMargins(0, 0, marginEnd, 0) } - - gravity = android.view.Gravity.CENTER - background = createCapsuleBackground() - - isSelected = index == 0 - updateTagStyleNoAnim(this, isSelected) - - setOnClickListener { - if (viewPager.currentItem != index) viewPager.currentItem = index - } - } - tagContainer.addView(tv) - } - } - - private fun createCapsuleBackground(): GradientDrawable { - val density = resources.displayMetrics.density - return GradientDrawable().apply { - shape = GradientDrawable.RECTANGLE - cornerRadius = 50f * density - setColor(Color.parseColor("#F1F1F1")) - setStroke((2 * density).toInt(), Color.parseColor("#F1F1F1")) - } - } - - private fun setupViewPager() { - // ✅ 只设置一次 - viewPager.offscreenPageLimit = 1 - - viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { - override fun onPageSelected(position: Int) { - super.onPageSelected(position) - updateTagState(position) - - // ✅ 切换到某页就按需加载(交给 VM) - styleIds.getOrNull(position)?.let { vm.loadStyleIfNeeded(it) } - } - }) - } - - private fun updateTagState(position: Int) { - for (i in 0 until tagContainer.childCount) { - val child = tagContainer.getChildAt(i) as TextView - val newSelected = i == position - if (child.isSelected == newSelected) continue - - child.isSelected = newSelected - updateTagStyleWithAnim(child, newSelected) - - if (newSelected) { - child.post { - val scrollX = child.left - (tagScroll.width - child.width) / 2 - tagScroll.smoothScrollTo(scrollX, 0) - } - } - } - } - - private fun setupViewPagerScrollListener() { - // 监听 AppBarLayout 的展开状态来判断是否在顶部 - view?.findViewById(R.id.appBar)?.addOnOffsetChangedListener { appBarLayout, verticalOffset -> - val isAtTop = verticalOffset == 0 - swipeRefreshLayout.isEnabled = isAtTop - } - } - - @SuppressLint("ClickableViewAccessibility") - private fun fixViewPager2SwipeConflict() { - val rv = viewPager.getChildAt(0) as? RecyclerView ?: return - rv.setOnTouchListener { v, ev -> - when (ev.actionMasked) { - MotionEvent.ACTION_DOWN -> v.parent?.requestDisallowInterceptTouchEvent(true) - MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> - v.parent?.requestDisallowInterceptTouchEvent(false) - } - false - } - } - - private fun updateTagStyleNoAnim(textView: TextView, selected: Boolean) { - val density = resources.displayMetrics.density - val bg = (textView.background as? GradientDrawable) - ?: createCapsuleBackground().also { textView.background = it } - val strokeWidth = (2 * density).toInt() - - if (selected) { - bg.setColor(Color.parseColor("#FFFFFF")) - bg.setStroke(strokeWidth, Color.parseColor("#02BEAC")) - textView.setTextColor(Color.parseColor("#1B1F1A")) - textView.setTypeface(null, Typeface.BOLD) - } else { - bg.setColor(Color.parseColor("#F1F1F1")) - bg.setStroke(strokeWidth, Color.parseColor("#F1F1F1")) - textView.setTextColor(Color.parseColor("#9F9F9F")) - textView.setTypeface(null, Typeface.NORMAL) - } - } - - private fun updateTagStyleWithAnim(textView: TextView, selected: Boolean) { - val density = resources.displayMetrics.density - val bg = (textView.background as? GradientDrawable) - ?: createCapsuleBackground().also { textView.background = it } - val strokeWidth = (2 * density).toInt() - - val selectedTextColor = Color.parseColor("#1B1F1A") - val unselectedTextColor = Color.parseColor("#9F9F9F") - val selectedStrokeColor = Color.parseColor("#02BEAC") - val unselectedStrokeColor = Color.parseColor("#F1F1F1") - val selectedBgColor = Color.parseColor("#FFFFFF") - val unselectedBgColor = Color.parseColor("#F1F1F1") - - val colorsArray = if (selected) { - arrayOf( - unselectedTextColor, selectedTextColor, - unselectedStrokeColor, selectedStrokeColor, - unselectedBgColor, selectedBgColor - ) - } else { - arrayOf( - selectedTextColor, unselectedTextColor, - selectedStrokeColor, unselectedStrokeColor, - selectedBgColor, unselectedBgColor - ) - } - - val startTextColor = colorsArray[0] - val endTextColor = colorsArray[1] - val startStrokeColor = colorsArray[2] - val endStrokeColor = colorsArray[3] - val startBgColor = colorsArray[4] - val endBgColor = colorsArray[5] - - val evaluator = ArgbEvaluator() - ValueAnimator.ofFloat(0f, 1f).apply { - duration = 200L - addUpdateListener { va -> - val f = va.animatedFraction - textView.setTextColor(evaluator.evaluate(f, startTextColor, endTextColor) as Int) - bg.setStroke(strokeWidth, evaluator.evaluate(f, startStrokeColor, endStrokeColor) as Int) - bg.setColor(evaluator.evaluate(f, startBgColor, endBgColor) as Int) - } - start() - } - - textView.setTypeface(null, if (selected) Typeface.BOLD else Typeface.NORMAL) - } - - private inner class ShopPagerAdapter( - fragment: Fragment, - private val styleIds: List - ) : FragmentStateAdapter(fragment) { - - override fun getItemCount(): Int = styleIds.size - - override fun createFragment(position: Int): Fragment { - val styleId = styleIds[position] - return ShopStylePageFragment.newInstance(styleId) - } - } - - // ============================ 网络请求 ============================ - - private suspend fun getwalletBalance(): ApiResponse? { - return try { - RetrofitClient.apiService.walletBalance() - } catch (e: Exception) { - Log.e("1314520-ShopFragment", "获取钱包余额失败", e) - null - } - } - - private suspend fun getThemeList(): ApiResponse>? { - return try { - RetrofitClient.apiService.themeList() - } catch (e: Exception) { - Log.e("1314520-ShopFragment", "获取主题风格失败", e) - null - } - } - /** - * 根据余额值计算字体大小 - * 基础字体大小16sp,数字越大字体越小 - */ - // private fun calculateFontSize(balance: Double): Float { - // val baseSize = 40f // 基础字体大小 - // val minSize = 5f // 最小字体大小 - // val maxSize = 40f // 最大字体大小 - - // // 使用对数函数实现平滑的字体大小变化 - // // 当余额为0时使用最大字体,余额越大字体越小 - // val scaleFactor = when { - // balance <= 0 -> 1.0 - // balance < 10 -> 0.93 - // balance < 100 -> 0.86 - // balance < 1000 -> 0.79 - // balance < 10000 -> 0.72 - // balance < 100000 -> 0.65 - // balance < 1000000 -> 0.58 - // balance < 10000000 -> 0.51 - // balance < 100000000 -> 0.44 - // balance < 1000000000 -> 0.37 - // balance < 10000000000 -> 0.3 - // balance < 100000000000 -> 0.23 - // balance < 1000000000000 -> 0.16 - // else -> 0.09 - // } - - // val calculatedSize = baseSize * scaleFactor.toFloat() - - // // 确保字体大小在最小和最大限制范围内 - // return calculatedSize.coerceIn(minSize, maxSize) - // } } + diff --git a/app/src/main/java/com/example/myapplication/ui/shop/ThemeCardAdapter.kt b/app/src/main/java/com/example/myapplication/ui/shop/ThemeCardAdapter.kt index 360362d..4aafab6 100644 --- a/app/src/main/java/com/example/myapplication/ui/shop/ThemeCardAdapter.kt +++ b/app/src/main/java/com/example/myapplication/ui/shop/ThemeCardAdapter.kt @@ -13,6 +13,8 @@ import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView 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.themeStyle import com.google.android.material.card.MaterialCardView @@ -54,7 +56,8 @@ class ThemeCardAdapter : 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

}YV-#Vn|x(CMd1yoZaxEJr(J;Z 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 diff --git a/app/src/main/res/drawable/home.png b/app/src/main/res/drawable/home.png index 41920276c478e11becfe6076900b70bce8d38e27..274874e036f4c04a36829b271034331ce0c66463 100644 GIT binary patch literal 1840 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 + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_mine_selector.xml b/app/src/main/res/drawable/ic_mine_selector.xml new file mode 100644 index 0000000..271dcfa --- /dev/null +++ b/app/src/main/res/drawable/ic_mine_selector.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_shop_selector.xml b/app/src/main/res/drawable/ic_shop_selector.xml new file mode 100644 index 0000000..9c9cd6e --- /dev/null +++ b/app/src/main/res/drawable/ic_shop_selector.xml @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/app/src/main/res/drawable/mine.png b/app/src/main/res/drawable/mine.png index b3a71379c98c94f2affd0d8dc237efc75b210a93..15a93179bf820fb845f1928bfe3dd8e24e0d8dbb 100644 GIT binary patch literal 2917 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 diff --git a/app/src/main/res/drawable/selected_circle.png b/app/src/main/res/drawable/selected_circle.png index 195942ffe955ece793d5444d68ab20c9a2faa437..cfa00ff8d6622116423586faa895791509c0dc31 100644 GIT binary patch literal 5327 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 literal 1557 zcmV+w2I~2VP)X1^@s6D=Y3@00001b5ch_0Itp) z=>Px)&q+i@n47x$YKPrk+SnsYn4xs&hFw_%4lw`XCA}cd~ z0C5=@^$h3gt;Q!x61XvP}W7hKR;8 z_@vT`xeX0YxvOng0%0^;my_3jNS3ReJwAW8%|EBTj>{Q+7KScLR@$ z3p4sPa|q%|0-NE*QlFONHAL%GT!0VAt{d3^6q96~OC}XHCX?BgMuNU$g%`?hXI>ZZiGt`jm@CXvAKyH9ZN@Bsp1S@?fp8r! z#;7me1qnj=`=6ol*DDzQ>Bdq;!P@V~&M)T>{C+n@ugWfGHW?-RdxEg|j=v=~*ex+J zy`waSD-6CpVo&ymhQzoW0HG@R&4Wd7d|ZIk{A}o=jre`#W+?4mqTG zVT#Wu#W>B+S>loMRy~%7{OhV))t)XF)Dkmgikw0NzhFt5E0QgjcvHSD#%3gl^ z`PixHNLtf>Ws4y%5s02|?ALt2UwadKHF!v8|4b=J?q{Xb#^U@#(V5 z`L$~GRK-t+9l80lYxW;SpE=WDePJGiE~Hx|btli_+NKX-7?6PEZEt|Int=}ZvoBdcK*EzONxq9I> zVr&R>#JLNo{k#yKUrWJ$wc!ALKRcwElMy>@B1DKb2;Nk76{U;TAbR3s=$Ew=%(&RO zO@+x~J3*jyzrr)doG)wzE5%)N!tGvo8=IgB(?b&$80v1)R^!H>OR@q^4BfK@+Q{DO zT)!J!*O8GnlL)0VL>R!N$sASu)j9wJAK0e=n#(Fsk+lhaPZI`x@Fv0r^iw}$5uyy~ zcF`gt;-fTrQAk8-5vh;3t;;gaVTtzpa;OEZ+4mLPUmkWMxtb<`-V!)mmd%j6} zWd47hOsz?>t|p>a0n!_W3_`@nVFq8#ajarzbD--nzAc+u9>Y7lK}rIp}Q{WQ9Qod?IwonS_M;&i4ls z{9`$;veKwkS{E?U3;;vbo!Ie@gmPwl%Zjr5bpPZ(?k(8gLHkZtzdqLh00000NkvXX Hu0mjfgx2*+ diff --git a/app/src/main/res/drawable/selected_home.png b/app/src/main/res/drawable/selected_home.png index 9fa464c3eb6d8b74673ee5fb9adc56d05bc33efd..01c5a45b48cbd844446b87a96d15bf57868916cd 100644 GIT binary patch literal 3771 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 literal 1147 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�bH7%`lIky@0` zBqg$rZ>hFY+!oXBw3zLf;1#VKi;2S{B~Npu z8OJ)Sj(cX$;APPQE&x_i;AGQoGzYDRWo5GT!tLJs0DniK<4;|RAV?i`@T#YT2EFs7 zpBeN{pFbjSuo{J9KH!pKP4~WCCx^Z@ChH?Hnn2N+@05s(KlQO~MSkm@$Gx-}H9YEWQm; zImPa>I;R|^eGZ8}zVvTk=r~ox)o&dx1)2!%-fzF!d<@QS-zk&|yl=eZ~9KQ8-) zupZhFPnqauWBoW~=quQpHCstXTNUdoy6kF)zZVl;+(x{!ov2FAZ~wiHpr{h>-SRx+ z;?ROkaEPbYZv~8Dc!jM!SN+C8pvRIzfjyIED*J-$NNA^u?CRtDy)srl0cnpc5Uz|l zXoK^Jne!Q7ycI4jlK6n3U_gk58$Fw`MFkoI9DeZJ_TR(#s$JZnB4|^qUIxrdsR9~) z(A*yd*i@G_likE_3jjXEZWkxi?UpiZo?U8Mc%o?;NJQk9+0fs;icuPjQ5u>8oU7W& zRF_SMKe}+?z9-U6Gc^-}da0-IxB{(PrR5G8&*N)sS>*!2XMGlbG zO~k%hH*bTsnzw}AqU)T!;o0E#&b%~A<$}FgGehg_t^mNELT{Zgyrl>UF9F#hy27`x zrO88Ylj?zrc1hTg*P)kWYQ{Yvxc=-b-vBpGinHk$9OhKMpyZKsHpVPz;USTRx~%(k zez$7?wDVJ6A?5U*%6V zd44w+K+ztOxi`nFyDBp(0PJ{{_x(esj+~B63L+t{b7PEay6rV@GPl&KAm?YTFXzND z##(xby>*S|rn)Sz=^Zq22SB-Q68x%^FjX|fYNaf4LfbKfSz;7`FgiZJ{Z+VW!S(ng z>io<#D`@0gr+mPus-A5WX0F?K3u`BPH|F3;#<6oXSy7tyTY+v@K5G+RSBnO>q zO-C8wagD;Rq!&L76UrWU@q!m9L^x54>C?#amAMTkZeEn5i0B{mL-9@v7NkSy#sw8wlxMuY1lg{*D~7}9{`k#_$&`*XlXanI~DL_4+ak> zK}rIE5&TQvr*Nh51NOU{f*e1-^ap@x27R%YfFL9IyAx!t-q*Gl7XYvWmyvU5OgQ18 zstZaFA`uJK=8ed%P1j>+^iovho}tXjmzn83RKxo2ub z?-Cmj0JJj+fdOP*&{jnFA_gi1eyWxy)g2- ly@_4TZvA*W4!8UM{{e*zwq`0Czt;c&002ovPDHLkV1jHli}U~h literal 1510 zcmVPx)ph-kQR7gvORcUZjRTTctP0}=7(j=6=Hf<6_p|k^tP^C^?z)@^zMMOjv!9hV0 z-0C*!SP+rHL1kP3Wf+hFml0$bR0<4LhJq|ps&62%1`q-S)GFWu3iGyr&vWcL9H47mnkCx|ka&*( zI~a8eb2$-ei4X+C#DpwjwB>fTl9zC1TqX}N$dkKmVsBBeXdUcDAxlrZGy{9e!M-rKN%S+Y$h z65lAy#mzp~N7o}SC@s~;4M8@uurlOMq0wE~e&d810BlKhYzHt=R+Ql_b?#b~M-@=J zSM2gYEgzaX%sc2nt>?hQK+{hQ|9 zexGwjSimINCJ7QdLyD3gsB`a)_TDVn*O3rUS#n1p&Yp_qU(cbf#*Lw`&OusXUNpS< z-13bVy?c*jcC~j}+uFSKWRe^k1W?%Ib7lYtMOv5#+U_KcD8K2Y*|0u1J{%k~qiV%Q zG?Z5&ck4=Mjqza<>IuBvc?rkoEQSJQZnM|DiOiDyG!xD>dtFnb-ANraW)o!P@!P)p z5ERjG9o|M%OnU`cOBZ6`xSXr9dU(IH=C5-uB#UHkWnhip=XyO-U{dvgTWVHq zKHgk$O5}X~em{~>pbbZh79n%-0;JrV8zsOv@yv3_!Hx@w>tD=NBM1>;S(DebG*Y0j z>fpDHWrwGoU$zz_R+qpya%f*F++Y3(=lX5P`Q`(}T9f+)uBPf#@k+3wVED&x%v1&Z z1p1=M=X|LbSx{Z7*Km@bL$cx2qPG!rUqbrKA{a8#5cvHpF74Qdv?=#t@C&oAB3BQ7 ze`*P0EJ?_IuXqPpB*#%E`2AjI!4-juTLePCs{2rD8=PytLjAr&;La{+660ZgqyV`iS76_cI!s%z1V%YLxSnkLPkx|MRt0m1*nK7@$=iH!z3aXD!ASio- z9xwdARG|G#4KDlYpm0&z{IFfn6;XCje%|qzr)GnhFu43r7*W;D!>s42p?CO3`@O=1qq- zF&=-{x^VKz*I=Di1joWzs_B`qKvJ?TM`-965h|H+9>AkIlTj;8Ekg2yyP&s9Jss4Y z3RW1cC(okp$1*gQ9mJp)=V4&}-S}g{o9Obl;O4JBhBhG%3iGqPB4tI%=5gB#v>7RmRI>xMH*_Y56fc+Dr%B-x4y zV)20ddpv1#rVTeZ)G>91oI^6&&s3p)=N>ec9e^&$h`~!bLN|->(?8NlZ*1potX^5Q$q2nS%?o2?;l7;tbH+(vdJC8%eoi)K-kN+AZsK^MAHw zUhF-*u0W*axc&RJ!k+pF0S|+bOMnEhI^O>TP|i%7e;Sf?B--JB0B9yZw&RRtHvj+t M07*qoM6N<$f>qhUfdBvi diff --git a/app/src/main/res/drawable/selected_shop.png b/app/src/main/res/drawable/selected_shop.png index 63cd79d83839cbfbd913141b4f074daf6688a3a8..5bfcf0192bd191b22a69955741dfd7c0abdcc98b 100644 GIT binary patch literal 4231 zcmV;25P0v2P)Px_K}keGRCr$PU3+j;)fxZJ4X**zBoY#+k`3AAC2Ce4fd*pIc7`OPY%1VrotlKP zR>wfn*VLc}tb{t9mLRlR9h0+~gOeW;J=kfjS`ObHK-*?VM5Je?E-VhICAV)yr-58+^zz~lB41gfs z-Ay~j;6Mns1BMf#D6~4x+1sON2&%h+R6n7^1Mw+_909~f08mi~)!PA3op>3xIvjRK z2+xn`BO?kxe3Bsp3Ah#^$Ou~t7#x65b*up~A^;FmBa9Qbg!snGV}-#XVpQztx7UXa zY6L2XH~{e}27>^&1&D3evtV33(08_6&nC2}JE8y(lOqVY#b;5~VhqeWFhDE5j0&T9 zZHO2Es+Etyfe{dI$AJLb31}E2;td(ptQi~hb)3_JKzIZJ#bBZ_3H{iVv3;>0B@jnh$vq~xmr^RvTXu@2q;Y}z||<4 zC95w0$*F_vw;z=c^x3Pm7(`$l3CXEemZubLYk_V6xcD7u!xdC8hW5d}90FW~UB8bI~-cNP)NaQ>(@iIz?md%-N03;-*?nVeK!LL6! z#37WXw*qcXF%)6IwX`?V?F}*a8EW6+aO8CZATcGCn1CR@CsI38Y3Ch>t#k(fmk;!v z)n)xr3x=KmV8-AhMv^6_q|*BUXv09SeWO}s=^;N707UHVW6eT{qWwU`0f@u`?0HjT z766wUCstyNGSF~5R_zR=^Ziof3L+Ic)Ts}sPAd}@Gy`1GDrxc3H(;U`&S;a@h+z!^ zKxr!+Qlp52ZG+eZu4U!+5G6^zw{>k(I4wA(O2}P5f!S*I1Uv6OGk?VMhh)~!{?&30^mex6`XJX4;8TNw!brgM6H0G<@Gai zWe1K>((;zCt!;gXw4meVaofXE9#x<$O<@O~--z*oOA0IYhz0azp;Fyr5T0LTZ@ z)#cNuodFixehXmO&21Mr1P`q$moY&<?4YzrJ^(N{2Kssulv@c+Vnt`$pw@4HXg#4n zB?rKqs&cq_={)7;5Vr3zW~T)T`T-yl3$PFL_5?kw+^Vt!@p|y6QPeCp<)&r8!NXYcd05E;+!!UJK z9#=Q8hzs}4%=TN1156MjnMwoBgVn=(I}em00QUI-uA%8Gbl%zlAFX|!+Q_t$AH%fb z`?)%R0m}E8miQ%vaRH!~3FYdITj;*d14Q|92P@Q6r;Dr{0Ll5;V5)eGuU!Fc*qff^ zmk{O;05hFjzk>}cYzJ#GhEPt(^9@=9DdJ5XS+$N@lM8^KbG3pH)a@~5`FTQtGeDPg zLUMcv1Ii)yK9G}-7*Mh2ki@;VgS!!?B=K?$i7j-w_Z)O?dKu2QcL3pRlJoC|X(fE7 zBCu9c*HH!l#09yBivhRpGcEB;jrRf|8w*fLMf>)KvAed5PE<%zI_|UmyZf4n zGibm(c$o{Lu#ZZg2lD3nmZ_`rV0!6KLt;1%EP05kWC?(6&+suP0PTBCS$^jtxByVg zg!%!%GHb5$VddEeUatg<4dF9CF1>!)b`(0RUWTh*U!p23tL^oW7^VYD=>UvPNrDAC zxAMI|2poHjS$_MeVE|-e0pS23cU*{QXzHqbm{zh9;%*opl43l-UH$4JoUPdfpY3d7 znu7_ZRLH3PeMs#bS-Cc7Mv;cdu6j}PYkU9zz+U6`{mj1a43LQhsAEEXH4s19U=ai? zOR|wc5Fn|j#b^WA2M;QQ+HnI-9!DoUHz?CaQ zY0W;IkPiSdv4AjB@ZwVpMFPfKl+m==lY-F`U8JIS^7JvEn3NJdJRV1Fkbd~Pkl~NG&lO}hWP-{ z;Ap4�r@STuHwKjImRaV1m)$niT+&T_?)E*lB0l_&@~_8$EmTFJXd-t68S`I$8Q0 z6M%U;x52n6Nqn9VzM9)$TI!9fcmYUEo>m43QFo+T9cm+)*JvExt#qvb*GM>oCQGj8 zN(sntOUF}xgn_mr)N1B#d)7T;Ia(2+c;Af0-T=)o05XTF)l$()-EbeEtK^*xO7+p+ zdZKt@aqp`0t}{MFoT?aNc?fPLC)=M`sK^X$b^ii+>Z7UvK(L`PeSx%ScxHfHEI^k_?(XS2S_>FQbud0q)5ljn&ZNHYdg~=1riiN` zsD3AXfka2R0g#CWXh22NI#pmhN?1_~kJsQELK;c=Q>D+s1?wrQj$Hsu=JJ97puW*K zU!o%v0nnNW_4K}=>!=m52Hy?fdgZhc`d9{lIoqC-Xc3-5*o7wJe2I>b0Fa9X=m)?t z&9fo+_~6jbeSGrN3ozJrn5tt5fV*zv3{4_?WBNQP*VY99I~JfD6I#%9Y><2-hO@_- zoR|qI80-^K=&ITd=NhRuaYFj~Cm|{S2i*N^G|rQB@0kItdzWxh-O)hpbLzShn6i2~_joP|LPBer+2Ni6^k9r$OemotgwbQjozk&10pPziZ%Y4Y z<(85M;FdKH@Q=soG&jyz*e(Ge6ARGg;|F=2M{)!qjy{*U-=WA0e*We@=y|b*+HlJ1 zZGsrF01a*fq4g-g>sT28Jp+S(1d*4#aQq~6l+qJ%Z#2(^+1r1|-zgE7H<{*D z%L5QbQm$N2^17^*NV?WOwiba4$4@~=>C@Dqxd0%CIQa4~u1RfZPB(9KdqMPAfL=^! zURQhVwM&~~iiRLsCozGOMf5LYjW?yi?RESIeK0^>bGo_MGXtox0KEXn@3ImaI{0F5 z{s}xHl0%>OL;Fhl`C>vtWbAr{yI&YXYqQaui`@5wQhjnQZUv;T0qs@*atTLlnIMw2 zacmhqO`VK0^WYwS6NIrF0N0o8sK-RLxEGTF00~9LL^ecV{|{%aV7}!GB>=dKy*WK2 z4JpI|bfKd2y4qtV7$2xkG6PsKfjf7-DlwwGr8zwVA-PYDXqA-f+o8M;s{zKKs6Lo2 zr@#~UKMF&={Zx^;b=5!?W8QLEzzIn10EHe*s0#ogW&t=^v<@zH(z`!vdle9Ol(#sY zq8Y`fFoH2UCFSOIT5~`UVvdIJD7E9s3i!%;lB#3V<_bv2Uc{?^08z|EGO++%n9w|% zwFppLE$@aU+T>3Eb`v<-KAs;LhgsVu3no8bQr#yUr85%PtCe8%V#&oIk z4ATn=0RRVLU-8bX((7^_4U9>d40r5Oclj4el>6lDb=|7cK-|O$V19Rpif53W%z&6B z##D?nVxsd8zQf%XmKI@|j~{c_bX`!=09gZO{`m!dZD3rDehFf7M&*yY^7)E31A}8{JhVN3bUqL9hHEp*4Dan!00GSD+ zVB9){NsiFBzg+t=ZS^-Ww2{2|p3#no2?|v8Fc1<)L}-ebr78l(X1{hBi5)QBb5%g~ dp10mt=Kr|5XNvS+;cNf^002ovPDHLkV1gBcw-5jT literal 1277 zcmVX1^@s6D=Y3@00001b5ch_0Itp) z=>Px(w@E}nR7gvemV0c|RTRg+=eA>;2wlt8j13=3mGKppZ>GI{t2 z0s#}E5sdOsK@*6)B0}O2M1vrx5Qd;4Lll8+j>yOc<nQ;=}D*!!8gh61g3rP92x8bU_Ge`%3j09~e*MOmsfk0u?^|~Vwqa=gz89`zv zGpgNA+fV@VL6H9hXi`m+RiIrg4q%0AFLKff_R|Y zVb|RQ=&IKn;zgoEGOzPE?QcW_^2)yx)E3wQrd%SZmAJRcipn`F&}Y$1q&+(-3`!_;xAlahIX z$7$aX-HwUpk6#9HMrRl5()t~!-~A(o?p%Y!UIsAZ(*CU6Ow#C$`6?j}vE(AR%f2IG zq)jzfgZcD`pT3wR65|si`_k72>*~+ZeD(r{?)>Bq*IxWBYPasiz%B3N;r_~;*|)#% z$VAeln5L*y^i3d$aoz^o!8?Ey<2(pj+a+16))!cikfw*P&WVPf|A4>IgN*q_NSid~ z4xnyV39fAT5(CyOhIUv^X#ZwYYZ7Vorq@W&X1~OUW|!?m`&RUsF+E=;REIn#E8%y0 z5vS82>4_ZldT|0C>TSHIYp#+~SXXXB*7Ai&&U-2p3kY>T1@IOL`q&@v_iMgZU(;SS z?))hW2`=rd|4O{E^b~5|S&iO{UV-7c{IEp8LRy1qB@r#Y)#5X>v^ZVu%?d7*O;(ZI z6$_xL;w;WBSPtW>FCcwJVMxM^sif7LKP7?J8y&VdrK)=>xLCFj%xhx-w4T3=zh}RR zp3^46JpZLI0JMO#2J=@0OlWl4xat`q+!*#Q@EU1rYGIpnPl*w3gw>TJ?5FB7tJ1g5N<%bUSQAqKyiye;oi} zTr2<%N}RS7qTAqX^xybFq=FJ<$W;V#G&*g0(MDsemE}aZ58M&3Z1gn5_tfLD?du~$ zu22AVOgQ0j*q@IU=3CFy5m8z!6(~7p3THv7WY7=WZjS)}kj`LgWuTr2x4#8$ExJXzRI_rqvSKyqEHA;Fj_j{Pp9tlRTG`=mi;|FcsX9ln nECyk4=w8OYBr__5BxnB%V?*E!)9i9X00000NkvXXu0mjfj1Oye diff --git a/app/src/main/res/drawable/shop.png b/app/src/main/res/drawable/shop.png index 16005cb53f83aecdc3cd6aec78c76fb8fdd9b5f3..aad52325cc1de5c6b3b107cd6178e51233ceb701 100644 GIT binary patch literal 2177 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 D?P~hM literal 933 zcmV;W16urvP)Px&Ur9tkR7gvum2HSrRT#(r|8vLPtY|SoEfA6|3t33)#SjW1tSrKcCaG9w24iW9 zZ0F9J-q~yi+qu`Qxp!p4^vm44ru0VIr=2o45r`q}C5<0*TB z;8}qjE6)kE0c;b&1Q?6wnwsy8m){aod=Y{XAs@) zyFL5=x#TJ5loovTr!;qb02u6l{!#|cQKaCKBbiUfT4c4 zkncHM*%ULgFDf!Gf?pvR0C5^%D;>JzcwlJbnARZ!Qfe3yEF(_KSIpA#_p1C)Xv|~^VwASkxOWCg|@C}wqw-t76 z8>u^|Df=;kheV^33DdDbSfvZah41dk{8Bfx+gVM)5rOnDVcNSvcK+~9an8_Crc^hy zE4!SA`W7N@F>cxi2tMk&)^+s)%ewaN*Ox>ja#{ohCQ{C)5LxEC>6;pXKGV5%Uh~y0 zzd>-QoYUg~=K8L+q7i5`8a1w2ykZK((Q;0QL5}-5>;6Wdms-_62V%4w{+I|(1g`aD z<51^EK#a1d7XbVu;PhMC$RP2!2qNX`mp{0rjllk+6@2#>JK}t_k8Ssj00000NkvXX Hu0mjf77e^W diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index aa61952..d1d4b51 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -7,16 +7,27 @@ android:layout_height="match_parent" tools:context=".MainActivity"> - - + android:layout_height="match_parent"> + + + + + + + + - - + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_empty.xml b/app/src/main/res/layout/fragment_empty.xml new file mode 100644 index 0000000..02cd488 --- /dev/null +++ b/app/src/main/res/layout/fragment_empty.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_forget_password_email.xml b/app/src/main/res/layout/fragment_forget_password_email.xml index c468711..17a44bd 100644 --- a/app/src/main/res/layout/fragment_forget_password_email.xml +++ b/app/src/main/res/layout/fragment_forget_password_email.xml @@ -53,7 +53,7 @@ android:textColor="#1B1F1A"/> + + + + + @@ -103,8 +103,8 @@ android:orientation="vertical"> @@ -127,8 +127,8 @@ android:orientation="vertical"> @@ -151,8 +151,8 @@ android:orientation="vertical"> diff --git a/app/src/main/res/layout/fragment_register.xml b/app/src/main/res/layout/fragment_register.xml index 11e2c87..3480ee8 100644 --- a/app/src/main/res/layout/fragment_register.xml +++ b/app/src/main/res/layout/fragment_register.xml @@ -99,7 +99,7 @@ - + + android:text="Next step" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_bottom_nav.xml b/app/src/main/res/menu/menu_bottom_nav.xml index e6e632c..f9aee97 100644 --- a/app/src/main/res/menu/menu_bottom_nav.xml +++ b/app/src/main/res/menu/menu_bottom_nav.xml @@ -2,24 +2,15 @@

+ android:id="@+id/home_graph" + android:icon="@drawable/ic_home_selector"/> - - + android:id="@+id/shop_graph" + android:icon="@drawable/ic_shop_selector"/> + android:id="@+id/mine_graph" + android:icon="@drawable/ic_mine_selector" /> - diff --git a/app/src/main/res/navigation/global_graph.xml b/app/src/main/res/navigation/global_graph.xml new file mode 100644 index 0000000..25035c3 --- /dev/null +++ b/app/src/main/res/navigation/global_graph.xml @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/home_graph.xml b/app/src/main/res/navigation/home_graph.xml new file mode 100644 index 0000000..207be59 --- /dev/null +++ b/app/src/main/res/navigation/home_graph.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/app/src/main/res/navigation/mine_graph.xml b/app/src/main/res/navigation/mine_graph.xml new file mode 100644 index 0000000..864693c --- /dev/null +++ b/app/src/main/res/navigation/mine_graph.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 62278c2..0cfbfba 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -3,285 +3,11 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_graph" - app:startDestination="@id/homeFragment"> + app:startDestination="@id/home_graph"> - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/app/src/main/res/navigation/shop_graph.xml b/app/src/main/res/navigation/shop_graph.xml new file mode 100644 index 0000000..c26acea --- /dev/null +++ b/app/src/main/res/navigation/shop_graph.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index b9300ba..eecab10 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -19,6 +19,7 @@ center 20sp 1 + number @drawable/code_box_bg #000000