自定义下拉框实现,下拉框在spinner的下方且与spinner等宽

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>

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值