refactor(fragment): DbInspectFragment 改用嵌套 RecyclerView 展示字段,优化已删除记录视觉样式
This commit is contained in:
@@ -244,15 +244,27 @@ class DbViewModel : ViewModel() {
|
|||||||
const val DB_INSPECT_PAGE_SIZE = 50
|
const val DB_INSPECT_PAGE_SIZE = 50
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单条数据库记录的展示模型
|
||||||
|
* @param isDel 是否已逻辑删除
|
||||||
|
* @param fields 字段名-值对列表,按顺序排列
|
||||||
|
* @param columnsPerRow 每行显示的列数,默认 3;槽位表传 1 保持单列
|
||||||
|
*/
|
||||||
|
data class DbRecord(
|
||||||
|
val isDel: Boolean,
|
||||||
|
val fields: List<Pair<String, String>>,
|
||||||
|
val columnsPerRow: Int = 3
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据库调试页面 UI 状态
|
* 数据库调试页面 UI 状态
|
||||||
* @param items 当前已加载的记录列表,Pair.first=是否逻辑删除,Pair.second=格式化文本
|
* @param items 当前已加载的记录列表
|
||||||
* @param totalCount 当前过滤条件下的总记录数
|
* @param totalCount 当前过滤条件下的总记录数
|
||||||
* @param hasMore 是否还有更多数据可加载
|
* @param hasMore 是否还有更多数据可加载
|
||||||
* @param isLoading 是否正在加载(首次加载或加载更多)
|
* @param isLoading 是否正在加载(首次加载或加载更多)
|
||||||
*/
|
*/
|
||||||
data class DbInspectUiState(
|
data class DbInspectUiState(
|
||||||
val items: List<Pair<Boolean, String>> = emptyList(),
|
val items: List<DbRecord> = emptyList(),
|
||||||
val totalCount: Int = 0,
|
val totalCount: Int = 0,
|
||||||
val hasMore: Boolean = false,
|
val hasMore: Boolean = false,
|
||||||
val isLoading: Boolean = false
|
val isLoading: Boolean = false
|
||||||
@@ -303,22 +315,25 @@ class DbViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行分页查询,返回格式化后的列表和总记录数
|
* 执行分页查询,返回 DbRecord 列表和总记录数
|
||||||
*/
|
*/
|
||||||
private suspend fun queryPage(
|
private suspend fun queryPage(
|
||||||
tableIndex: Int,
|
tableIndex: Int,
|
||||||
showDel: Boolean,
|
showDel: Boolean,
|
||||||
offset: Int
|
offset: Int
|
||||||
): Pair<List<Pair<Boolean, String>>, Int> {
|
): Pair<List<DbRecord>, Int> {
|
||||||
val limit = DB_INSPECT_PAGE_SIZE
|
val limit = DB_INSPECT_PAGE_SIZE
|
||||||
return when (tableIndex) {
|
return when (tableIndex) {
|
||||||
0 -> {
|
0 -> {
|
||||||
val total = rep.countCookFoodAll(showDel)
|
val total = rep.countCookFoodAll(showDel)
|
||||||
val rows = rep.getCookFoodPaged(showDel, limit, offset).map { e ->
|
val rows = rep.getCookFoodPaged(showDel, limit, offset).map { e ->
|
||||||
(e.isDel == 1) to fmt(
|
DbRecord(
|
||||||
"id" to e.id, "foodId" to e.foodId, "foodName" to e.foodName,
|
isDel = e.isDel == 1,
|
||||||
"canteenId" to e.canteenId, "foodWeight" to e.foodWeight, "cookMode" to e.cookMode,
|
fields = listOf(
|
||||||
"dinnerType" to e.dinnerType, "isDel" to e.isDel, "createTime" to e.createTime
|
"id" to "${e.id}", "foodId" to "${e.foodId}", "foodName" to "${e.foodName}",
|
||||||
|
"canteenId" to "${e.canteenId}", "foodWeight" to "${e.foodWeight}", "cookMode" to "${e.cookMode}",
|
||||||
|
"dinnerType" to "${e.dinnerType}", "isDel" to "${e.isDel}", "createTime" to "${e.createTime}"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
rows to total
|
rows to total
|
||||||
@@ -326,12 +341,15 @@ class DbViewModel : ViewModel() {
|
|||||||
1 -> {
|
1 -> {
|
||||||
val total = rep.countCookFoodGoodsAll(showDel)
|
val total = rep.countCookFoodGoodsAll(showDel)
|
||||||
val rows = rep.getCookFoodGoodsPaged(showDel, limit, offset).map { e ->
|
val rows = rep.getCookFoodGoodsPaged(showDel, limit, offset).map { e ->
|
||||||
(e.isDel == 1) to fmt(
|
DbRecord(
|
||||||
"id" to e.id, "pid" to e.pid, "goodsId" to e.goodsId,
|
isDel = e.isDel == 1,
|
||||||
"goodsName" to e.goodsName, "foodId" to e.foodId, "materialType" to e.materialType,
|
fields = listOf(
|
||||||
"relateionType" to e.relateionType, "allEdible" to e.allEdible, "useWeight" to e.useWeight,
|
"id" to "${e.id}", "pid" to "${e.pid}", "goodsId" to "${e.goodsId}",
|
||||||
"sort" to e.sort, "zjmCode" to e.zjmCode, "materId" to e.materId,
|
"goodsName" to "${e.goodsName}", "foodId" to "${e.foodId}", "materialType" to "${e.materialType}",
|
||||||
"isDel" to e.isDel, "createTime" to e.createTime
|
"relateionType" to "${e.relateionType}", "allEdible" to "${e.allEdible}", "useWeight" to "${e.useWeight}",
|
||||||
|
"sort" to "${e.sort}", "zjmCode" to "${e.zjmCode}", "materId" to "${e.materId}",
|
||||||
|
"isDel" to "${e.isDel}", "createTime" to "${e.createTime}"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
rows to total
|
rows to total
|
||||||
@@ -339,11 +357,14 @@ class DbViewModel : ViewModel() {
|
|||||||
2 -> {
|
2 -> {
|
||||||
val total = rep.countSeasoningAll(showDel)
|
val total = rep.countSeasoningAll(showDel)
|
||||||
val rows = rep.getSeasoningPaged(showDel, limit, offset).map { e ->
|
val rows = rep.getSeasoningPaged(showDel, limit, offset).map { e ->
|
||||||
(e.isDel == 1) to fmt(
|
DbRecord(
|
||||||
"id" to e.id, "goodsId" to e.goodsId, "goodsName" to e.goodsName,
|
isDel = e.isDel == 1,
|
||||||
"sort" to e.sort, "materialType" to e.materialType, "useWeight" to e.useWeight,
|
fields = listOf(
|
||||||
"zjmCode" to e.zjmCode, "materId" to e.materId, "isDel" to e.isDel,
|
"id" to "${e.id}", "goodsId" to "${e.goodsId}", "goodsName" to "${e.goodsName}",
|
||||||
"createTime" to e.createTime
|
"sort" to "${e.sort}", "materialType" to "${e.materialType}", "useWeight" to "${e.useWeight}",
|
||||||
|
"zjmCode" to "${e.zjmCode}", "materId" to "${e.materId}", "isDel" to "${e.isDel}",
|
||||||
|
"createTime" to "${e.createTime}"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
rows to total
|
rows to total
|
||||||
@@ -351,23 +372,21 @@ class DbViewModel : ViewModel() {
|
|||||||
3 -> {
|
3 -> {
|
||||||
val total = rep.countSlotAll()
|
val total = rep.countSlotAll()
|
||||||
val rows = rep.getSlotPaged(limit, offset).map { e ->
|
val rows = rep.getSlotPaged(limit, offset).map { e ->
|
||||||
false to "deviceId: ${e.deviceId}\naddress: ${e.address}\ngoodsId: ${e.goodsId}\ngoodsName: ${e.goodsName}"
|
DbRecord(
|
||||||
|
isDel = false,
|
||||||
|
fields = listOf(
|
||||||
|
"deviceId" to e.deviceId, "address" to "${e.address}",
|
||||||
|
"goodsId" to e.goodsId, "goodsName" to e.goodsName
|
||||||
|
),
|
||||||
|
columnsPerRow = 1 // 槽位表字段少,保持单列显示
|
||||||
|
)
|
||||||
}
|
}
|
||||||
rows to total
|
rows to total
|
||||||
}
|
}
|
||||||
else -> emptyList<Pair<Boolean, String>>() to 0
|
else -> emptyList<DbRecord>() to 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 将字段列表格式化为每行 3 个的紧凑布局
|
|
||||||
* 格式:key: value | key: value | key: value
|
|
||||||
*/
|
|
||||||
private fun fmt(vararg fields: Pair<String, Any?>): String =
|
|
||||||
fields.toList().chunked(3).joinToString("\n") { row ->
|
|
||||||
row.joinToString(" | ") { (k, v) -> "$k: ${v ?: "null"}" }
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// viewModelScope.launch {
|
// viewModelScope.launch {
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.RadioButton
|
import android.widget.RadioButton
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.cardview.widget.CardView
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.shuwei.dish.match.R
|
import com.shuwei.dish.match.R
|
||||||
@@ -22,8 +24,8 @@ import kotlinx.coroutines.launch
|
|||||||
/**
|
/**
|
||||||
* 数据库调试查看页面
|
* 数据库调试查看页面
|
||||||
* 支持按表切换、isDel 过滤开关、分页加载(每页 50 条)
|
* 支持按表切换、isDel 过滤开关、分页加载(每页 50 条)
|
||||||
|
* 菜品/食材/调料表每行 3 列等宽显示字段,槽位表保持单列
|
||||||
* 已逻辑删除(isDel=1)的记录以灰色文字 + 半透明卡片区分
|
* 已逻辑删除(isDel=1)的记录以灰色文字 + 半透明卡片区分
|
||||||
* 槽位表无 isDel 字段,切换到该 Tab 时自动隐藏 isDel 控件
|
|
||||||
*/
|
*/
|
||||||
class DbInspectFragment : BaseFragment<FragmentDbInspectBinding>() {
|
class DbInspectFragment : BaseFragment<FragmentDbInspectBinding>() {
|
||||||
|
|
||||||
@@ -35,10 +37,7 @@ class DbInspectFragment : BaseFragment<FragmentDbInspectBinding>() {
|
|||||||
/** 是否显示已删除记录(槽位表忽略此参数) */
|
/** 是否显示已删除记录(槽位表忽略此参数) */
|
||||||
private var showDel = true
|
private var showDel = true
|
||||||
|
|
||||||
/**
|
/** 防止代码中设置 Switch 状态时误触发监听器 */
|
||||||
* 防止在代码中设置 Switch 状态时触发监听器,
|
|
||||||
* 例如切换回非槽位 Tab 时恢复 Switch 状态
|
|
||||||
*/
|
|
||||||
private var ignoreSwitch = false
|
private var ignoreSwitch = false
|
||||||
|
|
||||||
private val adapter = DbRecordAdapter()
|
private val adapter = DbRecordAdapter()
|
||||||
@@ -83,7 +82,7 @@ class DbInspectFragment : BaseFragment<FragmentDbInspectBinding>() {
|
|||||||
loadFirstPage()
|
loadFirstPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 刷新按钮:重新加载第一页
|
// 刷新按钮
|
||||||
binding.tvRefresh.setOnClickListener { loadFirstPage() }
|
binding.tvRefresh.setOnClickListener { loadFirstPage() }
|
||||||
|
|
||||||
// 加载更多按钮
|
// 加载更多按钮
|
||||||
@@ -98,30 +97,23 @@ class DbInspectFragment : BaseFragment<FragmentDbInspectBinding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化 Tab 样式并加载默认表
|
// 初始化样式并加载
|
||||||
updateTabStyles()
|
updateTabStyles()
|
||||||
updateDelControlsVisibility()
|
updateDelControlsVisibility()
|
||||||
binding.vTabIndicator.post { moveIndicator(currentTableIndex) }
|
binding.vTabIndicator.post { moveIndicator(currentTableIndex) }
|
||||||
loadFirstPage()
|
loadFirstPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 重新从第一页开始加载当前表数据 */
|
|
||||||
private fun loadFirstPage() {
|
private fun loadFirstPage() {
|
||||||
currentActivity.appViewModel.loadDbInspect(currentTableIndex, showDel)
|
currentActivity.appViewModel.loadDbInspect(currentTableIndex, showDel)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据 UI 状态更新计数文字、加载更多按钮和列表
|
|
||||||
*/
|
|
||||||
private fun renderState(state: DbViewModel.DbInspectUiState) {
|
private fun renderState(state: DbViewModel.DbInspectUiState) {
|
||||||
// 计数文字
|
|
||||||
binding.tvCount.text = when {
|
binding.tvCount.text = when {
|
||||||
state.isLoading && state.items.isEmpty() -> "加载中..."
|
state.isLoading && state.items.isEmpty() -> "加载中..."
|
||||||
state.hasMore -> "已加载 ${state.items.size} / 共 ${state.totalCount} 条"
|
state.hasMore -> "已加载 ${state.items.size} / 共 ${state.totalCount} 条"
|
||||||
else -> "共 ${state.totalCount} 条"
|
else -> "共 ${state.totalCount} 条"
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载更多按钮:有更多数据时显示,加载中时显示"加载中..."并禁用点击
|
|
||||||
when {
|
when {
|
||||||
state.isLoading && state.hasMore -> {
|
state.isLoading && state.hasMore -> {
|
||||||
binding.tvLoadMore.visible()
|
binding.tvLoadMore.visible()
|
||||||
@@ -135,13 +127,11 @@ class DbInspectFragment : BaseFragment<FragmentDbInspectBinding>() {
|
|||||||
}
|
}
|
||||||
else -> binding.tvLoadMore.gone()
|
else -> binding.tvLoadMore.gone()
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter.setData(state.items)
|
adapter.setData(state.items)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 槽位表(index=3)没有 isDel 字段,切换到该 Tab 时隐藏 isDel 相关控件;
|
* 槽位表无 isDel 字段,切换到时隐藏相关控件;切换回其他 Tab 时恢复
|
||||||
* 切换回其他 Tab 时恢复,并同步 Switch 状态
|
|
||||||
*/
|
*/
|
||||||
private fun updateDelControlsVisibility() {
|
private fun updateDelControlsVisibility() {
|
||||||
val isSlot = currentTableIndex == 3
|
val isSlot = currentTableIndex == 3
|
||||||
@@ -151,16 +141,12 @@ class DbInspectFragment : BaseFragment<FragmentDbInspectBinding>() {
|
|||||||
} else {
|
} else {
|
||||||
binding.tvDelLabel.visible()
|
binding.tvDelLabel.visible()
|
||||||
binding.swShowDel.visible()
|
binding.swShowDel.visible()
|
||||||
// 恢复 Switch 显示状态(防止误触发监听器)
|
|
||||||
ignoreSwitch = true
|
ignoreSwitch = true
|
||||||
binding.swShowDel.isChecked = showDel
|
binding.swShowDel.isChecked = showDel
|
||||||
ignoreSwitch = false
|
ignoreSwitch = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新所有 Tab 的文字颜色和加粗状态
|
|
||||||
*/
|
|
||||||
private fun updateTabStyles() {
|
private fun updateTabStyles() {
|
||||||
tabButtons.forEachIndexed { index, btn ->
|
tabButtons.forEachIndexed { index, btn ->
|
||||||
val selected = index == currentTableIndex
|
val selected = index == currentTableIndex
|
||||||
@@ -169,20 +155,12 @@ class DbInspectFragment : BaseFragment<FragmentDbInspectBinding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 将下方指示条平移到选中 Tab 的正下方(150ms 动画)
|
|
||||||
*/
|
|
||||||
private fun moveIndicator(index: Int) {
|
private fun moveIndicator(index: Int) {
|
||||||
val btn = tabButtons.getOrNull(index) ?: return
|
val btn = tabButtons.getOrNull(index) ?: return
|
||||||
val tabWidth = btn.width.toFloat()
|
val tabWidth = btn.width.toFloat()
|
||||||
val indicatorWidth = tabWidth / 2f
|
val indicatorWidth = tabWidth / 2f
|
||||||
val indicatorX = btn.x + (tabWidth - indicatorWidth) / 2f
|
val indicatorX = btn.x + (tabWidth - indicatorWidth) / 2f
|
||||||
|
binding.vTabIndicator.animate().translationX(indicatorX).setDuration(150).start()
|
||||||
binding.vTabIndicator.animate()
|
|
||||||
.translationX(indicatorX)
|
|
||||||
.setDuration(150)
|
|
||||||
.start()
|
|
||||||
|
|
||||||
binding.vTabIndicator.post {
|
binding.vTabIndicator.post {
|
||||||
val lp = binding.vTabIndicator.layoutParams
|
val lp = binding.vTabIndicator.layoutParams
|
||||||
lp.width = indicatorWidth.toInt()
|
lp.width = indicatorWidth.toInt()
|
||||||
@@ -190,14 +168,14 @@ class DbInspectFragment : BaseFragment<FragmentDbInspectBinding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- 内部 Adapter ----
|
// ---- 外层 Adapter:每条数据库记录对应一个 CardView ----
|
||||||
|
|
||||||
/** 数据库记录列表适配器 */
|
/** 外层列表适配器,每个 item 内嵌一个 GridLayoutManager 的 RecyclerView 展示字段 */
|
||||||
private inner class DbRecordAdapter : RecyclerView.Adapter<DbRecordAdapter.VH>() {
|
private inner class DbRecordAdapter : RecyclerView.Adapter<DbRecordAdapter.VH>() {
|
||||||
|
|
||||||
private val data = mutableListOf<Pair<Boolean, String>>()
|
private val data = mutableListOf<DbViewModel.DbRecord>()
|
||||||
|
|
||||||
fun setData(list: List<Pair<Boolean, String>>) {
|
fun setData(list: List<DbViewModel.DbRecord>) {
|
||||||
data.clear()
|
data.clear()
|
||||||
data.addAll(list)
|
data.addAll(list)
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
@@ -210,20 +188,57 @@ class DbInspectFragment : BaseFragment<FragmentDbInspectBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: VH, position: Int) {
|
override fun onBindViewHolder(holder: VH, position: Int) {
|
||||||
val (isDeleted, content) = data[position]
|
val record = data[position]
|
||||||
holder.tvContent.text = content
|
|
||||||
// isDel=1 的记录用灰色标识,正常记录用深色
|
if (record.isDel) {
|
||||||
holder.tvContent.setTextColor(
|
// 已删除:浅红背景 + 左侧红色标记条 + 文字颜色正常(深色可读)
|
||||||
if (isDeleted) Color.parseColor("#BBBBBB") else Color.parseColor("#333333")
|
holder.card.setCardBackgroundColor(Color.parseColor("#FFF3F3"))
|
||||||
)
|
holder.vDelMark.visibility = View.VISIBLE
|
||||||
// 已删除记录卡片略微透明
|
} else {
|
||||||
holder.itemView.alpha = if (isDeleted) 0.6f else 1.0f
|
// 正常记录:白色背景,隐藏标记条
|
||||||
|
holder.card.setCardBackgroundColor(Color.WHITE)
|
||||||
|
holder.vDelMark.visibility = View.GONE
|
||||||
|
}
|
||||||
|
val textColor = if (record.isDel) Color.parseColor("#C62828") else Color.parseColor("#333333")
|
||||||
|
|
||||||
|
// 每次绑定时重新设置 GridLayoutManager 列数(槽位表为 1,其余为 3)
|
||||||
|
holder.rvFields.layoutManager = GridLayoutManager(holder.rvFields.context, record.columnsPerRow)
|
||||||
|
holder.rvFields.adapter = DbFieldAdapter(record.fields, textColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount() = data.size
|
override fun getItemCount() = data.size
|
||||||
|
|
||||||
inner class VH(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
inner class VH(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
val tvContent: TextView = itemView.findViewById(R.id.tvContent)
|
val card: CardView = itemView.findViewById(R.id.cardRecord)
|
||||||
|
val vDelMark: View = itemView.findViewById(R.id.vDelMark)
|
||||||
|
val rvFields: RecyclerView = itemView.findViewById(R.id.rvFields)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- 内层 Adapter:每个字段对应一个 TextView,垂直显示字段名和值 ----
|
||||||
|
|
||||||
|
/** 内层字段适配器,每个 item 为单个 TextView,显示格式:字段名\n字段值 */
|
||||||
|
private inner class DbFieldAdapter(
|
||||||
|
private val fields: List<Pair<String, String>>,
|
||||||
|
private val textColor: Int
|
||||||
|
) : RecyclerView.Adapter<DbFieldAdapter.VH>() {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
|
||||||
|
val view = LayoutInflater.from(parent.context)
|
||||||
|
.inflate(R.layout.list_item_db_field, parent, false)
|
||||||
|
return VH(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: VH, position: Int) {
|
||||||
|
val (key, value) = fields[position]
|
||||||
|
holder.tvField.text = "$key\n$value"
|
||||||
|
holder.tvField.setTextColor(textColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount() = fields.size
|
||||||
|
|
||||||
|
inner class VH(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
val tvField: TextView = itemView.findViewById(R.id.tvField)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/tvField"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="10sp"
|
||||||
|
android:fontFamily="monospace"
|
||||||
|
android:gravity="start"
|
||||||
|
android:paddingBottom="4dp" />
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/cardRecord"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
@@ -9,13 +10,28 @@
|
|||||||
app:cardElevation="1dp"
|
app:cardElevation="1dp"
|
||||||
app:cardBackgroundColor="#FFFFFF">
|
app:cardBackgroundColor="#FFFFFF">
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:id="@+id/tvContent"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="10dp"
|
android:orientation="horizontal">
|
||||||
android:textSize="11sp"
|
|
||||||
android:lineSpacingMultiplier="1.3"
|
<!-- 已删除标记条:isDel=1 时显示红色左边框 -->
|
||||||
android:fontFamily="monospace" />
|
<View
|
||||||
|
android:id="@+id/vDelMark"
|
||||||
|
android:layout_width="4dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#E53935"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<!-- 字段由内层 RecyclerView(GridLayoutManager)填充 -->
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvFields"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:nestedScrollingEnabled="false"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:clipToPadding="false" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|||||||
Reference in New Issue
Block a user