From b653b90d4598ee2a65bceffa793bb75353b6d186 Mon Sep 17 00:00:00 2001
From: cloudroam <cloudroam>
Date: 星期三, 26 二月 2025 17:21:53 +0800
Subject: [PATCH] add: 快递列表展示
---
app/src/main/java/com/example/firstapp/adapter/ExpressAdapter.kt | 87 ++++++++
app/src/main/java/com/example/firstapp/database/repository/CodeRepository.kt | 4
app/src/main/java/com/example/firstapp/model/ExpressGroup.kt | 12 +
app/src/main/res/navigation/mobile_navigation.xml | 2
app/src/main/java/com/example/firstapp/adapter/ReminderAdapter.kt | 1
app/src/main/res/layout/item_express_package.xml | 46 ++++
app/src/main/java/com/example/firstapp/database/dao/CodeDao.kt | 7
app/src/main/res/layout/fragment_home.xml | 130 ++++++++++--
app/src/main/java/com/example/firstapp/ui/home/HomeViewModel.kt | 62 ++++-
app/src/main/res/drawable/location.png | 0
app/src/main/java/com/example/firstapp/database/dao/ReminderDao.kt | 3
app/src/main/java/com/example/firstapp/ui/home/HomeFragment.kt | 82 +++++--
app/src/main/java/com/example/firstapp/MainActivity.kt | 62 +++---
app/src/main/java/com/example/firstapp/database/repository/ReminderRepository.kt | 5
app/src/main/res/layout/item_express_group.xml | 54 +++++
15 files changed, 459 insertions(+), 98 deletions(-)
diff --git a/app/src/main/java/com/example/firstapp/MainActivity.kt b/app/src/main/java/com/example/firstapp/MainActivity.kt
index df33c98..6abffe0 100644
--- a/app/src/main/java/com/example/firstapp/MainActivity.kt
+++ b/app/src/main/java/com/example/firstapp/MainActivity.kt
@@ -66,10 +66,10 @@
// logout()
// }
// 在此位置初始化 homeViewModel
- homeViewModel = ViewModelProvider(this).get(HomeViewModel::class.java)
-
- val navView: BottomNavigationView = binding.navView
-
+// homeViewModel = ViewModelProvider(this).get(HomeViewModel::class.java)
+//
+// val navView: BottomNavigationView = binding.navView
+ val navView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_activity_main)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
@@ -91,34 +91,34 @@
registerSmsReceiver()
syncRecentSms()
}
- val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
- recyclerView.layoutManager = LinearLayoutManager(this)
+// val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
+// recyclerView.layoutManager = LinearLayoutManager(this)
+//
+// // 初始化适配器
+// adapter = MyAdapter()
+// recyclerView.adapter = adapter
+//
+// // 观察 LiveData 数据
+// homeViewModel.codeList.observe(this) { codeList ->
+// // 如果 codeList 为 null,避免闪退
+// if (codeList != null) {
+// adapter.submitList(codeList)
+// // 滚动到顶部
+// recyclerView.scrollToPosition(0)
+// } else {
+// // 如果数据为空,可以显示空列表或其他处理
+// Toast.makeText(this, "No data available", Toast.LENGTH_SHORT).show()
+// }
+// }
- // 初始化适配器
- adapter = MyAdapter()
- recyclerView.adapter = adapter
-
- // 观察 LiveData 数据
- homeViewModel.codeList.observe(this) { codeList ->
- // 如果 codeList 为 null,避免闪退
- if (codeList != null) {
- adapter.submitList(codeList)
- // 滚动到顶部
- recyclerView.scrollToPosition(0)
- } else {
- // 如果数据为空,可以显示空列表或其他处理
- Toast.makeText(this, "No data available", Toast.LENGTH_SHORT).show()
- }
- }
-
- // 注册广播接收器来监听数据更新
- val filter = IntentFilter("com.example.firstapp.DATA_UPDATED")
- registerReceiver(object : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent) {
- // 数据已更新,刷新 LiveData
- homeViewModel.loadData()
- }
- }, filter)
+// // 注册广播接收器来监听数据更新
+// val filter = IntentFilter("com.example.firstapp.DATA_UPDATED")
+// registerReceiver(object : BroadcastReceiver() {
+// override fun onReceive(context: Context, intent: Intent) {
+// // 数据已更新,刷新 LiveData
+// homeViewModel.loadData()
+// }
+// }, filter)
}
diff --git a/app/src/main/java/com/example/firstapp/adapter/ExpressAdapter.kt b/app/src/main/java/com/example/firstapp/adapter/ExpressAdapter.kt
new file mode 100644
index 0000000..2445433
--- /dev/null
+++ b/app/src/main/java/com/example/firstapp/adapter/ExpressAdapter.kt
@@ -0,0 +1,87 @@
+package com.example.firstapp.adapter
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import androidx.recyclerview.widget.ListAdapter
+import com.example.firstapp.databinding.ItemExpressGroupBinding
+import com.example.firstapp.databinding.ItemExpressPackageBinding
+import androidx.recyclerview.widget.DiffUtil
+import com.example.firstapp.model.ExpressGroup
+import com.example.firstapp.model.ExpressPackage
+
+class ExpressAdapter : ListAdapter<ExpressGroup, ExpressAdapter.ViewHolder>(ExpressGroupDiffCallback()) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val binding = ItemExpressGroupBinding.inflate(
+ LayoutInflater.from(parent.context), parent, false
+ )
+ return ViewHolder(binding)
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ val group = getItem(position)
+ holder.bind(group)
+ }
+
+ class ViewHolder(private val binding: ItemExpressGroupBinding) : RecyclerView.ViewHolder(binding.root) {
+ private val packagesAdapter = ExpressPackageAdapter()
+
+ init {
+ binding.rvPackages.apply {
+ layoutManager = LinearLayoutManager(context)
+ adapter = packagesAdapter
+ }
+ }
+
+ fun bind(group: ExpressGroup) {
+ binding.tvStationName.text = group.stationName
+ binding.tvPackageCount.text = "共${group.packages.size}个包裹"
+ packagesAdapter.submitList(group.packages)
+ }
+ }
+}
+
+class ExpressPackageAdapter : ListAdapter<ExpressPackage, ExpressPackageAdapter.ViewHolder>(ExpressPackageDiffCallback()) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val binding = ItemExpressPackageBinding.inflate(
+ LayoutInflater.from(parent.context), parent, false
+ )
+ return ViewHolder(binding)
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ val pack = getItem(position)
+ holder.bind(pack)
+ }
+
+ class ViewHolder(private val binding: ItemExpressPackageBinding) : RecyclerView.ViewHolder(binding.root) {
+ fun bind(pack: ExpressPackage) {
+ binding.tvCompany.text = pack.company
+ binding.tvTrackingNumber.text = pack.trackingNumber
+ binding.tvDate.text = pack.date
+ }
+ }
+}
+
+private class ExpressGroupDiffCallback : DiffUtil.ItemCallback<ExpressGroup>() {
+ override fun areItemsTheSame(oldItem: ExpressGroup, newItem: ExpressGroup): Boolean {
+ return oldItem.stationName == newItem.stationName
+ }
+
+ override fun areContentsTheSame(oldItem: ExpressGroup, newItem: ExpressGroup): Boolean {
+ return oldItem == newItem
+ }
+}
+
+private class ExpressPackageDiffCallback : DiffUtil.ItemCallback<ExpressPackage>() {
+ override fun areItemsTheSame(oldItem: ExpressPackage, newItem: ExpressPackage): Boolean {
+ return oldItem.trackingNumber == newItem.trackingNumber
+ }
+
+ override fun areContentsTheSame(oldItem: ExpressPackage, newItem: ExpressPackage): Boolean {
+ return oldItem == newItem
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/firstapp/adapter/ReminderAdapter.kt b/app/src/main/java/com/example/firstapp/adapter/ReminderAdapter.kt
index e4a2ade..3a579bc 100644
--- a/app/src/main/java/com/example/firstapp/adapter/ReminderAdapter.kt
+++ b/app/src/main/java/com/example/firstapp/adapter/ReminderAdapter.kt
@@ -5,7 +5,6 @@
import androidx.recyclerview.widget.RecyclerView
import com.example.firstapp.database.entity.Reminder
import com.example.firstapp.databinding.ItemReminderBinding
-import com.sun.mail.imap.protocol.FetchResponse.getItem
class ReminderAdapter(private val onDelete: (Reminder) -> Unit) :
ListAdapter<Reminder, ReminderAdapter.ReminderViewHolder>(ReminderDiffCallback()) {
diff --git a/app/src/main/java/com/example/firstapp/database/dao/CodeDao.kt b/app/src/main/java/com/example/firstapp/database/dao/CodeDao.kt
index 8df5a2b..64e658e 100644
--- a/app/src/main/java/com/example/firstapp/database/dao/CodeDao.kt
+++ b/app/src/main/java/com/example/firstapp/database/dao/CodeDao.kt
@@ -41,4 +41,11 @@
@Query("SELECT * FROM Code order by time desc")
abstract fun getAllCodesDesc(): List<Code>
+
+ @Query("""
+ SELECT * FROM Code
+ WHERE type LIKE '%' || :keyword || '%'
+ ORDER BY time DESC
+ """)
+ fun getByKeyword(keyword: String): List<Code>
}
diff --git a/app/src/main/java/com/example/firstapp/database/dao/ReminderDao.kt b/app/src/main/java/com/example/firstapp/database/dao/ReminderDao.kt
index 59d5af1..e0cd71f 100644
--- a/app/src/main/java/com/example/firstapp/database/dao/ReminderDao.kt
+++ b/app/src/main/java/com/example/firstapp/database/dao/ReminderDao.kt
@@ -15,4 +15,7 @@
@Delete
fun delete(reminder: Reminder)
+
+ @Query("SELECT * FROM reminders WHERE type = :type")
+ fun getByType(type: String): List<Reminder>
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/firstapp/database/repository/CodeRepository.kt b/app/src/main/java/com/example/firstapp/database/repository/CodeRepository.kt
index 2d9eceb..c5d1165 100644
--- a/app/src/main/java/com/example/firstapp/database/repository/CodeRepository.kt
+++ b/app/src/main/java/com/example/firstapp/database/repository/CodeRepository.kt
@@ -17,5 +17,9 @@
fun getAllDesc() = codeDao.getAllCodesDesc()
+ @WorkerThread
+ fun getByKeyword(keyword: String): List<Code> {
+ return codeDao.getByKeyword(keyword)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/firstapp/database/repository/ReminderRepository.kt b/app/src/main/java/com/example/firstapp/database/repository/ReminderRepository.kt
index 6017712..20f90f4 100644
--- a/app/src/main/java/com/example/firstapp/database/repository/ReminderRepository.kt
+++ b/app/src/main/java/com/example/firstapp/database/repository/ReminderRepository.kt
@@ -18,4 +18,9 @@
fun delete(reminder: Reminder) {
reminderDao.delete(reminder)
}
+
+ @WorkerThread
+ fun getByType(type: String): List<Reminder> {
+ return reminderDao.getByType(type)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/firstapp/model/ExpressGroup.kt b/app/src/main/java/com/example/firstapp/model/ExpressGroup.kt
new file mode 100644
index 0000000..7122769
--- /dev/null
+++ b/app/src/main/java/com/example/firstapp/model/ExpressGroup.kt
@@ -0,0 +1,12 @@
+package com.example.firstapp.model
+
+data class ExpressGroup(
+ val stationName: String,
+ val packages: List<ExpressPackage>
+)
+
+data class ExpressPackage(
+ val company: String,
+ val trackingNumber: String,
+ val date: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/firstapp/ui/home/HomeFragment.kt b/app/src/main/java/com/example/firstapp/ui/home/HomeFragment.kt
index bf4b7ec..5cdc5e0 100644
--- a/app/src/main/java/com/example/firstapp/ui/home/HomeFragment.kt
+++ b/app/src/main/java/com/example/firstapp/ui/home/HomeFragment.kt
@@ -10,7 +10,7 @@
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.firstapp.R
-import com.example.firstapp.adapter.MyAdapter
+import com.example.firstapp.adapter.ExpressAdapter
import com.example.firstapp.core.Core
import com.example.firstapp.databinding.FragmentHomeBinding
@@ -23,45 +23,73 @@
private val binding get() = _binding!!
private lateinit var homeViewModel: HomeViewModel
- private lateinit var adapter: MyAdapter
+ private lateinit var expressAdapter: ExpressAdapter
+// private lateinit var financeAdapter: FinanceAdapter
+// private lateinit var memorialAdapter: MemorialAdapter
-
+ //onCreateView这个方法创建后被调用,通常是初始化视图组件和观察者
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
- homeViewModel =
- ViewModelProvider(this).get(HomeViewModel::class.java)
-
_binding = FragmentHomeBinding.inflate(inflater, container, false)
- val root: View = binding.root
+ return binding.root
+ }
-// val textView: TextView = binding.textHome
-// homeViewModel.text.observe(viewLifecycleOwner) {
-// textView.text = it
-// }
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ //通过 ViewModelProvider 获取 HomeViewModel 的实例,以便在视图中使用。
+ homeViewModel = ViewModelProvider(this).get(HomeViewModel::class.java)
- // 初始化适配器
- adapter = MyAdapter()
+ //调用这个方法来设置 RecyclerView用于设置 RecyclerView 的布局和适配器。
+ setupRecyclerViews()
+ //调用这个方法来观察 ViewModel 中的数据变化
+ observeViewModelData()
+ }
- // 获取数据
-// val codeList = Core.code.getAllDesc()
-
- // 使用 binding 来访问 RecyclerView
- val recyclerView: RecyclerView = binding.recyclerView
- recyclerView.layoutManager = LinearLayoutManager(requireContext()) // 使用 requireContext() 获取上下文
- recyclerView.adapter = adapter
-
- // 观察 LiveData,当数据发生变化时,更新 RecyclerView 的内容
- homeViewModel.codeList.observe(viewLifecycleOwner) { codeList ->
- adapter.submitList(codeList) // 更新 RecyclerView 的数据
- // 滚动到顶部
- recyclerView.scrollToPosition(0)
+ private fun setupRecyclerViews() {
+ // 快递列表
+ //layoutManager = LinearLayoutManager(context):设置 RecyclerView 的布局管理器为线性布局管理器,表示列表是垂直排列的。
+ //创建一个 ExpressAdapter 的实例,用于提供 RecyclerView 的数据。
+ //将适配器设置给 RecyclerView,以便显示数据。
+ binding.expressRecycler.apply {
+ layoutManager = LinearLayoutManager(context)
+ expressAdapter = ExpressAdapter()
+ adapter = expressAdapter
}
- return root
+// // 财务列表
+// binding.financeRecycler.apply {
+// layoutManager = LinearLayoutManager(context)
+// financeAdapter = FinanceAdapter()
+// adapter = financeAdapter
+// }
+//
+// // 纪念日列表
+// binding.memorialRecycler.apply {
+// layoutManager = LinearLayoutManager(context)
+// memorialAdapter = MemorialAdapter()
+// adapter = memorialAdapter
+// }
+ }
+
+ //这个方法用于观察 homeViewModel 中的 expressItems 数据。
+ private fun observeViewModelData() {
+ //当 expressItems 数据发生变化时,更新 RecyclerView 的数据。
+ homeViewModel.expressItems.observe(viewLifecycleOwner) { items ->
+ //将新的数据列表提交给适配器,以更新 RecyclerView 的显示内容。
+ expressAdapter.submitList(items)
+ }
+
+// homeViewModel.financeItems.observe(viewLifecycleOwner) { items ->
+// financeAdapter.submitList(items)
+// }
+//
+// homeViewModel.memorialItems.observe(viewLifecycleOwner) { items ->
+// memorialAdapter.submitList(items)
+// }
}
override fun onDestroyView() {
diff --git a/app/src/main/java/com/example/firstapp/ui/home/HomeViewModel.kt b/app/src/main/java/com/example/firstapp/ui/home/HomeViewModel.kt
index 630b6af..a8b15bf 100644
--- a/app/src/main/java/com/example/firstapp/ui/home/HomeViewModel.kt
+++ b/app/src/main/java/com/example/firstapp/ui/home/HomeViewModel.kt
@@ -3,34 +3,66 @@
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
import com.example.firstapp.core.Core
import com.example.firstapp.database.entity.Code
+import com.example.firstapp.model.ExpressGroup
+import com.example.firstapp.model.ExpressPackage
+import kotlinx.coroutines.launch
class HomeViewModel : ViewModel() {
- private val _text = MutableLiveData<String>().apply {
- value = "短信主页面"
- }
- val text: LiveData<String> = _text
+// private val _text = MutableLiveData<String>().apply {
+// value = "短信主页面"
+// }
+// val text: LiveData<String> = _text
+//
+// private val _codeList = MutableLiveData<List<Code>>()
+//
+// val codeList: LiveData<List<Code>> get() = _codeList
- private val _codeList = MutableLiveData<List<Code>>()
-
- val codeList: LiveData<List<Code>> get() = _codeList
+ private val _expressItems = MutableLiveData<List<ExpressGroup>>()
+ val expressItems: LiveData<List<ExpressGroup>> = _expressItems
init {
// 初始化时加载数据
- loadData()
+ // loadData()
+ loadExpressData()
}
// 加载数据的方法
- fun loadData() {
- // 获取数据,并更新 LiveData
- _codeList.value = Core.code.getAllDesc() // 假设这是获取最新的 data 的方法
- }
+// fun loadData() {
+// // 获取数据,并更新 LiveData
+// _codeList.value = Core.code.getAllDesc() // 假设这是获取最新的 data 的方法
+// }
+//
+// // 如果需要手动更新数据,可以调用这个方法
+// fun updateData() {
+// _codeList.value = Core.code.getAllDesc() // 重新获取并更新数据
+// }
- // 如果需要手动更新数据,可以调用这个方法
- fun updateData() {
- _codeList.value = Core.code.getAllDesc() // 重新获取并更新数据
+ fun loadExpressData() {
+ viewModelScope.launch {
+ // 1. 获取所有驿站类型的提醒设置
+ val stations = Core.reminder.getByType("驿站")
+
+ // 2. 按驿站分组获取包裹信息
+ val groups = stations.map { station ->
+ val packages = Core.code.getByKeyword(station.nickname).map { code ->
+ ExpressPackage(
+ company = code.name, //快递公司
+ trackingNumber = code.code, // 取件码
+ date = code.overtime //时间
+ )
+ }
+ ExpressGroup(
+ stationName = station.nickname,
+ packages = packages
+ )
+ }
+
+ _expressItems.postValue(groups)
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/location.png b/app/src/main/res/drawable/location.png
new file mode 100644
index 0000000..89a457e
--- /dev/null
+++ b/app/src/main/res/drawable/location.png
Binary files differ
diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml
index 0a6dc93..87907ab 100644
--- a/app/src/main/res/layout/fragment_home.xml
+++ b/app/src/main/res/layout/fragment_home.xml
@@ -1,30 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".ui.home.HomeFragment">
+ android:layout_height="match_parent">
-<!-- <TextView-->
-<!-- android:id="@+id/text_home"-->
-<!-- android:layout_width="match_parent"-->
-<!-- android:layout_height="wrap_content"-->
-<!-- android:layout_marginStart="8dp"-->
-<!-- android:layout_marginTop="8dp"-->
-<!-- android:layout_marginEnd="8dp"-->
-<!-- android:textAlignment="center"-->
-<!-- android:textSize="20sp"-->
-<!-- app:layout_constraintBottom_toBottomOf="parent"-->
-<!-- app:layout_constraintEnd_toEndOf="parent"-->
-<!-- app:layout_constraintStart_toStartOf="parent"-->
-<!-- app:layout_constraintTop_toTopOf="parent" />-->
-
- <androidx.recyclerview.widget.RecyclerView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/recyclerView"
+<!-- LinearLayout的作用是按照垂直或者水平方向排列其子视图-->
+<!-- CardView组件是用于实现卡片式布局-->
+<!-- RecyclerView 回收商视图 它使用适配器(Adapter)来管理数据的显示,-->
+<!-- 开发者可以根据自己的需求实现适配器的方法,将数据与视图进行绑定。-->
+<!-- 这使得 RecyclerView 能够轻松地处理各种类型的数据,并按照自定义的布局方式展示。-->
+<!-- 支持局部刷新 通知数据集变化-->
+ <LinearLayout
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:padding="8dp"/>
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="16dp">
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
+ <!-- 我的快递板块 -->
+ <androidx.cardview.widget.CardView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ app:cardCornerRadius="8dp"
+ app:cardElevation="2dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="我的快递"
+ android:textColor="#333333"
+ android:textSize="16sp"
+ android:textStyle="bold"/>
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/express_recycler"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp" />
+
+
+ </LinearLayout>
+ </androidx.cardview.widget.CardView>
+
+ <!-- 我的财务板块 -->
+ <androidx.cardview.widget.CardView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ app:cardCornerRadius="8dp"
+ app:cardElevation="2dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="16dp"
+ android:background="#E8F5E9">
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/finance_recycler"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"/>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="我的财务"
+ android:textColor="#333333"
+ android:textSize="16sp"
+ android:textStyle="bold"/>
+ </LinearLayout>
+ </androidx.cardview.widget.CardView>
+
+ <!-- 纪念日板块 -->
+ <androidx.cardview.widget.CardView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ app:cardCornerRadius="8dp"
+ app:cardElevation="2dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="16dp"
+ android:background="#FFF3E0">
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/memorial_recycler"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"/>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="纪念日"
+ android:textColor="#333333"
+ android:textSize="16sp"
+ android:textStyle="bold"/>
+ </LinearLayout>
+ </androidx.cardview.widget.CardView>
+
+ </LinearLayout>
+</ScrollView>
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_express_group.xml b/app/src/main/res/layout/item_express_group.xml
new file mode 100644
index 0000000..4a13e84
--- /dev/null
+++ b/app/src/main/res/layout/item_express_group.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginHorizontal="12dp"
+ android:layout_marginVertical="6dp"
+ app:cardCornerRadius="8dp"
+ app:cardElevation="2dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="16dp">
+
+ <!-- 驿站名称和包裹数量 -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginBottom="12dp">
+
+ <ImageView
+ android:id="@+id/iv_station_icon"
+ android:layout_width="20dp"
+ android:layout_height="20dp"
+ android:layout_gravity="center_vertical"
+ android:src="@drawable/location"/>
+
+ <TextView
+ android:id="@+id/tv_station_name"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginStart="8dp"
+ android:textSize="16sp"
+ android:textColor="#333333"/>
+
+ <TextView
+ android:id="@+id/tv_package_count"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="14sp"
+ android:textColor="#666666"/>
+ </LinearLayout>
+
+ <!-- 包裹列表 -->
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/rv_packages"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+ </LinearLayout>
+</androidx.cardview.widget.CardView>
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_express_package.xml b/app/src/main/res/layout/item_express_package.xml
new file mode 100644
index 0000000..b5389c3
--- /dev/null
+++ b/app/src/main/res/layout/item_express_package.xml
@@ -0,0 +1,46 @@
+<?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="wrap_content"
+ android:orientation="horizontal"
+ android:padding="12dp">
+
+ <ImageView
+ android:id="@+id/iv_company_logo"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_gravity="center_vertical" />
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="12dp"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/tv_company"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="#333333"
+ android:textSize="15sp" />
+
+ <TextView
+ android:id="@+id/tv_date"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:textColor="#999999"
+ android:textSize="12sp" />
+
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/tv_tracking_number"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="4dp"
+ android:textColor="#666666"
+ android:textSize="14sp" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml
index bc776fe..293c825 100644
--- a/app/src/main/res/navigation/mobile_navigation.xml
+++ b/app/src/main/res/navigation/mobile_navigation.xml
@@ -5,6 +5,8 @@
android:id="@+id/mobile_navigation"
app:startDestination="@+id/navigation_home">
+ <!-- 对应的多个片段-->
+ <!-- tools:layout="@layout/fragment_home"表示设计视图中显示的应该是fragment_home.xml的内容,而不是当前布局的内容-->
<fragment
android:id="@+id/navigation_home"
android:name="com.example.firstapp.ui.home.HomeFragment"
--
Gitblit v1.9.3