Update Android app login, home, and face verification flows.

Sync current local UI and activity changes to remote repository.

Made-with: Cursor
This commit is contained in:
2026-04-27 15:39:47 +08:00
parent 2e6aba459c
commit b47704b281
24 changed files with 876 additions and 204 deletions

View File

@@ -5,17 +5,75 @@ import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.Fragment
import com.example.defenseapplication.R
import com.example.defenseapplication.databinding.HomeActivityBinding
import com.example.defenseapplication.databinding.HomeMenuFragmentBinding
class HomeActivity : AppCompatActivity() {
// ViewBinding 核心对象
private lateinit var binding: HomeActivityBinding
// 定义两个 Fragment
private val homeMenuFragment = HomeMenuFragment()
private val personalFragment = PersonalFragment()
// 当前显示的 Fragment
private var currentFragment: Fragment = homeMenuFragment
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.home_activity)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
// 初始化 ViewBinding
binding = HomeActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
// 默认显示首页
switchFragment(homeMenuFragment)
// 第一次加载,只 add 首页
supportFragmentManager.beginTransaction()
.add(R.id.fragment_container, homeMenuFragment)
.commit()
// ========== 首页点击 ==========
binding.tabHome.setOnClickListener {
switchFragment(homeMenuFragment)
// 切换图标 + 文字颜色
binding.ivHome.setImageResource(R.drawable.home_checked)
binding.tvHome.setTextColor(resources.getColor(R.color.ic_selected))
binding.ivProfile.setImageResource(R.drawable.profile)
binding.tvProfile.setTextColor(resources.getColor(R.color.ic_normal))
}
// ========== 个人点击 ==========
binding.tabProfile.setOnClickListener {
switchFragment(personalFragment)
// 切换图标 + 文字颜色
binding.ivHome.setImageResource(R.drawable.home)
binding.tvHome.setTextColor(resources.getColor(R.color.ic_normal))
binding.ivProfile.setImageResource(R.drawable.profile_checked)
binding.tvProfile.setTextColor(resources.getColor(R.color.ic_selected))
}
}
/**
* 切换 Fragment 的方法
*/
private fun switchFragment(fragment: Fragment) {
if (currentFragment == fragment) return
val transaction = supportFragmentManager.beginTransaction()
// 如果没添加过,才 add
if (!fragment.isAdded) {
transaction.add(R.id.fragment_container, fragment)
}
// 隐藏当前,显示目标
transaction.hide(currentFragment)
transaction.show(fragment)
transaction.commit()
currentFragment = fragment
}
}

View File

@@ -6,55 +6,24 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.defenseapplication.R
import com.example.defenseapplication.databinding.HomeMenuFragmentBinding
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [HomeMenuFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class HomeMenuFragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
// ViewBinding
private var _binding: HomeMenuFragmentBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.home_menu_fragment, container, false)
): View {
_binding = HomeMenuFragmentBinding.inflate(inflater, container, false)
return binding.root
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment HomeMenuFragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
HomeMenuFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null // 避免内存泄漏
}
}

View File

@@ -6,55 +6,24 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.defenseapplication.R
import com.example.defenseapplication.databinding.PersonalFragmentBinding
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [PersonalFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class PersonalFragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
// ViewBinding
private var _binding: PersonalFragmentBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.personal_fragment, container, false)
): View {
_binding = PersonalFragmentBinding.inflate(inflater, container, false)
return binding.root
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment PersonalFragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
PersonalFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null // 避免内存泄漏
}
}