1.自定义下拉框适配器
/**
* 自定义下拉框适配器
*
* @author lyh
* @date 创建时间 2024-01-19
* @since V1.0
*/
class SpinnerAdapter(
context: Context,
private val keyValueList: MutableList<KeyValueEntity>
) : ArrayAdapter<KeyValueEntity>(context, android.R.layout.simple_spinner_item, keyValueList) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = convertView ?: LayoutInflater.from(context).inflate(R.layout.custom_spinner_item, parent, false)
val textView = view.findViewById<TextView>(R.id.spinner_text)
textView.text = getItem(position)?.value ?: ""
return view
}
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
return createViewFromResource(position, convertView, parent, android.R.layout.simple_spinner_dropdown_item)
}
private fun createViewFromResource(position: Int, convertView: View?, parent: ViewGroup, resource: Int): View {
val view: TextView = convertView as? TextView ?: LayoutInflater.from(context)
.inflate(resource, parent, false) as TextView
val list = keyValueList[position]
view.tag = list.key
view.text = list.value
return view
}
}
2.键值对实体
/**
* 键值对实体
*
* @author lyh
* @date 创建时间 2023-09-08
* @since V1.0
*/
data class KeyValueEntity(
val key: String,
val value: String
) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString() ?: "",
parcel.readString() ?: ""
)
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(key)
parcel.writeString(value)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<KeyValueEntity> {
override fun createFromParcel(parcel: Parcel): KeyValueEntity {
return KeyValueEntity(parcel)
}
override fun newArray(size: Int): Array<KeyValueEntity?> {
return arrayOfNulls(size)
}
}
}
3.弹出的下拉框显示
3.1后台页面
/**
* 弹出的下拉框显示
*
* @author lyh
* @date 创建时间 2024-01-19
* @since V1.0
*/
class CustomPopupWindow(
private val activityContext: Context,
private val data: List<KeyValueEntity>,
private val spinnerIdentifier: String,
private val listener: OnItemSelectedListener
) : PopupWindow(activityContext) {
private var selectedEntity: KeyValueEntity? = null
init {
contentView =
LayoutInflater.from(activityContext).inflate(R.layout.custom_popup_window, null)
width = ViewGroup.LayoutParams.WRAP_CONTENT
height = ViewGroup.LayoutParams.WRAP_CONTENT
isFocusable = true
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
setUpListView()
}
private fun setUpListView() {
val listView = contentView.findViewById<ListView>(R.id.popupListView)
// 只取出 data 中的 value
val values = data.map { it.value }.toTypedArray()
listView.adapter = ArrayAdapter(activityContext, R.layout.custom_spinner_item, values)
listView.setOnItemClickListener { _, _, position, _ ->
// 保存选中的 KeyValueEntity
selectedEntity = data[position]
// 触发回调,传递标识和选中的项
listener.onItemSelected(spinnerIdentifier, position, selectedEntity)
dismiss() // 关闭 PopupWindow
}
}
fun showPopup(anchor: View) {
val location = IntArray(2)
anchor.getLocationInWindow(location)
showAsDropDown(
anchor,
0, // offsetX
0 // offsetY
)
}
fun setPopupWidth(width: Int) {
this.width = width
}
interface OnItemSelectedListener {
fun onItemSelected(spinnerIdentifier: String, position: Int, selectedEntity: KeyValueEntity?)
}
}
3.2UI页面
(1)custom_popup_window.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ListView
android:id="@+id/popupListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white" />
</LinearLayout>
(2)custom_spinner_item.xml
<!-- 下拉框显示的内容 -->
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/spinner_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:textSize="16sp"
android:textColor="#000000" />
4.具体使用
class DataActivity : BaseActivity(), CustomPopupWindow.OnItemSelectedListener {
private lateinit var spinner: Spinner
private var dataList = mutableListOf<KeyValueEntity>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_data)
spinner = findViewById(R.id.spinner)
// 创建适配器
val spinnerAdapter = SpinnerAdapter(this, dataList)
// 将适配器设置到 Spinner 上
spinner.adapter = spinnerAdapter
spinner.setSelection(0, false)
val taskPopupWindow = CustomPopupWindow(this, dataList, "spinner_data", this)
spinner.setOnTouchListener { _, _ ->
val width = spinner.width
taskPopupWindow.setPopupWidth(width)
// 显示自定义的 PopupWindow
taskPopupWindow.showPopup(spinner)
// 返回 true,表示已经处理了触摸事件
true
}
}
override fun onItemSelected(
spinnerIdentifier: String,
position: Int,
selectedEntity: KeyValueEntity?
) {
when (spinnerIdentifier) {
"spinner_data" -> {
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:orientation="vertical"
tools:context=".data_count.DataActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="734dp"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="342dp"
android:layout_height="40dp"
android:layout_marginStart="30dp"
android:background="@drawable/edit_text_5">
<Spinner
android:id="@+id/spinner"
android:layout_width="342dp"
android:layout_height="match_parent"
style="@style/SpinnerTextStyle"/>
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>