diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 50ce187..2f6eac5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -38,7 +38,7 @@ + + diff --git a/app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt b/app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt index 9128989..aac0688 100644 --- a/app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt +++ b/app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt @@ -10,7 +10,7 @@ import android.text.TextUtils import android.view.View import android.view.ViewGroup import android.widget.TextView -import androidx.activity.ComponentActivity +import com.sw.inbound.base.BaseActivity import androidx.activity.viewModels import androidx.camera.view.PreviewView import androidx.core.view.updateLayoutParams @@ -68,7 +68,7 @@ import java.io.File */ @SuppressLint("NotifyDataSetChanged") @AndroidEntryPoint -class FoodCollectionActivity : ComponentActivity() { +class FoodCollectionActivity : BaseActivity() { companion object { const val TAG = "FoodCollectionActivity" diff --git a/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt b/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt index 4cb7c8e..e2bc48a 100644 --- a/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt +++ b/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt @@ -9,7 +9,7 @@ import android.text.style.ForegroundColorSpan import android.view.View import android.view.ViewGroup import android.widget.TextView -import androidx.activity.ComponentActivity +import com.sw.inbound.base.BaseActivity import androidx.activity.OnBackPressedCallback import androidx.activity.viewModels import androidx.camera.view.PreviewView @@ -70,7 +70,7 @@ import kotlin.math.min typealias RecognizeCallback = (List) -> Unit @AndroidEntryPoint -abstract class GoodsListActivity : ComponentActivity() { +abstract class GoodsListActivity : BaseActivity() { companion object { private const val TAG = "GoodsListActivity" diff --git a/app/src/main/java/com/sw/inbound/activity/HomeActivity.kt b/app/src/main/java/com/sw/inbound/activity/HomeActivity.kt new file mode 100644 index 0000000..0c685b6 --- /dev/null +++ b/app/src/main/java/com/sw/inbound/activity/HomeActivity.kt @@ -0,0 +1,131 @@ +package com.sw.inbound.activity + +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import androidx.activity.viewModels +import com.sw.inbound.base.BaseActivity +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import com.sw.inbound.databinding.ActivityHomeBinding +import com.sw.inbound.model.response.User +import com.sw.inbound.objbox.FoodModule +import com.sw.inbound.sdk.SensorScaleUtils +import com.sw.inbound.utils.DateTimeUtils +import com.sw.inbound.utils.ThreadUtils +import com.sw.inbound.utils.ext.gone +import com.sw.inbound.utils.ext.startActivity +import com.sw.inbound.utils.ext.visible +import com.sw.inbound.viewmodel.UserViewModel +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch + +/** + * 首页 Activity(XML 版本) + * 对应原 HomeScreen.kt Compose 版本,原文件保留不动 + * 功能:展示标题栏(含实时时间或用户信息)和两个功能入口(采购单入库、自采入库) + */ +@AndroidEntryPoint +class HomeActivity : BaseActivity() { + + private lateinit var binding: ActivityHomeBinding + + /** 用于获取用户信息的 ViewModel */ + private val viewModel: UserViewModel by viewModels() + + /** 每秒刷新当前时间的 Handler */ + private val handler = Handler(Looper.getMainLooper()) + + /** 时间刷新任务,每 1 秒更新一次标题栏右侧时间文字 */ + private val timeRunnable = object : Runnable { + override fun run() { + binding.tvTime.text = DateTimeUtils.getChineseDateString() + handler.postDelayed(this, 1000) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityHomeBinding.inflate(layoutInflater) + setContentView(binding.root) + initViews() + observeUser() + SensorScaleUtils.startScale(autoScale = true) + lifecycleScope.launch { + FoodModule.init(this@HomeActivity) + } + } + + override fun onDestroy() { + SensorScaleUtils.closeScale() + ThreadUtils.release() + super.onDestroy() + } + + /** + * 初始化各控件的点击事件 + */ + private fun initViews() { + // 标题点击:跳转菜品采集页面 + binding.tvTitle.setOnClickListener { + startActivity() + } + + // 采购单入库入口 + binding.ivOrderPurchase.setOnClickListener { + startActivity() + } + + // 自采入库入口,传入非采购单标志 + binding.ivOrderSelfProcurement.setOnClickListener { + startActivity { + putExtra(GoodsListActivity.IS_RECEIPT_PAGE, false) + } + } + } + + /** + * 观察用户登录状态,动态切换标题栏右侧显示内容: + * - 已登录:显示用户名 + 退出图标 + * - 未登录:显示实时时间 + */ + private fun observeUser() { + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.user.collect { user -> + updateUserView(user) + } + } + } + } + + /** + * 根据登录状态切换标题栏右侧 UI + * @param user 当前用户信息,为 null 表示未登录 + */ + private fun updateUserView(user: User?) { + if (user != null) { + // 已登录:显示用户名和退出图标,隐藏时间 + binding.tvTime.gone() + binding.llUserInfo.visible() + binding.tvUserName.text = user.name ?: "用户" + } else { + // 未登录:显示实时时间,隐藏用户信息 + binding.llUserInfo.gone() + binding.tvTime.visible() + } + } + + override fun onResume() { + super.onResume() + // 页面可见时启动时间刷新 + handler.post(timeRunnable) + } + + override fun onPause() { + super.onPause() + // 页面不可见时停止刷新,避免内存泄漏 + handler.removeCallbacks(timeRunnable) + } +} diff --git a/app/src/main/java/com/sw/inbound/activity/LocalImagePreviewActivity.kt b/app/src/main/java/com/sw/inbound/activity/LocalImagePreviewActivity.kt index e62d3e3..dd59d8a 100644 --- a/app/src/main/java/com/sw/inbound/activity/LocalImagePreviewActivity.kt +++ b/app/src/main/java/com/sw/inbound/activity/LocalImagePreviewActivity.kt @@ -4,7 +4,7 @@ import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.ViewGroup -import androidx.activity.ComponentActivity +import com.sw.inbound.base.BaseActivity import androidx.recyclerview.widget.GridLayoutManager import coil.load import com.chad.library.adapter4.BaseQuickAdapter @@ -15,7 +15,7 @@ import com.sw.inbound.dialog.Loading import com.sw.inbound.utils.ext.copyText import java.io.File -class LocalImagePreviewActivity : ComponentActivity() { +class LocalImagePreviewActivity : BaseActivity() { private lateinit var binding: ActivityLocalImagePreviewBinding diff --git a/app/src/main/java/com/sw/inbound/activity/PurchaseOrderActivity.kt b/app/src/main/java/com/sw/inbound/activity/PurchaseOrderActivity.kt index c13a034..20409dd 100644 --- a/app/src/main/java/com/sw/inbound/activity/PurchaseOrderActivity.kt +++ b/app/src/main/java/com/sw/inbound/activity/PurchaseOrderActivity.kt @@ -2,7 +2,7 @@ package com.sw.inbound.activity import android.annotation.SuppressLint import android.os.Bundle -import androidx.activity.ComponentActivity +import com.sw.inbound.base.BaseActivity import androidx.activity.viewModels import androidx.compose.runtime.collectAsState import androidx.lifecycle.lifecycleScope @@ -24,7 +24,7 @@ import kotlinx.coroutines.launch * 采购单列表 */ @AndroidEntryPoint -class PurchaseOrderActivity : ComponentActivity() { +class PurchaseOrderActivity : BaseActivity() { private var list = mutableListOf() private val adapter by lazy { diff --git a/app/src/main/java/com/sw/inbound/base/BaseActivity.kt b/app/src/main/java/com/sw/inbound/base/BaseActivity.kt new file mode 100644 index 0000000..c5e04e3 --- /dev/null +++ b/app/src/main/java/com/sw/inbound/base/BaseActivity.kt @@ -0,0 +1,51 @@ +package com.sw.inbound.base + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsControllerCompat + +/** + * 所有 Activity 的基类 + * - 继承 ComponentActivity,保持与项目其他 Activity 一致 + * - 自动隐藏状态栏和导航栏,实现全屏沉浸式体验 + * - 在屏幕底部上滑时可临时唤出导航栏,松手后自动收回 + */ +abstract class BaseActivity : ComponentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + hideSystemBars() + } + + /** + * 窗口焦点变化时回调 + * 场景:弹出 Dialog 后焦点丢失,Dialog 消失后焦点恢复,此时需重新隐藏系统栏, + * 避免系统栏在 Dialog 关闭后意外"复活" + */ + override fun onWindowFocusChanged(hasFocus: Boolean) { + super.onWindowFocusChanged(hasFocus) + if (hasFocus) { + hideSystemBars() + } + } + + /** + * 隐藏状态栏和导航栏 + * 使用 WindowInsetsControllerCompat(Androidx 推荐方式,向下兼容性好) + * - 状态栏:完全隐藏 + * - 导航栏:完全隐藏,底部上滑时临时出现,松手后自动收回(BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) + */ + private fun hideSystemBars() { + // 允许布局延伸到系统栏区域(edge-to-edge),避免内容被系统栏遮挡 + WindowCompat.setDecorFitsSystemWindows(window, false) + WindowInsetsControllerCompat(window, window.decorView).apply { + // 同时隐藏状态栏和导航栏 + hide(WindowInsetsCompat.Type.systemBars()) + // 底部上滑时临时显示导航栏,松手后自动隐藏(沉浸式 Sticky 模式) + systemBarsBehavior = + WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + } + } +} diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml new file mode 100644 index 0000000..26dac8b --- /dev/null +++ b/app/src/main/res/layout/activity_home.xml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +