From d1d995c698e43e796b9f2932c5d0b237cb30d0c5 Mon Sep 17 00:00:00 2001 From: YANG JIANKUAN Date: Wed, 14 Oct 2026 20:21:04 -0700 Subject: [PATCH] =?UTF-8?q?fix(phone):=20PhoneDataLayout=20=E4=B8=8B?= =?UTF-8?q?=E6=8B=89=E6=94=B9=E4=B8=BA=E5=BA=95=E9=83=A8=E5=BC=B9=E5=87=BA?= =?UTF-8?q?=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 筛选面板与弹框里的 PhoneDataLayout 原用系统 Spinner,点开是贴在输入框下的下拉菜单。 SPINNER 形态改为与 PhoneFormRow 同款 XPopup 底部列表(标题取 hint),保留原取值语义: 无 hint 默认选中第一项、有 hint 为空值,筛选「重置」逻辑不变。19 个手机布局随之生效。 Refs: 禅道 Bug #623 Co-Authored-By: Claude Opus 5.5 --- .../ui/weight/phone/PhoneDataLayout.kt | 63 +++++++++++-------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneDataLayout.kt b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneDataLayout.kt index 411a105..76f747f 100644 --- a/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneDataLayout.kt +++ b/module_base/src/main/java/com/lukouguoji/module_base/ui/weight/phone/PhoneDataLayout.kt @@ -13,12 +13,10 @@ import android.widget.TextView import androidx.core.widget.doOnTextChanged import androidx.databinding.InverseBindingListener import com.lukouguoji.module_base.R -import com.lukouguoji.module_base.adapter.bindAdapter -import com.lukouguoji.module_base.adapter.bindOnSelected -import com.lukouguoji.module_base.interfaces.IOnSpinnerSelected import com.lukouguoji.module_base.ktx.formatDate import com.lukouguoji.module_base.ktx.getActivity import com.lukouguoji.module_base.util.Common +import com.lxj.xpopup.XPopup import dev.utils.app.info.KeyValue import java.util.Calendar @@ -32,7 +30,7 @@ import java.util.Calendar * |-----------|-----------|----------| * | `INPUT` | EditText | 无 | * | `DATE` | TextView(点击弹日历)| 日历 | - * | `SPINNER` | Spinner | 下箭头 | + * | `SPINNER` | TextView(点击弹底部列表,与 PhoneFormRow SELECT 同款)| 下箭头 | * * XML 用法: * ```xml @@ -58,6 +56,7 @@ class PhoneDataLayout @JvmOverloads constructor( val llContent: LinearLayout val et: EditText val tv: TextView + /** 保留以兼容布局 id;Bug #623 起 SPINNER 形态改为底部弹出列表,原生 Spinner 恒隐藏 */ val spinner: Spinner val iv: ImageView @@ -85,7 +84,7 @@ class PhoneDataLayout @JvmOverloads constructor( field = v et.hint = v tv.hint = v - bindAdapter(spinner, list, v, R.layout.item_spinner_list_14sp) + applyDefaultSelection() } var value: String = "" @@ -99,7 +98,7 @@ class PhoneDataLayout @JvmOverloads constructor( var list: List = emptyList() set(v) { field = v - bindAdapter(spinner, v, hint, R.layout.item_spinner_list_14sp) + applyDefaultSelection() applyValue() } @@ -114,7 +113,6 @@ class PhoneDataLayout @JvmOverloads constructor( field = v llContent.isEnabled = v et.isEnabled = v - spinner.isEnabled = v } init { @@ -136,13 +134,6 @@ class PhoneDataLayout @JvmOverloads constructor( } } - bindOnSelected(spinner, object : IOnSpinnerSelected { - override fun onSelected(position: Int) { - value = list.getOrNull(position)?.value ?: "" - refreshCallBack?.invoke() - } - }) - applyType() } @@ -157,6 +148,28 @@ class PhoneDataLayout @JvmOverloads constructor( } } + /** SPINNER:底部弹出列表(标题取 hint,无 hint 时取 title),选中后回写 value 并回调 */ + private val spinnerClick: (v: View) -> Unit = { + if (enable && list.isNotEmpty()) { + XPopup.Builder(context) + .asBottomList(hint.ifEmpty { title }, list.map { it.key }.toTypedArray()) { position, _ -> + value = list.getOrNull(position)?.value ?: "" + refreshCallBack?.invoke() + } + .show() + } + } + + /** + * 保持原生 Spinner 的默认取值语义:无 hint 时自动选中第一项(value 为空才补), + * 有 hint 时保持空值显示占位文字。 + */ + private fun applyDefaultSelection() { + if (type == PhoneDataLayoutType.SPINNER && hint.isEmpty() && value.isEmpty() && list.isNotEmpty()) { + value = list[0].value + } + } + private fun applyType() { when (type) { PhoneDataLayoutType.INPUT -> { @@ -179,12 +192,12 @@ class PhoneDataLayout @JvmOverloads constructor( PhoneDataLayoutType.SPINNER -> { et.visibility = GONE - tv.visibility = GONE - spinner.visibility = VISIBLE + tv.visibility = VISIBLE + spinner.visibility = GONE iv.visibility = VISIBLE iv.setImageResource(R.drawable.ic_phone_chevron_down) - llContent.setOnClickListener(null) - llContent.isClickable = false + llContent.setOnClickListener(spinnerClick) + applyDefaultSelection() } } } @@ -200,10 +213,8 @@ class PhoneDataLayout @JvmOverloads constructor( } PhoneDataLayoutType.SPINNER -> { - if (value.isNotEmpty()) { - val position = list.indexOfFirst { it.value == value } - if (position >= 0) spinner.setSelection(position) - } + // 显示选中项文案;列表里找不到就按原值显示(如后端返回的历史值),空值显示 hint + tv.text = list.firstOrNull { it.value == value }?.key ?: value } } } @@ -223,10 +234,10 @@ class PhoneDataLayout @JvmOverloads constructor( /** 重置为空值(筛选弹层「重置」按钮使用) */ fun reset() { - value = "" - if (type == PhoneDataLayoutType.SPINNER && list.isNotEmpty()) { - spinner.setSelection(if (hint.isEmpty()) list.size - 1 else list.size) - } + // 与原 Spinner 版本一致:有 hint 回到占位(空值);无 hint 选中最后一项 + value = if (type == PhoneDataLayoutType.SPINNER && hint.isEmpty() && list.isNotEmpty()) { + list.last().value + } else "" } }