feat(activity): 新增 BaseActivity 沉浸式基类和 HomeActivity 首页,统一 Activity 继承关系
- 新增 BaseActivity:继承 ComponentActivity,隐藏状态栏和导航栏,底部上滑可临时唤出导航栏 - 新增 HomeActivity(XML 版本)及对应布局 activity_home.xml,作为应用启动入口 - GoodsListActivity、FoodCollectionActivity、LocalImagePreviewActivity、PurchaseOrderActivity 统一改为继承 BaseActivity - 更新 AndroidManifest.xml:HomeActivity 注册为启动入口 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -38,7 +38,7 @@
|
|||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".activity.HomeActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
@@ -59,6 +59,10 @@
|
|||||||
android:windowSoftInputMode="adjustPan" />
|
android:windowSoftInputMode="adjustPan" />
|
||||||
<activity android:name="com.sw.inbound.activity.LocalImagePreviewActivity" />
|
<activity android:name="com.sw.inbound.activity.LocalImagePreviewActivity" />
|
||||||
<activity android:name="com.sw.inbound.activity.PurchaseOrderActivity" />
|
<activity android:name="com.sw.inbound.activity.PurchaseOrderActivity" />
|
||||||
|
<!-- 首页 Activity(XML 版本,对应 HomeScreen.kt Compose 版本) -->
|
||||||
|
<activity
|
||||||
|
android:name="com.sw.inbound.MainActivity"
|
||||||
|
android:screenOrientation="landscape" />
|
||||||
|
|
||||||
<!-- <activity-->
|
<!-- <activity-->
|
||||||
<!-- android:name=".InitActivity"-->
|
<!-- android:name=".InitActivity"-->
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import android.text.TextUtils
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.activity.ComponentActivity
|
import com.sw.inbound.base.BaseActivity
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.camera.view.PreviewView
|
import androidx.camera.view.PreviewView
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
@@ -68,7 +68,7 @@ import java.io.File
|
|||||||
*/
|
*/
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class FoodCollectionActivity : ComponentActivity() {
|
class FoodCollectionActivity : BaseActivity() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "FoodCollectionActivity"
|
const val TAG = "FoodCollectionActivity"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import android.text.style.ForegroundColorSpan
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.activity.ComponentActivity
|
import com.sw.inbound.base.BaseActivity
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.camera.view.PreviewView
|
import androidx.camera.view.PreviewView
|
||||||
@@ -70,7 +70,7 @@ import kotlin.math.min
|
|||||||
typealias RecognizeCallback = (List<SearchGoodsInfo.Record>) -> Unit
|
typealias RecognizeCallback = (List<SearchGoodsInfo.Record>) -> Unit
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
abstract class GoodsListActivity : ComponentActivity() {
|
abstract class GoodsListActivity : BaseActivity() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "GoodsListActivity"
|
private const val TAG = "GoodsListActivity"
|
||||||
|
|||||||
@@ -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<FoodCollectionActivity>()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 采购单入库入口
|
||||||
|
binding.ivOrderPurchase.setOnClickListener {
|
||||||
|
startActivity<PurchaseOrderActivity>()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自采入库入口,传入非采购单标志
|
||||||
|
binding.ivOrderSelfProcurement.setOnClickListener {
|
||||||
|
startActivity<SelfProcurementActivity> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import android.content.Context
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.activity.ComponentActivity
|
import com.sw.inbound.base.BaseActivity
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import coil.load
|
import coil.load
|
||||||
import com.chad.library.adapter4.BaseQuickAdapter
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
@@ -15,7 +15,7 @@ import com.sw.inbound.dialog.Loading
|
|||||||
import com.sw.inbound.utils.ext.copyText
|
import com.sw.inbound.utils.ext.copyText
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class LocalImagePreviewActivity : ComponentActivity() {
|
class LocalImagePreviewActivity : BaseActivity() {
|
||||||
|
|
||||||
private lateinit var binding: ActivityLocalImagePreviewBinding
|
private lateinit var binding: ActivityLocalImagePreviewBinding
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package com.sw.inbound.activity
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import com.sw.inbound.base.BaseActivity
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@@ -24,7 +24,7 @@ import kotlinx.coroutines.launch
|
|||||||
* 采购单列表
|
* 采购单列表
|
||||||
*/
|
*/
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class PurchaseOrderActivity : ComponentActivity() {
|
class PurchaseOrderActivity : BaseActivity() {
|
||||||
|
|
||||||
private var list = mutableListOf<SupplierInfo>()
|
private var list = mutableListOf<SupplierInfo>()
|
||||||
private val adapter by lazy {
|
private val adapter by lazy {
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@mipmap/bg"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<!-- 标题栏区域,与 TopTitleBar Compose 组件对应 -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingStart="60dp"
|
||||||
|
android:paddingEnd="60dp"
|
||||||
|
android:paddingTop="22dp">
|
||||||
|
|
||||||
|
<!-- 标题文字,点击可跳转菜品采集页面 -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTitle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:text="出入库管理"
|
||||||
|
android:textColor="@color/title"
|
||||||
|
android:textSize="36sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<!-- 占位弹性空间 -->
|
||||||
|
<Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
<!-- 当前时间文字(用户未登录时显示) -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTime"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:visibility="visible" />
|
||||||
|
|
||||||
|
<!-- 用户信息区(已登录时显示,未登录隐藏) -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/llUserInfo"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvUserName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="21dp"
|
||||||
|
android:layout_height="1dp" />
|
||||||
|
|
||||||
|
<!-- 退出登录图标 -->
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivLogout"
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:contentDescription="退出"
|
||||||
|
android:src="@mipmap/ic_logout" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- 功能入口区域,水平居中排列两个入口图标 -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<!-- 采购单入库入口 -->
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivOrderPurchase"
|
||||||
|
android:layout_width="595dp"
|
||||||
|
android:layout_height="477dp"
|
||||||
|
android:contentDescription="采购单入库"
|
||||||
|
android:src="@mipmap/ic_order_purchase" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="15dp"
|
||||||
|
android:layout_height="1dp" />
|
||||||
|
|
||||||
|
<!-- 自采入库入口 -->
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivOrderSelfProcurement"
|
||||||
|
android:layout_width="595dp"
|
||||||
|
android:layout_height="477dp"
|
||||||
|
android:contentDescription="自采入库"
|
||||||
|
android:src="@mipmap/ic_order_self_procurement" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
Reference in New Issue
Block a user